Files
gaim/Resources/Players/player.gd
T

284 lines
8.1 KiB
GDScript

extends CharacterBody3D
class_name Player
var speed = 5.0
const JUMP_VELOCITY = 12
const throw_strength = 50
var speeds = [5.0, 2.5, 1.5, 1.0]
var animation_player_speeds = [1.5, 1.0, 0.7, 0.5]
var counter_speed := 0
enum PlayerMode {
NORMAL,
AIM
}
var mode = PlayerMode.NORMAL
var xform : Transform3D
var grabbed_item : Grabbable_Object
var dialogueActive : bool
var weight: float = 5.0
# --- Camera ---
var camera_pitch := 0.0
var zoom := 5.0
@export var min_zoom := 1
@export var max_zoom := 10.0
@export var zoom_speed := 0.5
@export var min_pitch := deg_to_rad(-80)
@export var max_pitch := deg_to_rad(0)
@export var mouse_sensitivity:float = 0.0007
@onready var camera_3d: Camera3D = $Camera_Controller/Camera_Pivot/Camera3D
@onready var crosshair: Control = $Crosshair
@onready var spring_arm: SpringArm3D = $Camera_Controller/Camera_Pivot
@onready var interact_ray: ShapeCast3D = $InteractRay
@onready var chatbot = $Chatbot
@onready var env = $".."
var rock_scene: PackedScene = preload("res://Resources/Objects/rock.tscn")
signal inventory_opened
signal inventory_closed
signal chatbot_opened
func _ready() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
$Camera_Controller.position = position
$Armature/Skeleton3D/CharacterMesh.mesh = load(Global.mesh_resource_player)
camera_pitch = $Camera_Controller/Camera_Pivot.rotation.x
zoom = spring_arm.spring_length
if DialogueState.currentTask > 1:
$AnimationPlayer.play('helper_visible')
if Global.balloon_collected == true:
print(Global.resource_balloon)
_on_balloon_balloon_chosen(Global.resource_balloon)
func _process(delta: float) -> void:
if Global.chatbot_opened:
return
if Input.is_action_just_pressed("help"):
if DialogueState.is_dialogue_open == false:
DialogueState.is_dialogue_open = true
DialogueManager.show_chosen_dialogue_balloon(load("res://Interact/dialogue/helper.dialogue"), "/game_balloons/game_balloon_v_1.tscn", "start", [self, $Player/helper])
func _input(event):
if event is InputEventMouseMotion and mode == PlayerMode.NORMAL:
$Camera_Controller.rotate_y(-event.relative.x * mouse_sensitivity)
camera_pitch -= event.relative.y * mouse_sensitivity
camera_pitch = clamp(camera_pitch, min_pitch, max_pitch)
$Camera_Controller/Camera_Pivot.rotation.x = camera_pitch
if event is InputEventMouseButton and event.pressed:
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
zoom -= zoom_speed
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
zoom += zoom_speed
zoom = clamp(zoom, min_zoom, max_zoom)
spring_arm.spring_length = zoom
print(spring_arm.spring_length)
func _physics_process(delta: float) -> void:
if Global.chatbot_opened or $Inventory.visible:
return
dialogueActive = DialogueState.is_dialogue_open
var thisTime = Time.get_unix_time_from_system()
# --- DROP / THROW ---
if Input.is_action_just_pressed("drop") and grabbed_item:
grabbed_item.release(self)
$AnimationPlayer.play_backwards("pickup")
play_sound('drop')
if Input.is_action_just_pressed("throw") and grabbed_item:
grabbed_item.release(self, true)
play_sound('drop')
elif Input.is_action_just_pressed("throw") and not grabbed_item:
if mode == PlayerMode.NORMAL:
mode = PlayerMode.AIM
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
mode = PlayerMode.NORMAL
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
# --- AIM THROW ---
elif Input.is_action_just_pressed("click") and mode == PlayerMode.AIM and not dialogueActive and not $Inventory.visible:
var mouse_pos = get_viewport().get_mouse_position()
var ray_origin = camera_3d.project_ray_origin(mouse_pos)
var ray_direction = camera_3d.project_ray_normal(mouse_pos)
var ray_length = 1000
var space_state = get_world_3d().direct_space_state
var query = PhysicsRayQueryParameters3D.create(
ray_origin,
ray_origin + ray_direction * ray_length
)
query.exclude = [self]
#Exclude Boundary Layer (Layer 7)
query.collision_mask = ~(1 << 6)
var result = space_state.intersect_ray(query)
var target_position: Vector3
if result.size() > 0:
target_position = result.position
else:
target_position = ray_origin + ray_direction * ray_length
var from = global_transform.origin + Vector3(0, 1.5, 0)
var throw_direction = (target_position - from).normalized()
var rock_instance = rock_scene.instantiate()
get_tree().current_scene.add_child(rock_instance)
var forward_dir = -camera_3d.global_transform.basis.z.normalized()
rock_instance.global_transform.origin = from + forward_dir * 1.0
rock_instance.freeze = false
rock_instance.sleeping = false
rock_instance.gravity_scale = 0.0
rock_instance.linear_velocity = throw_direction * throw_strength
$AnimationPlayer.play("jump")
$audio_throw.play()
# --- GRAVITY ---
if not is_on_floor():
velocity += get_gravity() * delta
# --- JUMP ---
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
var deltaTime = thisTime - DialogueState.time_since_dialoge_open
if not dialogueActive and (deltaTime > 0.5):
$audio_jump.play()
velocity.y = JUMP_VELOCITY
$AnimationPlayer.stop()
$AnimationPlayer.play("jump")
await get_tree().create_timer(0.4).timeout
$AnimationPlayer.play_backwards("jump")
# --- MOVEMENT ---
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
if dialogueActive or $Inventory.visible:
input_dir = Vector2.ZERO
var direction : Vector3 = ($Camera_Controller.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if input_dir != Vector2.ZERO:
self.rotation_degrees.y = $Camera_Controller.rotation_degrees.y - rad_to_deg(input_dir.angle()) - 90
# --- FLOOR ALIGN ---
if is_on_floor() and input_dir != Vector2.ZERO:
align_with_floor($RayCast3D.get_collision_normal())
global_transform = global_transform.interpolate_with(xform, 0.3)
elif not is_on_floor():
align_with_floor(Vector3.UP)
global_transform = global_transform.interpolate_with(xform, 0.3)
# --- VELOCITY ---
if direction:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
if grabbed_item:
$AnimationPlayer.play("pickup_walk")
else:
$AnimationPlayer.play("walk")
else:
velocity.x = move_toward(velocity.x, 0, speed)
velocity.z = move_toward(velocity.z, 0, speed)
move_and_slide()
$Camera_Controller.position = lerp($Camera_Controller.position, position, 0.15)
func align_with_floor(floor_normal):
xform = global_transform
xform.basis.y = floor_normal
xform.basis.x = -xform.basis.z.cross(floor_normal)
xform.basis = xform.basis.orthonormalized()
func _on_fall_zone_body_entered(body: Node3D) -> void:
get_tree().reload_current_scene()
func openChatBot():
chatbot_opened.emit()
chatbot.visible = true
Global.chatbot_opened = true
chatbot._prompt_edit.grab_focus()
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
env.quiet_down_music()
func get_weight():
return weight
func _on_interact_ray_grabbed() -> void:
$AnimationPlayer.play("pickup")
func set_mode(mode_new: String) -> void:
if mode_new == "aim":
mode = PlayerMode.AIM
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
elif mode_new == "normal":
mode = PlayerMode.NORMAL
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func toggle_inventory() -> void:
if $Inventory.visible:
$Inventory.visible = false
set_mode("normal")
inventory_closed.emit()
else:
$Inventory.visible = true
set_mode("aim")
inventory_opened.emit()
func _on_balloon_balloon_chosen(mesh: String) -> void:
$Balloon.visible = true
$Balloon.set_mesh(mesh)
Global.resource_balloon = mesh
Global.balloon_collected = true
func slow_down() -> void:
if counter_speed < len(speeds)-1:
counter_speed += 1
speed = speeds[counter_speed]
func reset_speed() -> void:
counter_speed = 0
speed = 5.0
func _on_animation_player_animation_started(anim_name: StringName) -> void:
if anim_name == 'walk' or anim_name == 'pickup_walk':
$AnimationPlayer.speed_scale = animation_player_speeds[counter_speed]
else:
$AnimationPlayer.speed_scale = animation_player_speeds[1]
func play_sound(sound_name: String) -> void:
if sound_name == 'pickup':
$audio_pickup.play()
elif sound_name == 'drop':
$audio_pickup.play()
func toggle_music() -> void:
env.toggle_music()