fix: ladder climb self-resets after 5 seconds

This commit is contained in:
tiger tiger tiger 2026-01-16 21:36:36 +01:00
parent c76f599e4b
commit 1bdcf6c78f
4 changed files with 68 additions and 67 deletions

View File

@ -18,6 +18,8 @@ func raise(body) -> void:
raiser = create_tween() raiser = create_tween()
raiser.tween_property(self, "position", start_position + Vector3(0,1.1,0), 1) raiser.tween_property(self, "position", start_position + Vector3(0,1.1,0), 1)
risen = true risen = true
await get_tree().create_timer(5).timeout
reset(false)
func reset(_discard) -> void: func reset(_discard) -> void:

View File

@ -5,7 +5,7 @@
[ext_resource type="PackedScene" uid="uid://mkccbig41bqb" path="res://logic-scenes/player_controller/player_controller.tscn" id="3_foj4y"] [ext_resource type="PackedScene" uid="uid://mkccbig41bqb" path="res://logic-scenes/player_controller/player_controller.tscn" id="3_foj4y"]
[ext_resource type="AudioStream" uid="uid://bbpo1hu35yer8" path="res://base-environments/youth_room/import/sounds/thunder.mp3" id="3_wcypa"] [ext_resource type="AudioStream" uid="uid://bbpo1hu35yer8" path="res://base-environments/youth_room/import/sounds/thunder.mp3" id="3_wcypa"]
[ext_resource type="Script" uid="uid://c281w7earok6w" path="res://base-environments/youth_room/crouch_volume.gd" id="3_x3dlb"] [ext_resource type="Script" uid="uid://c281w7earok6w" path="res://base-environments/youth_room/crouch_volume.gd" id="3_x3dlb"]
[ext_resource type="Script" path="res://base-environments/youth_room/climb_volume.gd" id="4_dqyng"] [ext_resource type="Script" uid="uid://hji6r2e8mcqo" path="res://base-environments/youth_room/climb_volume.gd" id="4_dqyng"]
[ext_resource type="PackedScene" uid="uid://bnskiyx1sksww" path="res://logic-scenes/board/physics-board.tscn" id="4_gyjxx"] [ext_resource type="PackedScene" uid="uid://bnskiyx1sksww" path="res://logic-scenes/board/physics-board.tscn" id="4_gyjxx"]
[ext_resource type="AudioStream" uid="uid://1tvopjmo6dp2" path="res://base-environments/youth_room/audio/Azure Studios - mgd-723687677.mp3" id="5_fe1yj"] [ext_resource type="AudioStream" uid="uid://1tvopjmo6dp2" path="res://base-environments/youth_room/audio/Azure Studios - mgd-723687677.mp3" id="5_fe1yj"]
[ext_resource type="PackedScene" uid="uid://citwb7f4dl3l1" path="res://thank-you.tscn" id="5_kts6y"] [ext_resource type="PackedScene" uid="uid://citwb7f4dl3l1" path="res://thank-you.tscn" id="5_kts6y"]

View File

