diff --git a/src/base-environments/youth_room/climb_volume.gd b/src/base-environments/youth_room/climb_volume.gd index 7c090e6..107c421 100644 --- a/src/base-environments/youth_room/climb_volume.gd +++ b/src/base-environments/youth_room/climb_volume.gd @@ -18,6 +18,8 @@ func raise(body) -> void: raiser = create_tween() raiser.tween_property(self, "position", start_position + Vector3(0,1.1,0), 1) risen = true + await get_tree().create_timer(5).timeout + reset(false) func reset(_discard) -> void: diff --git a/src/base-environments/youth_room/youth_room.tscn b/src/base-environments/youth_room/youth_room.tscn index b1a40de..3c53269 100644 --- a/src/base-environments/youth_room/youth_room.tscn +++ b/src/base-environments/youth_room/youth_room.tscn @@ -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="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" 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="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"] diff --git a/src/dev-util/hardcoded_cards.gd b/src/dev-util/hardcoded_cards.gd index d1c32ad..9e12970 100644 --- a/src/dev-util/hardcoded_cards.gd +++ b/src/dev-util/hardcoded_cards.gd @@ -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_id_reference: Dictionary[StringName, StringName] = generate_id_reference(false, true) -var obscure_reference: Dictionary[StringName, StringName] = generate_obscure_reference() +var sticky_ids: Dictionary[StringName, StringName] = generate_id_reference(false, true) +var obscure_ids: Dictionary[StringName, StringName] = generate_obscure_reference() func generate_id_reference(include_cards: bool, include_sticky: bool) -> Dictionary[StringName, StringName]: var out:Dictionary[StringName, StringName] = {} - + for id in range(source_dicts.size()): for card_name:String in source_dicts[id].keys(): 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]: if sticky_name is String: out[sticky_name] = "%d.%s.%s" % [id, card_name, sticky_name] - + return out func generate_obscure_reference(): var out:Dictionary[StringName, StringName] = {} - + randomize() var salt = randi_range(1111, 9999) - + for id in range(source_dicts.size()): for card_name:String in source_dicts[id].keys(): out[card_name] = StringName("%d.%d" % [id, card_name.hash() % salt ]) - + for sticky_name in source_dicts[id][card_name]: if sticky_name is String: out[sticky_name] = StringName("%d.%s.%s" % [id, card_name.hash() % salt, sticky_name.hash() % salt]) - + return out - + func get_child_names_of(parent_id: StringName) -> Array[StringName]: var out: Array[StringName] - for child_name: StringName in id_reference.keys(): - if id_reference[child_name].contains(parent_id): + for child_name: StringName in all_ids.keys(): + if all_ids[child_name].contains(parent_id): if child_name != parent_id: out.append(child_name) return out @@ -117,23 +117,21 @@ func get_children_of(parent_id: StringName) -> Array: func get_obscure_name(card_name: StringName): if State.obscure_logs and not OS.is_debug_build(): - return obscure_reference[card_name] + return obscure_ids[card_name] else: return card_name func arrange(cards: Array[Card], rect: Rect2, _obstacles: Array[Area2D]) -> Array[Card]: - #var total_cards := cards.size() - var x:int = 0 var y:int = 0 var i:int = 0 var maximum:int = cards.size() var grid: int = ceil(sqrt(maximum)) var diameter:float = cards[0].diameter - + var r_cards: Array[Card] = cards.duplicate() r_cards.shuffle() - + while i < maximum: while x < grid 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 for card: Card in r_cards: - + for _i in range(20): - + if is_out_of_bounds(card, rect): card.position = rect.get_center() - card.position * 0.8 continue @@ -159,11 +157,11 @@ func arrange(cards: Array[Card], rect: Rect2, _obstacles: Array[Area2D]) -> Arra for colliding in colliders: if (colliding.position - card.position).length() > (nearest.position - card.position).length(): nearest = colliding - + card.position += min(nearest.position - card.position.normalized() * (card.diameter + 1), nearest.position - card.position) continue break - + return r_cards @@ -175,7 +173,7 @@ func is_out_of_bounds(card: Card, rect: Rect2): Transform2D(0, rect.position+rect.size) ] var shape: = WorldBoundaryShape2D.new() - + for boundary:Transform2D in world_boundaries: if card.collider.collide(card.transform, shape, boundary): 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]: var output:Array[Card] - + for card_name in source_dicts[id].keys(): 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) - + return output # 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": [], "sticky_notes": [] } - + for card_name:StringName in names: - if card_id_reference.has(card_name): - output["cards"].append(create_from_id(id_reference[card_name])) + if card_ids.has(card_name): + output["cards"].append(create_from_id(all_ids[card_name])) 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 func create_from_id(id:StringName) -> Area2D: - var parsed: PackedStringArray = id.rsplit(".") - if card_id_reference.values().has(id): + var parsed: PackedStringArray = id.rsplit(".") + if card_ids.values().has(id): var card := card_prefab.instantiate() as Card card.init(parsed[1], id); return card - elif sticky_id_reference.values().has(id): + elif sticky_ids.values().has(id): var note := note_prefab.instantiate() as StickyNote note.init(parsed[2], id) return note @@ -223,31 +223,30 @@ func create_from_id(id:StringName) -> Area2D: func create_dev_board(parent: Control, _rect: Rect2) -> void: var scroll_container := ScrollContainer.new() var panel := Panel.new() - + parent.add_child(scroll_container) scroll_container.add_child(panel) - + for x in range(source_dicts.size()): var sub_parent := Panel.new() sub_parent.position = Vector2( 128 + 256*x , 0) panel.add_child(sub_parent, false, Node.INTERNAL_MODE_BACK) var y := 1 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) card.position = Vector2(0, card.diameter * y - card.diameter/2) - + var z := 0 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) sticky.position = card.sticky_note_position + Vector2(0, 80) * z z += 1 y += 1 - + panel.custom_minimum_size.x = source_dicts.size() * 256 func _ready() -> void: create_dev_board(self, get_viewport().get_visible_rect()) TranslationServer.set_locale("en") - diff --git a/src/logic-scenes/board/card-board.gd b/src/logic-scenes/board/card-board.gd index f7851b1..6974483 100644 --- a/src/logic-scenes/board/card-board.gd +++ b/src/logic-scenes/board/card-board.gd @@ -137,7 +137,7 @@ func _on_board_focused() -> void: visible = true if is_node_ready(): process_mode = Node.PROCESS_MODE_INHERIT - + # Check board state and give lore feedback when presented if is_board_complete(): board_was_completed = true @@ -212,12 +212,12 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act # Prevent dragging multiple nodes at once if current_context == DRAG and to_handle != currently_active_node: return - + # === DRAG START === if input.button_index == MOUSE_BUTTON_LEFT and input.pressed: _start_drag(to_handle) return - + # === DRAG END === if input.button_index == MOUSE_BUTTON_LEFT and not input.pressed: _end_drag(to_handle) @@ -228,7 +228,7 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act func _start_drag(draggable: Draggable) -> void: currently_active_node = draggable current_context = DRAG - + var mouse_offset = get_viewport().get_mouse_position() - draggable.global_position draggable.start_drag(mouse_offset) @@ -236,14 +236,14 @@ func _start_drag(draggable: Draggable) -> void: ## Ends a drag operation and handles the drop func _end_drag(draggable: Draggable) -> void: draggable.end_drag() - + # Let draggable find its own drop target var drop_target = draggable.find_drop_target() - + # Execute the drop if drop_target and Draggable.is_drop_target(drop_target): var result = drop_target.handle_drop(draggable) - + # Handle exchange result (sticky swapped with card's sticky) if result == Draggable.DropResult.EXCHANGED: _handle_sticky_exchange(draggable, drop_target) @@ -253,12 +253,12 @@ func _end_drag(draggable: Draggable) -> void: else: # Fallback: use default board drop handle_drop(draggable) - + # Cleanup and state update _return_sticky_notes_to_panels() current_context = NAVIGATE _update_focus_after_drop(draggable) - + # Check win condition if sticky was attached to card if draggable is StickyNote and draggable.is_sticky_note_attached(): 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) func _handle_sticky_exchange(new_sticky: StickyNote, card: Card) -> void: var old_sticky = card.get_last_exchanged_sticky() - + if not old_sticky: push_warning("CardBoard: Exchange occurred but no sticky returned") return - + # Reset visual state for old sticky old_sticky.rotation = old_sticky.base_rotation old_sticky.scale = old_sticky.base_scale old_sticky.z_index = 0 - + # Exchanged sticky always goes to sticky_note_container 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) @@ -290,7 +290,7 @@ func _handle_sticky_exchange(new_sticky: StickyNote, card: Card) -> void: else: # New sticky was loose - create new panel for old sticky add_sticky_note(old_sticky) - + # 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: 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() if children.size() <= 1: return - + # Sort by global Y position children.sort_custom(func(a, b): return a.global_position.y < b.global_position.y) - + # Reorder children in the scene tree for i in range(children.size()): dropzone.move_child(children[i], i) - + print_debug("CardBoard: Re-sorted %d dropzone children by Y position" % children.size()) - + # Force collision shape updates on next physics frame # This ensures Area2D hover detection works correctly after repositioning _update_collision_shapes.call_deferred() @@ -447,7 +447,7 @@ func can_accept_drop(draggable: Draggable) -> bool: func handle_drop(draggable: Draggable) -> int: if not can_accept_drop(draggable): return Draggable.DropResult.REJECTED - + if draggable is StickyNote: # Handle sticky note drop var sticky = draggable as StickyNote @@ -462,7 +462,7 @@ func handle_drop(draggable: Draggable) -> int: # Handle card drop insert_area(dropzone, draggable) draggable.is_dragable = true - + return Draggable.DropResult.ACCEPTED @@ -710,14 +710,14 @@ func initialise_from_save(savegame: SaveGame) -> void: else: target_position = _generate_random_position() print_debug(" Card '%s' - generated random position: %s" % [card.name, target_position]) - + # Add to board first add_child(card) card.set_owner(self) card.is_dragable = true cards_by_name[card.name] = card card.picked_random = savegame.board_randoms.has(card.card_id) - + # Move to dropzone and set position (position must be set after adding to scene) insert_area(dropzone, card) card.position = target_position @@ -754,7 +754,7 @@ func initialise_from_save(savegame: SaveGame) -> void: else: target_position = _generate_random_position() print_debug(" Loose sticky '%s' - generated random position: %s" % [sticky.name, target_position]) - + # Add to board first add_child(sticky) sticky.set_owner(self) @@ -762,7 +762,7 @@ func initialise_from_save(savegame: SaveGame) -> void: sticky.on_board = true sticky.attached_to = self sticky.is_dragable = true - + # Move to dropzone and set position (position must be set after adding to scene) insert_area(dropzone, sticky) 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) print_debug("CardBoard: Load complete!") - + # Re-sort dropzone children now that all positions are set correctly # This fixes hover detection issues caused by incorrect z-order during load _sort_dropzone_children() - + # Note: Lore feedback will be triggered when board is presented (in play())