diff --git a/data/body_parts/head_default.tres b/data/body_parts/head_default.tres new file mode 100644 index 0000000..f803db1 --- /dev/null +++ b/data/body_parts/head_default.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="BodyPartData" load_steps=2 format=3] + +[ext_resource type="Script" path="res://scripts/upgrades/body_part_data.gd" id="1"] + +[resource] +script = ExtResource("1") +slot = "head" +display_name = "Default Head" diff --git a/data/body_parts/left_arm_default.tres b/data/body_parts/left_arm_default.tres new file mode 100644 index 0000000..7f449df --- /dev/null +++ b/data/body_parts/left_arm_default.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="BodyPartData" load_steps=2 format=3] + +[ext_resource type="Script" path="res://scripts/upgrades/body_part_data.gd" id="1"] + +[resource] +script = ExtResource("1") +slot = "left_arm" +display_name = "Default Left Arm" diff --git a/data/body_parts/legs_default.tres b/data/body_parts/legs_default.tres new file mode 100644 index 0000000..6844909 --- /dev/null +++ b/data/body_parts/legs_default.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="BodyPartData" load_steps=2 format=3] + +[ext_resource type="Script" path="res://scripts/upgrades/body_part_data.gd" id="1"] + +[resource] +script = ExtResource("1") +slot = "legs" +display_name = "Default Legs" diff --git a/data/body_parts/right_arm_default.tres b/data/body_parts/right_arm_default.tres new file mode 100644 index 0000000..2f832f9 --- /dev/null +++ b/data/body_parts/right_arm_default.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="BodyPartData" load_steps=2 format=3] + +[ext_resource type="Script" path="res://scripts/upgrades/body_part_data.gd" id="1"] + +[resource] +script = ExtResource("1") +slot = "right_arm" +display_name = "Default Right Arm" diff --git a/data/body_parts/torso_default.tres b/data/body_parts/torso_default.tres new file mode 100644 index 0000000..742ab9e --- /dev/null +++ b/data/body_parts/torso_default.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="BodyPartData" load_steps=2 format=3] + +[ext_resource type="Script" path="res://scripts/upgrades/body_part_data.gd" id="1"] + +[resource] +script = ExtResource("1") +slot = "torso" +display_name = "Default Torso" diff --git a/scripts/enemies/warden.gd b/scripts/enemies/warden.gd index 1d87ba5..2107731 100644 --- a/scripts/enemies/warden.gd +++ b/scripts/enemies/warden.gd @@ -19,13 +19,13 @@ const ORBIT_SPEED_P1 := 0.55 # rad/sec ≈ 31 deg/sec const ORBIT_SPEED_P2 := 0.85 # rad/sec ≈ 49 deg/sec const TELEGRAPH_TIME := 0.8 -const PASS_DELAY := 1.2 +const PASS_DELAY := 1.8 const SWEEP_SPEED_P1 := 50.0 const SWEEP_SPEED_P2 := 85.0 const SWEEP_CD_P1 := 6.5 const SWEEP_CD_P2 := 4.5 -const PROJ_SPACING := 26.0 +const PROJ_SPACING := 18.0 const GAP_W := 90.0 const MINE_CD_P1 := 4.0 diff --git a/scripts/ui/armory_ui.gd b/scripts/ui/armory_ui.gd index fcd336e..52de41a 100644 --- a/scripts/ui/armory_ui.gd +++ b/scripts/ui/armory_ui.gd @@ -106,12 +106,30 @@ func open() -> void: show() +# --------------------------------------------------------------------------- +# Default body parts (always available) +# --------------------------------------------------------------------------- +const DEFAULT_PARTS: Array[String] = [ + "res://data/body_parts/head_default.tres", + "res://data/body_parts/torso_default.tres", + "res://data/body_parts/left_arm_default.tres", + "res://data/body_parts/right_arm_default.tres", + "res://data/body_parts/legs_default.tres", +] + # --------------------------------------------------------------------------- # Rebuild item list from UpgradeManager # --------------------------------------------------------------------------- func _rebuild_items() -> void: _items.clear() + # Add default parts first (always available) + for path: String in DEFAULT_PARTS: + var part := load(path) as BodyPartData + if part: + _items.append(part) + + # Add acquired parts for path: String in UpgradeManager.acquired_part_paths: if path == "": continue @@ -140,7 +158,9 @@ func _refresh_labels() -> void: for i in _item_labels.size(): var part: BodyPartData = _items[i] var equipped_path: String = UpgradeManager.equipped_parts.get(part.slot, "") - var is_equipped := equipped_path == part.resource_path + # Check if this part is equipped (empty string means default is equipped) + var is_default_part := part.resource_path in DEFAULT_PARTS + var is_equipped := equipped_path == part.resource_path or (equipped_path == "" and is_default_part) var is_cursor := i == _cursor var slot_tag := "[%s]" % part.slot.to_upper() diff --git a/scripts/ui/hud.gd b/scripts/ui/hud.gd index d543088..2e004d4 100644 --- a/scripts/ui/hud.gd +++ b/scripts/ui/hud.gd @@ -55,6 +55,7 @@ var _mini_map: Control func _ready() -> void: EventBus.player_health_changed.connect(_on_health_changed) EventBus.credits_changed.connect(_on_credits_changed) + EventBus.save_loaded.connect(_on_save_loaded) # DEPRECATED — Boss bar signal connections (commented out) #EventBus.boss_health_changed.connect(_on_boss_health_changed) #EventBus.boss_died.connect(_on_boss_died) @@ -139,6 +140,10 @@ func _build_mini_map() -> void: func _on_credits_changed(new_total: int) -> void: _credits_label.text = "SCRAP: %d" % new_total +func _on_save_loaded() -> void: + var amount := RunManager.run_credits if RunManager.run_active else UpgradeManager.wallet_credits + _credits_label.text = "SCRAP: %d" % amount + # --------------------------------------------------------------------------- # Signal handler # --------------------------------------------------------------------------- diff --git a/scripts/ui/mini_map.gd b/scripts/ui/mini_map.gd index df8124b..c788c1f 100644 --- a/scripts/ui/mini_map.gd +++ b/scripts/ui/mini_map.gd @@ -4,10 +4,15 @@ extends Control # Layout constants # --------------------------------------------------------------------------- const MAP_SIZE := Vector2(150, 150) -const ROOM_SIZE := Vector2(18, 10) # 16:9 aspect ratio like actual rooms +const ROOM_SIZE := Vector2(26, 15) # 16:9 aspect ratio like actual rooms const ROOM_GAP := 4.0 const PADDING := 10.0 const CONNECTION_WIDTH := 2.0 +const PARALLAX_STRENGTH := 4.0 # max pixels the map shifts with player movement + +# Room dimensions (must match floor.gd) +const ROOM_W := 960.0 +const ROOM_H := 540.0 # --------------------------------------------------------------------------- # Colors (brightened versions of room.gd floor colors) @@ -31,6 +36,8 @@ var _rooms_data: Dictionary = {} # Vector2i -> RoomData var _current_pos: Vector2i = Vector2i.ZERO var _grid_min: Vector2i = Vector2i.ZERO var _grid_max: Vector2i = Vector2i.ZERO +var _parallax_offset: Vector2 = Vector2.ZERO +var _player: Node2D = null # --------------------------------------------------------------------------- # Setup @@ -68,8 +75,34 @@ func _on_room_entered(grid_pos: Vector2i) -> void: func _on_run_ended(_reached_hub: bool) -> void: _rooms_data.clear() + _player = null queue_redraw() + +func _process(_delta: float) -> void: + if _rooms_data.is_empty(): + return + + # Find player if not cached + if _player == null: + _player = get_tree().get_first_node_in_group("player") + if _player == null: + return + + # Calculate player position within current room (-0.5 to 0.5 range) + var room_center := Vector2(_current_pos.x * ROOM_W, _current_pos.y * ROOM_H) + var local_pos := _player.global_position - room_center + var normalized := Vector2( + clampf(local_pos.x / (ROOM_W * 0.5), -1.0, 1.0), + clampf(local_pos.y / (ROOM_H * 0.5), -1.0, 1.0) + ) + + # Apply subtle parallax (inverted so map moves opposite to player) + var new_offset := -normalized * PARALLAX_STRENGTH + if not new_offset.is_equal_approx(_parallax_offset): + _parallax_offset = new_offset + queue_redraw() + # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- @@ -120,8 +153,8 @@ func _grid_to_map_pos(grid_pos: Vector2i) -> Vector2: var grid_size := Vector2i(_grid_max.x - _grid_min.x + 1, _grid_max.y - _grid_min.y + 1) var total_size := Vector2(grid_size.x, grid_size.y) * cell_size - Vector2(ROOM_GAP, ROOM_GAP) - # Center the map within the control - var centering := (MAP_SIZE - total_size) / 2.0 + # Center the map within the control, apply parallax offset + var centering := (MAP_SIZE - total_size) / 2.0 + _parallax_offset var offset := Vector2( (grid_pos.x - _grid_min.x) * cell_size.x, (grid_pos.y - _grid_min.y) * cell_size.y