feat: add playable generated dialogue mode
This commit is contained in:
@@ -7,6 +7,7 @@ const KIND_PANTRY := &"pantry"
|
||||
const KIND_STORAGE_DEPOSIT := &"storage_deposit"
|
||||
const KIND_GUARD := &"guard"
|
||||
const KIND_STUDY := &"study"
|
||||
const KIND_DIALOGUE := &"dialogue"
|
||||
|
||||
var kind: StringName
|
||||
var action_id: StringName
|
||||
|
||||
@@ -48,6 +48,11 @@ func _physics_process(delta: float) -> void:
|
||||
if simulation_manager != null and simulation_manager.has_method("update_player_combatant"):
|
||||
simulation_manager.update_player_combatant(player.global_position)
|
||||
_advance_timers(delta)
|
||||
if _input_is_locked():
|
||||
dash_duration_remaining = 0.0
|
||||
dashing = false
|
||||
dash_velocity = Vector3.ZERO
|
||||
return
|
||||
if _player_is_downed():
|
||||
attack_timer = 0.0
|
||||
dash_duration_remaining = 0.0
|
||||
@@ -81,7 +86,7 @@ func _player_is_downed() -> bool:
|
||||
|
||||
|
||||
func _perform_attack() -> void:
|
||||
if attack_timer > 0.0 or not _simulation_attack_ready():
|
||||
if _input_is_locked() or attack_timer > 0.0 or not _simulation_attack_ready():
|
||||
return
|
||||
attack_timer = attack_cooldown_seconds
|
||||
_play_swing()
|
||||
@@ -100,7 +105,7 @@ func _perform_attack() -> void:
|
||||
|
||||
|
||||
func _perform_dash() -> void:
|
||||
if dash_cooldown_remaining > 0.0 or _player_is_downed():
|
||||
if _input_is_locked() or dash_cooldown_remaining > 0.0 or _player_is_downed():
|
||||
return
|
||||
dash_duration_remaining = dash_duration
|
||||
dash_cooldown_remaining = maxf(dash_cooldown_seconds, dash_duration)
|
||||
@@ -144,7 +149,15 @@ func is_dashing() -> bool:
|
||||
|
||||
|
||||
func get_dash_velocity() -> Vector3:
|
||||
return dash_velocity if dashing else Vector3.ZERO
|
||||
return dash_velocity if dashing and not _input_is_locked() else Vector3.ZERO
|
||||
|
||||
|
||||
func _input_is_locked() -> bool:
|
||||
return (
|
||||
player != null
|
||||
and player.has_method("is_dialogue_input_locked")
|
||||
and bool(player.call("is_dialogue_input_locked"))
|
||||
)
|
||||
|
||||
|
||||
func get_dash_cooldown_remaining() -> float:
|
||||
|
||||
+77
-2
@@ -2,6 +2,8 @@ extends CharacterBody3D
|
||||
|
||||
signal interaction_feedback(heading: String, message: String, succeeded: bool)
|
||||
|
||||
const DIALOGUE_MODE_CONTROLLER_SCRIPT := preload("res://world/dialogue/DialogueModeController.gd")
|
||||
|
||||
@export var move_speed := 7.0
|
||||
@export var acceleration := 18.0
|
||||
@export var rotation_speed := 12.0
|
||||
@@ -21,12 +23,24 @@ signal interaction_feedback(heading: String, message: String, succeeded: bool)
|
||||
|
||||
@onready var combat_controller: Node = get_node_or_null("PlayerCombatController")
|
||||
|
||||
var dialogue_mode_controller: DialogueModeController
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("grass_interactors")
|
||||
_install_dialogue_mode_controller()
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if is_dialogue_input_locked():
|
||||
velocity.x = move_toward(velocity.x, 0.0, acceleration * delta)
|
||||
velocity.z = move_toward(velocity.z, 0.0, acceleration * delta)
|
||||
if not is_on_floor():
|
||||
velocity.y -= 30.0 * delta
|
||||
else:
|
||||
velocity.y = 0.0
|
||||
move_and_slide()
|
||||
return
|
||||
if _is_player_downed():
|
||||
velocity.x = move_toward(velocity.x, 0.0, acceleration * delta)
|
||||
velocity.z = move_toward(velocity.z, 0.0, acceleration * delta)
|
||||
@@ -79,16 +93,26 @@ func _is_player_downed() -> bool:
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("interact"):
|
||||
if is_dialogue_input_locked():
|
||||
return
|
||||
if (
|
||||
event.is_action_pressed("interact")
|
||||
or (event.is_action_pressed("ui_accept") and _get_nearby_dialogue_npc_id() >= 0)
|
||||
):
|
||||
try_interact()
|
||||
|
||||
|
||||
func try_interact() -> void:
|
||||
if is_dialogue_input_locked():
|
||||
return
|
||||
var context := get_interaction_context()
|
||||
if context == null:
|
||||
return
|
||||
|
||||
match context.kind:
|
||||
PlayerInteractionResult.KIND_DIALOGUE:
|
||||
if dialogue_mode_controller != null:
|
||||
dialogue_mode_controller.begin_conversation(int(String(context.target_id)))
|
||||
PlayerInteractionResult.KIND_ANIMAL:
|
||||
_execute_animal_interaction(context)
|
||||
PlayerInteractionResult.KIND_RESOURCE:
|
||||
@@ -110,8 +134,19 @@ func try_interact() -> void:
|
||||
|
||||
|
||||
func get_interaction_context() -> PlayerInteractionResult:
|
||||
if simulation_manager == null:
|
||||
if simulation_manager == null or is_dialogue_input_locked():
|
||||
return null
|
||||
var villager := _find_npc(_get_nearby_dialogue_npc_id())
|
||||
if villager != null:
|
||||
return PlayerInteractionResult.new(
|
||||
PlayerInteractionResult.KIND_DIALOGUE,
|
||||
DialogueModeController.TALK_ACTION_ID,
|
||||
StringName(str(villager.id)),
|
||||
villager.npc_name,
|
||||
"Talk with %s" % villager.npc_name,
|
||||
"Ask what is happening nearby",
|
||||
null
|
||||
)
|
||||
var animal := _find_feed_animal()
|
||||
if animal != null:
|
||||
return _build_animal_context(animal)
|
||||
@@ -148,6 +183,46 @@ func get_interaction_context() -> PlayerInteractionResult:
|
||||
return null
|
||||
|
||||
|
||||
func is_dialogue_input_locked() -> bool:
|
||||
if (
|
||||
simulation_manager != null
|
||||
and simulation_manager.has_method("is_dialogue_active")
|
||||
and bool(simulation_manager.call("is_dialogue_active"))
|
||||
):
|
||||
return true
|
||||
return (
|
||||
dialogue_mode_controller != null
|
||||
and is_instance_valid(dialogue_mode_controller)
|
||||
and dialogue_mode_controller.is_dialogue_active()
|
||||
)
|
||||
|
||||
|
||||
func _install_dialogue_mode_controller() -> void:
|
||||
var existing := get_node_or_null("DialogueModeController") as DialogueModeController
|
||||
if existing != null:
|
||||
dialogue_mode_controller = existing
|
||||
else:
|
||||
dialogue_mode_controller = DIALOGUE_MODE_CONTROLLER_SCRIPT.new()
|
||||
dialogue_mode_controller.name = "DialogueModeController"
|
||||
dialogue_mode_controller.configure(self, simulation_manager, world_view_manager)
|
||||
add_child(dialogue_mode_controller)
|
||||
if existing != null:
|
||||
dialogue_mode_controller.configure(self, simulation_manager, world_view_manager)
|
||||
|
||||
|
||||
func _get_nearby_dialogue_npc_id() -> int:
|
||||
if (
|
||||
world_view_manager == null
|
||||
or not world_view_manager.has_method("find_nearest_active_npc_id")
|
||||
):
|
||||
return -1
|
||||
return int(
|
||||
world_view_manager.call(
|
||||
"find_nearest_active_npc_id", global_position, villager_inspection_range
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
func get_nearby_villager_inspection() -> VillagerInspectionResult:
|
||||
if (
|
||||
simulation_manager == null
|
||||
|
||||
Reference in New Issue
Block a user