extends CharacterBody3D class_name PlayerCharacter @export_group("Dash Mechanics") @export var dash_speed: float = 15.0 # Скорость игрока во время рывка @export var dash_duration: float = 0.45 # Длительность рывка в секундах @export var dash_cooldown: float = 2.0 # Перезарядка дэша (в секундах) var is_dashing: bool = false var dash_timer: float = 0.0 var dash_cooldown_timer: float = 0.0 var dash_direction: Vector3 = Vector3.ZERO @onready var player_camera: Camera3D = %Camera # Ссылка на камеру (убедись, что %Camera есть в сцене) var normal_fov: float = 75.0 # Стандартный угол обзора @export_group("Movement variables") var moveSpeed : float var moveAccel : float var moveDeccel : float var desiredMoveSpeed : float @export var desiredMoveSpeedCurve : Curve @export var maxSpeed : float @export var inAirMoveSpeedCurve : Curve var inputDirection : Vector2 var moveDirection : Vector3 @export var hitGroundCooldown : float #amount of time the character keep his accumulated speed before losing it (while being on ground) var hitGroundCooldownRef : float @export var bunnyHopDmsIncre : float #bunny hopping desired move speed incrementer @export var autoBunnyHop : bool = false var lastFramePosition : Vector3 var lastFrameVelocity : Vector3 var wasOnFloor : bool var walkOrRun : String = "WalkState" #keep in memory if play char was walking or running before being in the air #for crouch visible changes @export var baseHitboxHeight : float @export var baseModelHeight : float @export var heightChangeSpeed : float @export_group("Crouch variables") @export var crouchSpeed : float @export var crouchAccel : float @export var crouchDeccel : float @export var continiousCrouch : bool = false #if true, doesn't need to keep crouch button on to crouch @export var crouchHitboxHeight : float @export var crouchModelHeight : float @export_group("Walk variables") @export var walkSpeed : float @export var walkAccel : float @export var walkDeccel : float @export_group("Run variables") @export var runSpeed : float @export var runAccel : float @export var runDeccel : float @export var continiousRun : bool = false #if true, doesn't need to keep run button on to run @export_group("Jump variables") @export var jumpHeight : float @export var jumpTimeToPeak : float @export var jumpTimeToFall : float @onready var jumpVelocity : float = (2.0 * jumpHeight) / jumpTimeToPeak @export_group("Jump variables continuation") # Разделили одинаковые группы, чтобы Godot не ругался @export var jumpCooldown : float var jumpCooldownRef : float @export var nbJumpsInAirAllowed : int var nbJumpsInAirAllowedRef : int var jumpBuffOn : bool = false var bufferedJump : bool = false @export var coyoteJumpCooldown : float var coyoteJumpCooldownRef : float var coyoteJumpOn : bool = false @export_range(0.1, 1.0, 0.05) var inAirInputMultiplier: float = 1.0 @export_group("Gravity variables") @onready var jumpGravity : float = (-2.0 * jumpHeight) / (jumpTimeToPeak * jumpTimeToPeak) @onready var fallGravity : float = (-2.0 * jumpHeight) / (jumpTimeToFall * jumpTimeToFall) @export_group("Keybind variables") @export var moveForwardAction : String = "" @export var moveBackwardAction : String = "" @export var moveLeftAction : String = "" @export var moveRightAction : String = "" @export var runAction : String = "" @export var crouchAction : String = "" @export var jumpAction : String = "" #references variables @onready var camHolder : Node3D = $CameraHolder @onready var model : MeshInstance3D = $Model @onready var hitbox : CollisionShape3D = $Hitbox @onready var stateMachine : Node = %StateMachine @onready var hud : CanvasLayer = $HUD @onready var ceilingCheck : RayCast3D = $Raycasts/CeilingCheck @onready var floorCheck : RayCast3D = $Raycasts/FloorCheck # --- МЕХАНИКА БОНУСНОГО УСКОРЕНИЯ (АДРЕНАЛИН) --- var is_speed_boosted: bool = false func activate_speed_boost() -> void: if is_speed_boosted: return # Защита от повторного накладывания эффекта is_speed_boosted = true print("[ИГРОК] Адреналин подействовал на ноги!") # 1. Запоминаем твои текущие настройки скорости из инспектора var old_walk: float = walkSpeed var old_run: float = runSpeed # 2. Принудительно разгоняем базовые переменные, которые стейт-машина читает каждый кадр! walkSpeed = old_walk * 1.8 runSpeed = old_run * 1.8 # Сразу толкаем текущую скорость moveSpeed вперед, чтобы разгон пошел без задержки в один кадр if "walkOrRun" in self and walkOrRun == "RunState": moveSpeed = runSpeed else: moveSpeed = walkSpeed # Визуальный эффект: плавно растягиваем камеру (FOV) на +20 градусов для сочности if player_camera: var tween = create_tween() tween.tween_property(player_camera, "fov", normal_fov + 20.0, 0.2) # 3. ВРЕМЯ ДЕЙСТВИЯ: Бонус работает ровно 5 секунд await get_tree().create_timer(5.0).timeout # 4. СБРОС: Возвращаем базовые скорости в норму walkSpeed = old_walk runSpeed = old_run if "walkOrRun" in self and walkOrRun == "RunState": moveSpeed = runSpeed else: moveSpeed = walkSpeed # Плавно возвращаем камеру назад if player_camera: var tween = create_tween() tween.tween_property(player_camera, "fov", normal_fov, 0.3) is_speed_boosted = false print("[ИГРОК] Действие адреналина закончилось. Скорость в норме.") # НАЙДИ ЭТУ ФУНКЦИЮ ВНУТРИ СKРИПТА PlayerCharacter.gd И ЗАМЕНИ ЕЁ: func _ready(): # Твой старый оригинальный код ready из ассета... moveSpeed = walkSpeed moveAccel = walkAccel moveDeccel = walkDeccel hitGroundCooldownRef = hitGroundCooldown jumpCooldownRef = jumpCooldown nbJumpsInAirAllowedRef = nbJumpsInAirAllowed coyoteJumpCooldownRef = coyoteJumpCooldown # --- НАШЕ НОВОЕ ДОБАВЛЕНИЕ: ЗАБИРАЕМ КЭШ СНАРЯЖЕНИЯ И ХП НА НОВОЙ КАРТЕ --- # Даем ассету фору в один кадр, чтобы его WeaponManager успел создаться, # прежде чем мы принудительно перезапишем его инвентарь данными с прошлого уровня await get_tree().create_timer(0.1).timeout if GameTransfer: GameTransfer.load_player_data(self) # ------------------------------------------------------------------------- func _process(_delta: float): displayProperties() func _physics_process(_delta : float): # 1. Отсчет кулдауна перезарядки дэша if dash_cooldown_timer > 0: dash_cooldown_timer -= _delta # 2. ЕСЛИ ИДЕТ ДЭШ: двигаем игрока силой кода if is_dashing: dash_timer -= _delta if dash_timer <= 0: is_dashing = false # Возвращаем FOV камеры обратно if player_camera: var tween = create_tween() tween.tween_property(player_camera, "fov", normal_fov, 0.15) # ВКЛЮЧАЕМ СТEЙТ-МАШИНУ ОБРАТНО if stateMachine: stateMachine.process_mode = Node.PROCESS_MODE_INHERIT else: # Принудительно толкаем персонажа со скоростью дэша velocity.x = dash_direction.x * dash_speed velocity.z = dash_direction.z * dash_speed # Применяем перемещение и ВЫХОДИМ, полностью блокируя ходьбу ассета во время рывка modifyPhysicsProperties() move_and_slide() return # 3. ПРОВЕРКА НАЖАТИЯ КНОПКИ ДЭША if Input.is_action_just_pressed("dash") and dash_cooldown_timer <= 0 and not is_dashing: # Если игрок бежит — берем направление moveDirection, если стоит — направление камеры var final_dir = moveDirection if final_dir == Vector3.ZERO: final_dir = -camHolder.global_transform.basis.z final_dir.y = 0 # Чтобы не летать вверх/вниз final_dir = final_dir.normalized() # Запускаем дэш is_dashing = true dash_timer = dash_duration dash_cooldown_timer = dash_cooldown dash_direction = final_dir # Эффект наплыва камеры (FOV) if player_camera: var tween = create_tween() tween.tween_property(player_camera, "fov", normal_fov + 15.0, 0.1) # ВЫКЛЮЧАЕМ СТEЙТ-МАШИНУ НА ВРЕМЯ РЫВКА, чтобы она не сбивала скорость! if stateMachine: stateMachine.process_mode = Node.PROCESS_MODE_DISABLED # Стандартная физика ходьбы из твоего ассета (работает, когда дэша нет) modifyPhysicsProperties() move_and_slide() # Проверяем нажатие на кнопку дэша (кнопка "dash" должна быть настроена в Input Map) if Input.is_action_just_pressed("dash") and dash_cooldown_timer <= 0 and not is_dashing: # Если игрок бежит — дэшимся в сторону бега, если стоит — строго вперед по взгляду камеры var final_dir = moveDirection if final_dir == Vector3.ZERO: final_dir = -camHolder.global_transform.basis.z # Берем направление взгляда камеры final_dir.y = 0 # Обнуляем вертикальную ось, чтобы игрок не улетал в небо или под пол final_dir = final_dir.normalized() # Активируем рывок is_dashing = true dash_timer = dash_duration dash_cooldown_timer = dash_cooldown dash_direction = final_dir # Эффект скорости: плавно увеличиваем угол обзора (FOV) камеры на +15 градусов if player_camera: var tween = create_tween() tween.tween_property(player_camera, "fov", normal_fov + 15.0, 0.1) # Стандартная физика ассета (вызывается, только когда мы не в дэше) modifyPhysicsProperties() move_and_slide() func displayProperties(): if hud != null: hud.displayCurrentState(stateMachine.currStateName) hud.displayCurrentDirection(moveDirection) hud.displayDesiredMoveSpeed(desiredMoveSpeed) hud.displayVelocity(velocity.length()) hud.displayNbJumpsInAirAllowed(nbJumpsInAirAllowed) func modifyPhysicsProperties(): lastFramePosition = position lastFrameVelocity = velocity wasOnFloor = !is_on_floor() func gravityApply(delta : float): if !is_on_floor(): if velocity.y >= 0.0: velocity.y += jumpGravity * delta elif velocity.y < 0.0: velocity.y += fallGravity * delta