@ -66,15 +66,15 @@ var source_dicts: Array[Dictionary] = [
}, },
] ]
var id_reference: Dictionary[StringName, StringName] = generate_id_reference(true, true) var all_ids: Dictionary[StringName, StringName] = generate_id_reference(true, true)
var card_ids: Dictionary[StringName, StringName] = generate_id_reference(true, false)
var card_id_reference: Dictionary[StringName, StringName] = generate_id_reference(true, false) var sticky_ids: Dictionary[StringName, StringName] = generate_id_reference(false, true)
var sticky_id_reference: Dictionary[StringName, StringName] = generate_id_reference(false, true) var obscure_ids: Dictionary[StringName, StringName] = generate_obscure_reference()
var obscure_reference: Dictionary[StringName, StringName] = generate_obscure_reference()
func generate_id_reference(include_cards: bool, include_sticky: bool) -> Dictionary[StringName, StringName]: func generate_id_reference(include_cards: bool, include_sticky: bool) -> Dictionary[StringName, StringName]:
var out:Dictionary[StringName, StringName] = {} var out:Dictionary[StringName, StringName] = {}
for id in range(source_dicts.size()): for id in range(source_dicts.size()):
for card_name:String in source_dicts[id].keys(): for card_name:String in source_dicts[id].keys():
if include_cards: if include_cards:
@ -83,30 +83,30 @@ func generate_id_reference(include_cards: bool, include_sticky: bool) -> Diction
for sticky_name in source_dicts[id][card_name]: for sticky_name in source_dicts[id][card_name]:
if sticky_name is String: if sticky_name is String:
out[sticky_name] = "%d.%s.%s" % [id, card_name, sticky_name] out[sticky_name] = "%d.%s.%s" % [id, card_name, sticky_name]
return out return out
func generate_obscure_reference(): func generate_obscure_reference():
var out:Dictionary[StringName, StringName] = {} var out:Dictionary[StringName, StringName] = {}
randomize() randomize()
var salt = randi_range(1111, 9999) var salt = randi_range(1111, 9999)
for id in range(source_dicts.size()): for id in range(source_dicts.size()):
for card_name:String in source_dicts[id].keys(): for card_name:String in source_dicts[id].keys():
out[card_name] = StringName("%d.%d" % [id, card_name.hash() % salt ]) out[card_name] = StringName("%d.%d" % [id, card_name.hash() % salt ])
for sticky_name in source_dicts[id][card_name]: for sticky_name in source_dicts[id][card_name]:
if sticky_name is String: if sticky_name is String:
out[sticky_name] = StringName("%d.%s.%s" % [id, card_name.hash() % salt, sticky_name.hash() % salt]) out[sticky_name] = StringName("%d.%s.%s" % [id, card_name.hash() % salt, sticky_name.hash() % salt])
return out return out
func get_child_names_of(parent_id: StringName) -> Array[StringName]: func get_child_names_of(parent_id: StringName) -> Array[StringName]:
var out: Array[StringName] var out: Array[StringName]
for child_name: StringName in id_reference.keys(): for child_name: StringName in all_ids.keys():
if id_reference[child_name].contains(parent_id): if all_ids[child_name].contains(parent_id):
if child_name != parent_id: if child_name != parent_id:
out.append(child_name) out.append(child_name)
return out return out
@ -117,23 +117,21 @@ func get_children_of(parent_id: StringName) -> Array:
func get_obscure_name(card_name: StringName): func get_obscure_name(card_name: StringName):
if State.obscure_logs and not OS.is_debug_build(): if State.obscure_logs and not OS.is_debug_build():
return obscure_reference[card_name] return obscure_ids[card_name]
else: else:
return card_name return card_name
func arrange(cards: Array[Card], rect: Rect2, _obstacles: Array[Area2D]) -> Array[Card]: func arrange(cards: Array[Card], rect: Rect2, _obstacles: Array[Area2D]) -> Array[Card]:
#var total_cards := cards.size()
var x:int = 0 var x:int = 0
var y:int = 0 var y:int = 0
var i:int = 0 var i:int = 0
var maximum:int = cards.size() var maximum:int = cards.size()
var grid: int = ceil(sqrt(maximum)) var grid: int = ceil(sqrt(maximum))
var diameter:float = cards[0].diameter var diameter:float = cards[0].diameter
var r_cards: Array[Card] = cards.duplicate() var r_cards: Array[Card] = cards.duplicate()
r_cards.shuffle() r_cards.shuffle()
while i < maximum: while i < maximum:
while x < grid and i < maximum: while x < grid and i < maximum:
while y < ceil(sqrt(maximum)) and i < maximum: while y < ceil(sqrt(maximum)) and i < maximum:
@ -143,9 +141,9 @@ func arrange(cards: Array[Card], rect: Rect2, _obstacles: Array[Area2D]) -> Arra
x += 1 x += 1
for card: Card in r_cards: for card: Card in r_cards:
for _i in range(20): for _i in range(20):
if is_out_of_bounds(card, rect): if is_out_of_bounds(card, rect):
card.position = rect.get_center() - card.position * 0.8 card.position = rect.get_center() - card.position * 0.8
continue continue
@ -159,11 +157,11 @@ func arrange(cards: Array[Card], rect: Rect2, _obstacles: Array[Area2D]) -> Arra
for colliding in colliders: for colliding in colliders:
if (colliding.position - card.position).length() > (nearest.position - card.position).length(): if (colliding.position - card.position).length() > (nearest.position - card.position).length():
nearest = colliding nearest = colliding
card.position += min(nearest.position - card.position.normalized() * (card.diameter + 1), nearest.position - card.position) card.position += min(nearest.position - card.position.normalized() * (card.diameter + 1), nearest.position - card.position)
continue continue
break break
return r_cards return r_cards
@ -175,7 +173,7 @@ func is_out_of_bounds(card: Card, rect: Rect2):
Transform2D(0, rect.position+rect.size) Transform2D(0, rect.position+rect.size)
] ]
var shape: = WorldBoundaryShape2D.new() var shape: = WorldBoundaryShape2D.new()
for boundary:Transform2D in world_boundaries: for boundary:Transform2D in world_boundaries:
if card.collider.collide(card.transform, shape, boundary): if card.collider.collide(card.transform, shape, boundary):
return true return true
@ -183,12 +181,12 @@ func is_out_of_bounds(card: Card, rect: Rect2):
func get_cards_by_scene_id(id: int) -> Array[Card]: func get_cards_by_scene_id(id: int) -> Array[Card]:
var output:Array[Card] var output:Array[Card]
for card_name in source_dicts[id].keys(): for card_name in source_dicts[id].keys():
var card := card_prefab.instantiate() as Card var card := card_prefab.instantiate() as Card
card.init(card_name, id_reference[card_name]); card.init(card_name, all_ids[card_name]);
output.append(card) output.append(card)
return output return output
# used to put cards on the dev board # used to put cards on the dev board
@ -197,22 +195,24 @@ func get_cards_by_name_array(names: Array[StringName]) -> Dictionary[String, Arr
"cards": [], "cards": [],
"sticky_notes": [] "sticky_notes": []
} }
for card_name:StringName in names: for card_name:StringName in names:
if card_id_reference.has(card_name): if card_ids.has(card_name):
output["cards"].append(create_from_id(id_reference[card_name])) output["cards"].append(create_from_id(all_ids[card_name]))
else: else:
output["sticky_notes"].append(create_from_id(id_reference[card_name])) if not card_name in sticky_ids:
push_error("No card or sticky with name '%s'!" % card_name)
output["sticky_notes"].append(create_from_id(all_ids[card_name]))
return output return output
func create_from_id(id:StringName) -> Area2D: func create_from_id(id:StringName) -> Area2D:
var parsed: PackedStringArray = id.rsplit(".") var parsed: PackedStringArray = id.rsplit(".")
if card_id_reference.values().has(id): if card_ids.values().has(id):
var card := card_prefab.instantiate() as Card var card := card_prefab.instantiate() as Card
card.init(parsed[1], id); card.init(parsed[1], id);
return card return card
elif sticky_id_reference.values().has(id): elif sticky_ids.values().has(id):
var note := note_prefab.instantiate() as StickyNote var note := note_prefab.instantiate() as StickyNote
note.init(parsed[2], id) note.init(parsed[2], id)
return note return note
@ -223,31 +223,30 @@ func create_from_id(id:StringName) -> Area2D:
func create_dev_board(parent: Control, _rect: Rect2) -> void: func create_dev_board(parent: Control, _rect: Rect2) -> void:
var scroll_container := ScrollContainer.new() var scroll_container := ScrollContainer.new()
var panel := Panel.new() var panel := Panel.new()
parent.add_child(scroll_container) parent.add_child(scroll_container)
scroll_container.add_child(panel) scroll_container.add_child(panel)
for x in range(source_dicts.size()): for x in range(source_dicts.size()):
var sub_parent := Panel.new() var sub_parent := Panel.new()
sub_parent.position = Vector2( 128 + 256*x , 0) sub_parent.position = Vector2( 128 + 256*x , 0)
panel.add_child(sub_parent, false, Node.INTERNAL_MODE_BACK) panel.add_child(sub_parent, false, Node.INTERNAL_MODE_BACK)
var y := 1 var y := 1
for card_name in source_dicts[x].keys(): for card_name in source_dicts[x].keys():
var card:Card = create_from_id(card_id_reference[card_name]) var card:Card = create_from_id(card_ids[card_name])
sub_parent.add_child(card, false, Node.INTERNAL_MODE_BACK) sub_parent.add_child(card, false, Node.INTERNAL_MODE_BACK)
card.position = Vector2(0, card.diameter * y - card.diameter/2) card.position = Vector2(0, card.diameter * y - card.diameter/2)
var z := 0 var z := 0
for sticky_name in get_child_names_of(card_name): for sticky_name in get_child_names_of(card_name):
var sticky: StickyNote = create_from_id(sticky_id_reference[sticky_name]) var sticky: StickyNote = create_from_id(sticky_ids[sticky_name])
card.add_child(sticky, false, Node.INTERNAL_MODE_BACK) card.add_child(sticky, false, Node.INTERNAL_MODE_BACK)
sticky.position = card.sticky_note_position + Vector2(0, 80) * z sticky.position = card.sticky_note_position + Vector2(0, 80) * z
z += 1 z += 1
y += 1 y += 1
panel.custom_minimum_size.x = source_dicts.size() * 256 panel.custom_minimum_size.x = source_dicts.size() * 256
func _ready() -> void: func _ready() -> void:
create_dev_board(self, get_viewport().get_visible_rect()) create_dev_board(self, get_viewport().get_visible_rect())
TranslationServer.set_locale("en") TranslationServer.set_locale("en")

