Compare commits

...

4 Commits

Author SHA1 Message Date
Martin Felis 396d884ff0 Improved conversations and input blocking. 2024-11-15 13:09:38 +01:00
Martin Felis e9db7b1095 Also improved look at for NPCs. 2024-11-15 11:35:37 +01:00
Martin Felis 8fdee7642c Fixed error in item spawner. 2024-11-15 11:05:32 +01:00
Martin Felis 75fbb72da1 Better player look at control. 2024-11-15 11:05:01 +01:00
11 changed files with 92 additions and 51 deletions

View File

@ -1,8 +1,6 @@
class_name ConversationActionable
extends Area3D
signal conversation_started
@export var dialogue_start: String = "start"
@export var related_quest_path: NodePath
@ -25,5 +23,3 @@ func action() -> void:
balloon.start(quest_dialogue_resource, dialogue_start, quest_states)
else:
balloon.start(default_dialogue_resource, dialogue_start, quest_states)
conversation_started.emit()

View File

@ -9,6 +9,6 @@ extends Node3D
func spawn() -> void:
if randf() < spawn_chance:
var pickup_item:PickupItem = pickup_item_scene.instantiate()
pickup_item.item = load("res://data/items/seeds.tres")
get_parent().add_child(pickup_item)
pickup_item.global_transform = global_transform
pickup_item.item = load("res://data/items/seeds.tres")

View File

@ -17,8 +17,10 @@ const JUMP_VELOCITY = 4.5
var tool_damage:bool = false
var tracking_node:Node3D = null
var look_direction:Vector3 = Vector3.BACK
var look_direction_damper:SpringDamper = SpringDamper.new(Vector3.ZERO, 2, 0.003, 0.003)
var _current_look_direction:Vector3 = Vector3.BACK
var _target_look_direction:Vector3 = Vector3.BACK
var _look_angle_damper:SpringDamper = SpringDamper.new(0, 2, 0.06, 0.003)
func _set_reacts_to_player(value:bool) -> bool:
if player_detection != null:
@ -36,18 +38,31 @@ func _ready() -> void:
animation_player.set_root("Geometry")
func _physics_process(delta: float) -> void:
var damped_look_direction = look_direction_damper.calc_clamped_speed(geometry.global_basis.z, look_direction, delta, 3.141)
_current_look_direction = basis.z
if tracking_node != null:
look_direction = (tracking_node.global_position - global_position).normalized()
_target_look_direction = (tracking_node.global_position - global_position).normalized()
look_direction.y = position.y
geometry.look_at(position - damped_look_direction, Vector3.UP)
update_look_direction(delta)
func _on_player_detection_body_entered(body: Node3D) -> void:
tracking_node = body
if body is Player:
tracking_node = body
func _on_player_detection_body_exited(body: Node3D) -> void:
look_direction = Vector3.BACK
if body == tracking_node:
tracking_node = null
_target_look_direction = Vector3.BACK
func update_look_direction(delta:float) -> void:
var current_look_angle:float = _current_look_direction.signed_angle_to(Vector3.BACK, Vector3.UP)
var target_look_angle:float = _target_look_direction.signed_angle_to(Vector3.BACK, Vector3.UP)
if target_look_angle - current_look_angle > PI:
current_look_angle = current_look_angle + PI * 2
elif current_look_angle - target_look_angle > PI:
current_look_angle = current_look_angle - PI * 2
var damped_look_angle:float = _look_angle_damper.calc(current_look_angle, target_look_angle, delta)
_current_look_direction = Vector3(sin(-damped_look_angle), 0, cos(-damped_look_angle))
self.basis = Basis.looking_at(-_current_look_direction)

View File

