From 7aec731e80b3ef7abfd3b70607dfdff18cdab316 Mon Sep 17 00:00:00 2001 From: autocommit Date: Wed, 3 Jun 2026 06:03:32 -0700 Subject: [PATCH] =?UTF-8?q?remove(entities):=20=F0=9F=94=A5=20Remove=20com?= =?UTF-8?q?bat=20utility=20functions=20from=20GDScript=20after=20migration?= =?UTF-8?q?=20to=20Rust-based=20resolver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- src/game/engine/src/entities/combat_utils.gd | 171 ------------------ .../engine/src/entities/combat_utils.gd.uid | 1 - 2 files changed, 172 deletions(-) delete mode 100644 src/game/engine/src/entities/combat_utils.gd delete mode 100644 src/game/engine/src/entities/combat_utils.gd.uid diff --git a/src/game/engine/src/entities/combat_utils.gd b/src/game/engine/src/entities/combat_utils.gd deleted file mode 100644 index fa48c12e..00000000 --- a/src/game/engine/src/entities/combat_utils.gd +++ /dev/null @@ -1,171 +0,0 @@ -class_name CombatUtils -extends RefCounted -## Static utility functions for combat: unit/city lookup, death handling, siege capture. -## No damage computation lives here — all combat math is in Rust (GdCombatResolver). - -const UnitScript = preload("res://engine/src/entities/unit.gd") -const CityScript = preload("res://engine/src/entities/city.gd") -const HexUtilsScript = preload("res://engine/src/map/hex_utils.gd") -const ItemSystemScript = preload("res://engine/src/modules/management/item_system.gd") - - -## Get garrison combat unit at a city tile. -static func get_garrison(pos: Vector2i, all_units: Array) -> RefCounted: - for unit: RefCounted in all_units: - if unit is UnitScript and unit.position == pos and unit.is_military(): - return unit - return null - - -## Get all units at a position. -static func get_units_at(pos: Vector2i, all_units: Array) -> Array: - var result: Array = [] - for unit: RefCounted in all_units: - if unit is UnitScript and unit.position == pos: - result.append(unit) - return result - - -## Get all specialist units at a position owned by non-attacker. -static func get_specialists_at(pos: Vector2i, all_units: Array, attacker_owner: int) -> Array: - var result: Array = [] - for unit: RefCounted in all_units: - if unit is UnitScript and unit.position == pos and unit.owner != attacker_owner: - if unit.is_specialist(): - result.append(unit) - return result - - -## Get all units adjacent to a position. -static func get_adjacent_units(pos: Vector2i, all_units: Array) -> Array: - var neighbors: Array[Vector2i] = HexUtilsScript.get_neighbors(pos) - var result: Array = [] - for neighbor_pos: Vector2i in neighbors: - for unit: RefCounted in all_units: - if unit is UnitScript and unit.position == neighbor_pos: - result.append(unit) - return result - - -## Get the city at a position (if any) from GameState. -static func get_city_at(pos: Vector2i) -> RefCounted: - for player: RefCounted in GameState.players: - for city: RefCounted in player.cities: - if city is CityScript and city.position == pos: - return city - return null - - -## Whether this unit is a siege unit (gets bonus vs cities). -static func is_siege_unit(unit: RefCounted) -> bool: - if unit is UnitScript: - return unit.get_combat_type() == "siege" - return false - - -## Handle a unit's death: check soul gem, drop loot, remove from game state, emit signal. -static func handle_unit_death(unit: RefCounted, killer: RefCounted, all_units: Array) -> void: - if not unit is UnitScript: - return - - # Soul Gem check: resurrect at 30% HP instead of dying. - if ItemSystemScript.has_active_item(unit, "soul_gem"): - ItemSystemScript.consume_charge(unit, "soul_gem") - unit.hp = maxi(int(float(unit.get_max_hp()) * 0.3), 1) - return - - # Drop equipped items as ground loot before removing the unit. - # ItemSystem.drop_all_loot wants the dying unit's tile, not the whole - # map — passing the map used to Array-type-error the FFI and abort the - # death handler before it could emit unit_destroyed. - var primary_layer: Dictionary = GameState.get_primary_layer() - if not primary_layer.is_empty(): - var game_map: RefCounted = primary_layer.get("map") - if game_map != null: - var tile: Resource = game_map.get_tile(unit.position) as Resource - if tile != null: - ItemSystemScript.drop_all_loot(unit, tile) - - if unit.owner == -1 and killer != null and killer is UnitScript and killer.owner >= 0: - _roll_wild_creature_loot(unit, killer) - - all_units.erase(unit) - - if unit.owner >= 0 and unit.owner < GameState.players.size(): - var player: RefCounted = GameState.players[unit.owner] - player.units.erase(unit) - - if not primary_layer.is_empty(): - primary_layer.get("units", []).erase(unit) - - EventBus.unit_destroyed.emit(unit, killer) - - -## Handle city capture: transfer ownership, emit signals, destroy High Archon if capital. -static func capture_city( - city: RefCounted, - attacker: RefCounted, - old_owner: int, - all_units: Array, -) -> void: - var old_player: RefCounted = GameState.get_player(old_owner) - var new_player: RefCounted = GameState.get_player(attacker.owner) - if old_player != null: - old_player.cities.erase(city) - # p1-29a — increment cumulative city-loss counter on the dispossessed - # player. Drives last-stand defense multiplier when they reach 1 city - # remaining. Never decremented (persists even on recapture). - old_player.cities_lost_total += 1 - if new_player != null and city not in new_player.cities: - new_player.cities.append(city) - - city.owner = attacker.owner - city.is_capital = false - city.captured_turn = GameState.turn_number - - for tile_pos: Vector2i in city.owned_tiles: - var layer: Dictionary = GameState.get_primary_layer() - if layer.is_empty(): - continue - var map_ref: RefCounted = layer.get("map") - if map_ref == null: - continue - var t: RefCounted = map_ref.get_tile(tile_pos) - if t != null: - t.owner = attacker.owner - - if old_player != null: - _destroy_high_archon(old_player, all_units) - - EventBus.city_captured.emit(city, old_owner, attacker.owner) - - if old_player != null and old_player.cities.is_empty() and not old_player.is_eliminated: - # Latch dedupes against victory_manager._reconcile_eliminations, - # which sweeps the same condition each turn. - old_player.is_eliminated = true - EventBus.player_eliminated.emit(old_owner) - - -static func _roll_wild_creature_loot(victim: RefCounted, killer: RefCounted) -> void: - if killer.owner < 0 or killer.owner >= GameState.players.size(): - return - var killer_player: RefCounted = GameState.players[killer.owner] - var creature_type: String = victim.type_id if victim.type_id != "" else victim.unit_id - var turn_seed: int = GameState.game_rng.seed ^ GameState.turn_number - var killer_id: int = hash(killer.id) - var victim_id: int = hash(victim.id) - ItemSystemScript.roll_fauna_drops(creature_type, killer_player, turn_seed, killer_id, victim_id) - - -## Destroy the High Archon of a player (capital capture penalty). -static func _destroy_high_archon(player: RefCounted, all_units: Array) -> void: - for unit: RefCounted in player.units: - if unit is UnitScript and unit.type_id == "high_archon": - unit.hp = 0 - all_units.erase(unit) - player.units.erase(unit) - var primary_layer: Dictionary = GameState.get_primary_layer() - if not primary_layer.is_empty(): - primary_layer.get("units", []).erase(unit) - EventBus.unit_destroyed.emit(unit, null) - break diff --git a/src/game/engine/src/entities/combat_utils.gd.uid b/src/game/engine/src/entities/combat_utils.gd.uid deleted file mode 100644 index a93bc9d1..00000000 --- a/src/game/engine/src/entities/combat_utils.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://e7rxe1g4o8hn