View File

@ -137,7 +137,7 @@ func _on_board_focused() -> void:
visible = true visible = true
if is_node_ready(): if is_node_ready():
process_mode = Node.PROCESS_MODE_INHERIT process_mode = Node.PROCESS_MODE_INHERIT
# Check board state and give lore feedback when presented # Check board state and give lore feedback when presented
if is_board_complete(): if is_board_complete():
board_was_completed = true board_was_completed = true
@ -212,12 +212,12 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act
# Prevent dragging multiple nodes at once # Prevent dragging multiple nodes at once
if current_context == DRAG and to_handle != currently_active_node: if current_context == DRAG and to_handle != currently_active_node:
return return
# === DRAG START === # === DRAG START ===
if input.button_index == MOUSE_BUTTON_LEFT and input.pressed: if input.button_index == MOUSE_BUTTON_LEFT and input.pressed:
_start_drag(to_handle) _start_drag(to_handle)
return return
# === DRAG END === # === DRAG END ===
if input.button_index == MOUSE_BUTTON_LEFT and not input.pressed: if input.button_index == MOUSE_BUTTON_LEFT and not input.pressed:
_end_drag(to_handle) _end_drag(to_handle)
@ -228,7 +228,7 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act
func _start_drag(draggable: Draggable) -> void: func _start_drag(draggable: Draggable) -> void:
currently_active_node = draggable currently_active_node = draggable
current_context = DRAG current_context = DRAG
var mouse_offset = get_viewport().get_mouse_position() - draggable.global_position var mouse_offset = get_viewport().get_mouse_position() - draggable.global_position
draggable.start_drag(mouse_offset) draggable.start_drag(mouse_offset)
@ -236,14 +236,14 @@ func _start_drag(draggable: Draggable) -> void:
## Ends a drag operation and handles the drop ## Ends a drag operation and handles the drop
func _end_drag(draggable: Draggable) -> void: func _end_drag(draggable: Draggable) -> void:
draggable.end_drag() draggable.end_drag()
# Let draggable find its own drop target # Let draggable find its own drop target
var drop_target = draggable.find_drop_target() var drop_target = draggable.find_drop_target()
# Execute the drop # Execute the drop
if drop_target and Draggable.is_drop_target(drop_target): if drop_target and Draggable.is_drop_target(drop_target):
var result = drop_target.handle_drop(draggable) var result = drop_target.handle_drop(draggable)
# Handle exchange result (sticky swapped with card's sticky) # Handle exchange result (sticky swapped with card's sticky)
if result == Draggable.DropResult.EXCHANGED: if result == Draggable.DropResult.EXCHANGED:
_handle_sticky_exchange(draggable, drop_target) _handle_sticky_exchange(draggable, drop_target)
@ -253,12 +253,12 @@ func _end_drag(draggable: Draggable) -> void:
else: else:
# Fallback: use default board drop # Fallback: use default board drop
handle_drop(draggable) handle_drop(draggable)
# Cleanup and state update # Cleanup and state update
_return_sticky_notes_to_panels() _return_sticky_notes_to_panels()
current_context = NAVIGATE current_context = NAVIGATE
_update_focus_after_drop(draggable) _update_focus_after_drop(draggable)
# Check win condition if sticky was attached to card # Check win condition if sticky was attached to card
if draggable is StickyNote and draggable.is_sticky_note_attached(): if draggable is StickyNote and draggable.is_sticky_note_attached():
check_board_comnpletion() check_board_comnpletion()
@ -268,16 +268,16 @@ func _end_drag(draggable: Draggable) -> void:
## The exchanged sticky always goes to the sticky_note_container (panel zone) ## The exchanged sticky always goes to the sticky_note_container (panel zone)
func _handle_sticky_exchange(new_sticky: StickyNote, card: Card) -> void: func _handle_sticky_exchange(new_sticky: StickyNote, card: Card) -> void:
var old_sticky = card.get_last_exchanged_sticky() var old_sticky = card.get_last_exchanged_sticky()
if not old_sticky: if not old_sticky:
push_warning("CardBoard: Exchange occurred but no sticky returned") push_warning("CardBoard: Exchange occurred but no sticky returned")
return return
# Reset visual state for old sticky # Reset visual state for old sticky
old_sticky.rotation = old_sticky.base_rotation old_sticky.rotation = old_sticky.base_rotation
old_sticky.scale = old_sticky.base_scale old_sticky.scale = old_sticky.base_scale
old_sticky.z_index = 0 old_sticky.z_index = 0
# Exchanged sticky always goes to sticky_note_container # Exchanged sticky always goes to sticky_note_container
if new_sticky._came_from_panel and sticky_note_container.get_child_count() > 0: if new_sticky._came_from_panel and sticky_note_container.get_child_count() > 0:
# New sticky came from panel - return old sticky to that panel (swap positions) # New sticky came from panel - return old sticky to that panel (swap positions)
@ -290,7 +290,7 @@ func _handle_sticky_exchange(new_sticky: StickyNote, card: Card) -> void:
else: else:
# New sticky was loose - create new panel for old sticky # New sticky was loose - create new panel for old sticky
add_sticky_note(old_sticky) add_sticky_note(old_sticky)
# Clean up empty panel if the new sticky came from one # Clean up empty panel if the new sticky came from one
if new_sticky._came_from_panel and sticky_note_container.get_child_count() > 0: if new_sticky._came_from_panel and sticky_note_container.get_child_count() > 0:
sticky_note_container.get_child(current_sticky_note_id).clear_if_empty() sticky_note_container.get_child(current_sticky_note_id).clear_if_empty()
@ -413,16 +413,16 @@ func _sort_dropzone_children() -> void:
var children = dropzone.get_children() var children = dropzone.get_children()
if children.size() <= 1: if children.size() <= 1:
return return
# Sort by global Y position # Sort by global Y position
children.sort_custom(func(a, b): return a.global_position.y < b.global_position.y) children.sort_custom(func(a, b): return a.global_position.y < b.global_position.y)
# Reorder children in the scene tree # Reorder children in the scene tree
for i in range(children.size()): for i in range(children.size()):
dropzone.move_child(children[i], i) dropzone.move_child(children[i], i)
print_debug("CardBoard: Re-sorted %d dropzone children by Y position" % children.size()) print_debug("CardBoard: Re-sorted %d dropzone children by Y position" % children.size())
# Force collision shape updates on next physics frame # Force collision shape updates on next physics frame
# This ensures Area2D hover detection works correctly after repositioning # This ensures Area2D hover detection works correctly after repositioning
_update_collision_shapes.call_deferred() _update_collision_shapes.call_deferred()
@ -447,7 +447,7 @@ func can_accept_drop(draggable: Draggable) -> bool:
func handle_drop(draggable: Draggable) -> int: func handle_drop(draggable: Draggable) -> int:
if not can_accept_drop(draggable): if not can_accept_drop(draggable):
return Draggable.DropResult.REJECTED return Draggable.DropResult.REJECTED
if draggable is StickyNote: if draggable is StickyNote:
# Handle sticky note drop # Handle sticky note drop
var sticky = draggable as StickyNote var sticky = draggable as StickyNote
@ -462,7 +462,7 @@ func handle_drop(draggable: Draggable) -> int:
# Handle card drop # Handle card drop
insert_area(dropzone, draggable) insert_area(dropzone, draggable)
draggable.is_dragable = true draggable.is_dragable = true
return Draggable.DropResult.ACCEPTED return Draggable.DropResult.ACCEPTED
@ -710,14 +710,14 @@ func initialise_from_save(savegame: SaveGame) -> void:
else: else:
target_position = _generate_random_position() target_position = _generate_random_position()
print_debug(" Card '%s' - generated random position: %s" % [card.name, target_position]) print_debug(" Card '%s' - generated random position: %s" % [card.name, target_position])
# Add to board first # Add to board first
add_child(card) add_child(card)
card.set_owner(self) card.set_owner(self)
card.is_dragable = true card.is_dragable = true
cards_by_name[card.name] = card cards_by_name[card.name] = card
card.picked_random = savegame.board_randoms.has(card.card_id) card.picked_random = savegame.board_randoms.has(card.card_id)
# Move to dropzone and set position (position must be set after adding to scene) # Move to dropzone and set position (position must be set after adding to scene)
insert_area(dropzone, card) insert_area(dropzone, card)
card.position = target_position card.position = target_position
@ -754,7 +754,7 @@ func initialise_from_save(savegame: SaveGame) -> void:
else: else:
target_position = _generate_random_position() target_position = _generate_random_position()
print_debug(" Loose sticky '%s' - generated random position: %s" % [sticky.name, target_position]) print_debug(" Loose sticky '%s' - generated random position: %s" % [sticky.name, target_position])
# Add to board first # Add to board first
add_child(sticky) add_child(sticky)
sticky.set_owner(self) sticky.set_owner(self)
@ -762,7 +762,7 @@ func initialise_from_save(savegame: SaveGame) -> void:
sticky.on_board = true sticky.on_board = true
sticky.attached_to = self sticky.attached_to = self
sticky.is_dragable = true sticky.is_dragable = true
# Move to dropzone and set position (position must be set after adding to scene) # Move to dropzone and set position (position must be set after adding to scene)
insert_area(dropzone, sticky) insert_area(dropzone, sticky)
sticky.position = target_position sticky.position = target_position
@ -770,11 +770,11 @@ func initialise_from_save(savegame: SaveGame) -> void:
sticky.picked_random = savegame.board_randoms.has(sticky.sticky_id) sticky.picked_random = savegame.board_randoms.has(sticky.sticky_id)
print_debug("CardBoard: Load complete!") print_debug("CardBoard: Load complete!")
# Re-sort dropzone children now that all positions are set correctly # Re-sort dropzone children now that all positions are set correctly
# This fixes hover detection issues caused by incorrect z-order during load # This fixes hover detection issues caused by incorrect z-order during load
_sort_dropzone_children() _sort_dropzone_children()
# Note: Lore feedback will be triggered when board is presented (in play()) # Note: Lore feedback will be triggered when board is presented (in play())