class_name Player extends CharacterBody3D const SPEED = 3.0 const JUMP_VELOCITY = 2.5 @onready var geometry:Node3D = %Geometry @onready var actionable_detector = %ActionableDetector @onready var animation_tree:AnimationTree = $Geometry/Rogue/AnimationTree @onready var build_location:Node3D = %BuildLocation @onready var right_hand_attachement:Node3D = %RightHandAttachement # Get the gravity from the project settings to be synced with RigidBody nodes. var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") var inventory:Inventory = Inventory.new() var selected_tool_slot_index:int = 0 var current_tool:Item = null var look_direction:Vector3 = Vector3.BACK var look_direction_damper:SpringDamper = SpringDamper.new(Vector3.ZERO) signal trigger_message(message:String) var interaction_state:bool = false func _process(_delta): animation_tree.set("parameters/conditions/interact", interaction_state) if interaction_state: interaction_state = false func _physics_process(delta): # Add the gravity. if not is_on_floor(): velocity.y -= gravity * delta # Get the input direction and handle the movement/deceleration. # As good practice, you should replace UI actions with custom gameplay actions. var input_dir = Input.get_vector("walk_left", "walk_right", "walk_forward", "walk_back") var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() if direction: velocity.x = direction.x * SPEED velocity.z = direction.z * SPEED else: velocity.x = move_toward(velocity.x, 0, SPEED) velocity.z = move_toward(velocity.z, 0, SPEED) move_and_slide() var ground_velocity:Vector2 = Vector2(velocity.x, velocity.z) var is_moving:bool = ground_velocity.length_squared() > 0.1 * 0.1 if is_moving: look_direction = Vector3(ground_velocity.x, 0, ground_velocity.y).normalized() elif direction.length_squared() > 0.1 * 0.1: look_direction = direction var damped_look_direction = look_direction_damper.calc(geometry.global_basis.z, look_direction, delta) animation_tree.set("parameters/conditions/running", is_moving) animation_tree.set("parameters/conditions/idle", not is_moving) geometry.look_at(position - damped_look_direction, Vector3.UP) func on_item_picked_up(item:Item): emit_signal("trigger_message", "Picked up a " + item.name) inventory.add_item(item) func get_actionable_global_transform() -> Vector3: return build_location.global_position func set_right_hand_item(item:Item) -> void: for child in right_hand_attachement.get_children(): child.queue_free() current_tool = null if item != null and item.is_tool: right_hand_attachement.add_child(item.scene.instantiate()) current_tool = item animation_tree.set("parameters/Interact/conditions/tool_action_slice", false) animation_tree.set("parameters/Interact/conditions/tool_action_chop", false) match item.tool_action: 1: animation_tree.set("parameters/Interact/conditions/tool_action_chop", true) 2: animation_tree.set("parameters/Interact/conditions/tool_action_slice", true) func has_build_tool_active() -> bool: if current_tool and current_tool.resource_path == "res://data/items/hammer.tres": return true return false func handle_tool_slot_input_events(_event:InputEvent) -> bool: var key_event:InputEventKey = _event as InputEventKey if key_event and key_event.is_released(): if key_event.keycode >= KEY_1 and key_event.keycode <= KEY_9: selected_tool_slot_index = key_event.keycode - KEY_1 set_right_hand_item(inventory.get_tool_item_stacks()[selected_tool_slot_index].item) return true if _event.is_action_released("item_next"): selected_tool_slot_index = (selected_tool_slot_index + 1) % (inventory.get_tool_item_stacks().size()) set_right_hand_item(inventory.get_tool_item_stacks()[selected_tool_slot_index].item) return true if _event.is_action_released("item_prev"): var tool_slot_size = inventory.get_tool_item_stacks().size() selected_tool_slot_index = (selected_tool_slot_index + tool_slot_size - 1) % (tool_slot_size) set_right_hand_item(inventory.get_tool_item_stacks()[selected_tool_slot_index].item) return true return false func _unhandled_input(_event: InputEvent) -> void: if Input.is_action_just_pressed("ui_accept"): var actionables = actionable_detector.get_overlapping_areas() if actionables.size() > 0: look_direction = (actionables[0].global_position - position).normalized() actionables[0].action() get_viewport().set_input_as_handled() return if Input.is_action_just_pressed("interaction"): interaction_state = true get_viewport().set_input_as_handled() return