From b1b040bacdbdb81ceec553094a36343b0934d643 Mon Sep 17 00:00:00 2001 From: Mike McGhen Date: Thu, 12 Mar 2026 16:47:56 -0400 Subject: [PATCH] Small changes --- scripts/enemies/hivemind.gd | 13 +++--- scripts/enemies/relay.gd | 13 +++--- scripts/enemies/warden.gd | 13 +++--- scripts/rooms/room.gd | 84 ++++++++++++++++--------------------- scripts/run_manager.gd | 32 ++++++++++++++ 5 files changed, 87 insertions(+), 68 deletions(-) diff --git a/scripts/enemies/hivemind.gd b/scripts/enemies/hivemind.gd index 44fd53c..aeea365 100644 --- a/scripts/enemies/hivemind.gd +++ b/scripts/enemies/hivemind.gd @@ -991,19 +991,18 @@ func _die() -> void: queue_free() func _spawn_item_drop() -> void: - # Filter out already collected items + # Filter out shop-only items and already collected/spawned items + const PATCH_KIT_PATH := "res://data/run_items/patch_kit.tres" var available: Array[String] = [] for path in ALL_ITEM_PATHS: - var already_collected := false - for collected in RunManager.run_items: - if collected.resource_path == path: - already_collected = true - break - if not already_collected: + if path == PATCH_KIT_PATH: + continue + if RunManager.is_item_available(path): available.append(path) if available.is_empty(): return var chosen: String = available[randi() % available.size()] + RunManager.reserve_item(chosen) var pickup = RUN_ITEM_PICKUP.instantiate() pickup.item = load(chosen) var spawn_pos := global_position + Vector2(-30, 0) diff --git a/scripts/enemies/relay.gd b/scripts/enemies/relay.gd index b365e87..c1fc2de 100644 --- a/scripts/enemies/relay.gd +++ b/scripts/enemies/relay.gd @@ -466,19 +466,18 @@ func _die() -> void: queue_free() func _spawn_item_drop() -> void: - # Filter out already collected items + # Filter out shop-only items and already collected/spawned items + const PATCH_KIT_PATH := "res://data/run_items/patch_kit.tres" var available: Array[String] = [] for path in ALL_ITEM_PATHS: - var already_collected := false - for collected in RunManager.run_items: - if collected.resource_path == path: - already_collected = true - break - if not already_collected: + if path == PATCH_KIT_PATH: + continue + if RunManager.is_item_available(path): available.append(path) if available.is_empty(): return var chosen: String = available[randi() % available.size()] + RunManager.reserve_item(chosen) var pickup = RUN_ITEM_PICKUP.instantiate() pickup.item = load(chosen) var spawn_pos := global_position + Vector2(-30, 0) diff --git a/scripts/enemies/warden.gd b/scripts/enemies/warden.gd index 81221d2..19ae589 100644 --- a/scripts/enemies/warden.gd +++ b/scripts/enemies/warden.gd @@ -420,19 +420,18 @@ func _die() -> void: queue_free() func _spawn_item_drop() -> void: - # Filter out already collected items + # Filter out shop-only items and already collected/spawned items + const PATCH_KIT_PATH := "res://data/run_items/patch_kit.tres" var available: Array[String] = [] for path in ALL_ITEM_PATHS: - var dominated := false - for collected in RunManager.run_items: - if collected.resource_path == path: - dominated = true - break - if not dominated: + if path == PATCH_KIT_PATH: + continue + if RunManager.is_item_available(path): available.append(path) if available.is_empty(): return var chosen: String = available[randi() % available.size()] + RunManager.reserve_item(chosen) var pickup = RUN_ITEM_PICKUP.instantiate() pickup.item = load(chosen) var spawn_pos := global_position + Vector2(-30, 0) diff --git a/scripts/rooms/room.gd b/scripts/rooms/room.gd index 090c15f..fdb2dc5 100644 --- a/scripts/rooms/room.gd +++ b/scripts/rooms/room.gd @@ -397,18 +397,13 @@ func _spawn_body_part_drop() -> void: contents.add_child(pickup) func _spawn_run_item() -> void: - # Exclude Patch Kit from item rooms (shop-only item) and already collected items + # Exclude shop-only items (Patch Kit) and already collected/spawned items const PATCH_KIT_PATH := "res://data/run_items/patch_kit.tres" var item_pool: Array[String] = [] for p in ALL_ITEM_PATHS: if p == PATCH_KIT_PATH: continue - var already_collected := false - for collected in RunManager.run_items: - if collected.resource_path == p: - already_collected = true - break - if not already_collected: + if RunManager.is_item_available(p): item_pool.append(p) if item_pool.is_empty(): @@ -416,6 +411,7 @@ func _spawn_run_item() -> void: return var chosen: String = item_pool[randi() % item_pool.size()] + RunManager.reserve_item(chosen) # Mark as spawned so other rooms won't use it var pickup = RUN_ITEM_PICKUP.instantiate() pickup.item = load(chosen) pickup.position = Vector2.ZERO @@ -597,64 +593,58 @@ func _make_exposed_wiring() -> void: contents.add_child(area) # --------------------------------------------------------------------------- -# Shop spawning — 2 random items + 1 Patch Kit, spaced horizontally +# Shop spawning — 2 random items + Patch Kit (restocking heal item) # --------------------------------------------------------------------------- func _spawn_shop() -> void: - # Item slot paths (exclude Patch Kit and already collected items from the random pool) const PATCH_KIT_PATH := "res://data/run_items/patch_kit.tres" + + # Build random item pool (exclude Patch Kit which has its own slot) var item_pool: Array[String] = [] for p in ALL_ITEM_PATHS: if p == PATCH_KIT_PATH: continue - var already_collected := false - for collected in RunManager.run_items: - if collected.resource_path == p: - already_collected = true - break - if not already_collected: + if RunManager.is_item_available(p): item_pool.append(p) item_pool.shuffle() - # Positions: left item, center item, right = Patch Kit + # Positions: left = random, center = random, right = Patch Kit var positions: Array[Vector2] = [ Vector2(-200, 0), Vector2( 0, 0), Vector2( 200, 0), ] - # Check if Patch Kit was already collected - var patch_kit_collected := false - for collected in RunManager.run_items: - if collected.resource_path == PATCH_KIT_PATH: - patch_kit_collected = true - break + # Slot 0: Random item + if item_pool.size() > 0: + RunManager.reserve_item(item_pool[0]) + var pedestal := Area2D.new() + pedestal.set_script(SHOP_PEDESTAL_SCR) + pedestal.position = positions[0] + pedestal.set("item", load(item_pool[0])) + pedestal.set("price", 20) + contents.add_child(pedestal) + else: + _spawn_out_of_stock_marker(positions[0]) - var prices: Array[int] = [20, 20, 10] + # Slot 1: Random item + if item_pool.size() > 1: + RunManager.reserve_item(item_pool[1]) + var pedestal := Area2D.new() + pedestal.set_script(SHOP_PEDESTAL_SCR) + pedestal.position = positions[1] + pedestal.set("item", load(item_pool[1])) + pedestal.set("price", 20) + contents.add_child(pedestal) + else: + _spawn_out_of_stock_marker(positions[1]) - for i in 3: - var pos: Vector2 = positions[i] - if i == 2: - # Patch Kit slot - if patch_kit_collected: - _spawn_out_of_stock_marker(pos) - else: - var pedestal := Area2D.new() - pedestal.set_script(SHOP_PEDESTAL_SCR) - pedestal.position = pos - pedestal.set("item", load(PATCH_KIT_PATH)) - pedestal.set("price", prices[i]) - contents.add_child(pedestal) - else: - # Random item slots - if i < item_pool.size(): - var pedestal := Area2D.new() - pedestal.set_script(SHOP_PEDESTAL_SCR) - pedestal.position = pos - pedestal.set("item", load(item_pool[i])) - pedestal.set("price", prices[i]) - contents.add_child(pedestal) - else: - _spawn_out_of_stock_marker(pos) + # Slot 2: Patch Kit (always available, restocks after purchase) + var patch_pedestal := Area2D.new() + patch_pedestal.set_script(SHOP_PEDESTAL_SCR) + patch_pedestal.position = positions[2] + patch_pedestal.set("item", load(PATCH_KIT_PATH)) + patch_pedestal.set("price", 10) + contents.add_child(patch_pedestal) # --------------------------------------------------------------------------- # Door locking diff --git a/scripts/run_manager.gd b/scripts/run_manager.gd index c5253b0..5acb57b 100644 --- a/scripts/run_manager.gd +++ b/scripts/run_manager.gd @@ -22,6 +22,9 @@ var npc_ids_on_run: Array[String] = [] # --- Floor-to-floor carry (not saved, only lives for one scene reload) --- var player_health_carry: float = -1.0 # -1 = no carry, use default full health +# --- Spawned items on current floor (prevents duplicates across rooms) --- +var spawned_item_paths: Array[String] = [] + # --- Hub spawn flag (cleared after hub reads it) --- var returning_from_run: bool = false @@ -32,6 +35,7 @@ func start_run(brought_credits: int, brought_buffs: Array[Resource], brought_npc player_health_carry = -1.0 run_items.clear() card_packs_found.clear() + spawned_item_paths.clear() credits_brought_in = brought_credits run_credits = brought_credits buff_items_brought = brought_buffs.duplicate() @@ -51,11 +55,37 @@ func end_run(player_survived: bool) -> void: func advance_floor() -> void: EventBus.floor_cleared.emit(current_floor) current_floor += 1 + spawned_item_paths.clear() # Reset for new floor func collect_item(item: Resource) -> void: run_items.append(item) EventBus.item_collected.emit(item) +# --------------------------------------------------------------------------- +# Item spawn tracking — prevents same item appearing in multiple rooms +# --------------------------------------------------------------------------- +const PATCH_KIT_PATH := "res://data/run_items/patch_kit.tres" + +func is_item_available(path: String) -> bool: + # Patch Kit always restocks - can be purchased multiple times + if path == PATCH_KIT_PATH: + return true + # Check if already collected + for collected in run_items: + if collected.resource_path == path: + return false + # Check if already spawned on this floor + if path in spawned_item_paths: + return false + return true + +func reserve_item(path: String) -> void: + # Don't reserve Patch Kit - it can appear in multiple places + if path == PATCH_KIT_PATH: + return + if path not in spawned_item_paths: + spawned_item_paths.append(path) + func collect_card_pack(pack: Resource) -> void: card_packs_found.append(pack) EventBus.card_pack_found.emit(pack) @@ -81,6 +111,7 @@ func _apply_run_rewards() -> void: # Run items are non-permanent — clear them (body parts stay via UpgradeManager) run_items.clear() card_packs_found.clear() + spawned_item_paths.clear() # Health resets on hub return — do not carry it over player_health_carry = -1.0 # NPCs survive @@ -91,6 +122,7 @@ func _apply_run_death() -> void: # Everything brought in / found is lost run_items.clear() card_packs_found.clear() + spawned_item_paths.clear() run_credits = 0 credits_brought_in = 0 buff_items_brought.clear()