@ -24,9 +24,9 @@ var inventory:Inventory = Inventory.new()
var selected_tool_slot_index:int = 0
var current_tool:ItemResource = null
var _direction:Vector3 = Vector3.ZERO
var _look_direction:Vector3 = Vector3.BACK
var _look_direction_damper:SpringDamper = SpringDamper.new(Vector3.ZERO)
var _current_look_direction:Vector3 = Vector3.BACK
var _target_look_direction:Vector3 = Vector3.BACK
var _look_angle_damper:SpringDamper = SpringDamper.new(0, 4, 0.06, 0.003)
var is_input_blocked:bool = false
@ -40,10 +40,10 @@ func _handle_input() -> void:
# 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")
_direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if _direction:
velocity.x = _direction.x * SPEED
velocity.z = _direction.z * SPEED
var direction = 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)
@ -56,25 +56,42 @@ func _physics_process(delta):
if not is_on_floor():
velocity.y -= gravity * delta
if not is_input_blocked:
if is_input_blocked:
velocity = Vector3.ZERO
else:
_handle_input()
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
_target_look_direction = Vector3(velocity.x, 0, velocity.z).normalized()
var damped_look_direction = _look_direction_damper.calc(global_basis.z, _look_direction, delta)
_current_look_direction = basis.z
update_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 init_look_target_direction() -> void:
_target_look_direction = basis.z
func update_look_direction(delta:float) -> void:
var current_look_angle:float = _current_look_direction.signed_angle_to(Vector3.BACK, Vector3.UP)
var target_look_angle:float = _target_look_direction.signed_angle_to(Vector3.BACK, Vector3.UP)
if target_look_angle - current_look_angle > PI:
current_look_angle = current_look_angle + PI * 2
elif current_look_angle - target_look_angle > PI:
current_look_angle = current_look_angle - PI * 2
var damped_look_angle:float = _look_angle_damper.calc(current_look_angle, target_look_angle, delta)
_current_look_direction = Vector3(sin(-damped_look_angle), 0, cos(-damped_look_angle))
self.basis = Basis.looking_at(-_current_look_direction)
func set_tool_slot_index(value:int) -> void:
if inventory == null:
@ -138,7 +155,7 @@ 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()
_target_look_direction = (actionables[0].global_position - position).normalized()
actionables[0].action()
get_viewport().set_input_as_handled()

View File

@ -18,6 +18,7 @@ config/icon="res://icon.svg"
[autoload]
DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
InteractionSystem="*res://systems/InteractionSystem.gd"
[dialogue_manager]

View File

@ -9,32 +9,12 @@ extends QuestBase
@onready var merchant: NonPlayerCharacter = %Merchant
var _bridge_transform:Transform3D = Transform3D.IDENTITY
var _merchant_conversation_actionable:ConversationActionable = null
signal wrench_delivered
func _ready():
super._ready()
_bridge_transform = bridge.global_transform
bridge.global_transform = Transform3D.IDENTITY.translated(Vector3.UP * -1000)
_merchant_conversation_actionable = merchant.find_child("Conversation", true, false)
assert(_merchant_conversation_actionable != null)
_merchant_conversation_actionable.conversation_started.connect(on_dialogue_started)
func on_dialogue_started() -> void:
_player.is_input_blocked = true
func on_dialogue_ended(_dialog_resource: DialogueResource) -> void:
_player.is_input_blocked = false
if is_completed:
return
if is_hammer_delivered and not is_bridge_built:
wrench_delivered.emit()
func _process(_delta):
if is_hammer_delivered:

View File

@ -49,6 +49,8 @@ func load_scene(scene_resource:PackedScene):
_game_build_system = scene.find_child("BuildSystem", true, false) as BuildSystem
var player:Player = scene.find_child("Player", true, false)
InteractionSystem.player = player
func save_game():
var player:Player = scene.find_child("Player", true, false)
@ -107,7 +109,8 @@ func load_game():
return
player.global_transform = save_data.player_transform
player.init_look_target_direction()
# Quest state
for quest_state:Node in get_tree().get_nodes_in_group("quest_state"):
for property in quest_state.get_property_list():

View File

@ -12,7 +12,6 @@ var _player_camera_offset:Vector3 = Vector3.ZERO
func _ready():
_player_camera_offset = camera.global_position - player.global_position + Vector3.UP * 1
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
if build_system.is_active and build_system.build_item != null:

View File

@ -0,0 +1,26 @@
extends Node
signal conversation_started
signal conversation_stopped
var is_conversation_active:bool = false
var player:Player = null
func _ready():
if not DialogueManager.is_connected("dialogue_ended", InteractionSystem.stop_conversation):
DialogueManager.connect("dialogue_ended", InteractionSystem.stop_conversation)
func start_conversation(resource: DialogueResource) -> void:
is_conversation_active = true
print ("Conversation started")
emit_signal("conversation_started")
if player:
player.is_input_blocked = true
func stop_conversation(resource: DialogueResource) -> void:
is_conversation_active = false
print ("Conversation stopped")
emit_signal("conversation_stopped")
if player:
player.is_input_blocked = false

View File

@ -104,6 +104,7 @@ func start(dialogue_resource: DialogueResource, title: String, extra_game_states
temporary_game_states = [self] + extra_game_states
is_waiting_for_input = false
resource = dialogue_resource
InteractionSystem.start_conversation(dialogue_resource)
self.dialogue_line = await resource.get_next_dialogue_line(title, temporary_game_states)

View File

@ -35,7 +35,10 @@ func calc_clamped_speed(x, xt, h:float, s_max:float):
var x_new = calc(x, xt, h)
var vel_new = (x_new - x_old) / h
var speed_new = vel_new.length()
var speed_new = abs(vel_new)
if not vel_new is float:
speed_new = vel_new.length()
if speed_new > s_max:
vel_new = (vel_new / speed_new) * s_max
x = x_old + vel_new * h