diff --git a/src/game/engine/scenes/world_map/world_map.gd b/src/game/engine/scenes/world_map/world_map.gd index 105e09ff..c9810c27 100644 --- a/src/game/engine/scenes/world_map/world_map.gd +++ b/src/game/engine/scenes/world_map/world_map.gd @@ -1125,28 +1125,17 @@ func _found_capital_from_tribe(tribe_unit: RefCounted) -> void: push_warning("WorldMap: dwarf_tribe unit present but prologue is null") return var pid: int = int(tribe_unit.owner) - var result: Dictionary = (TurnManager.prologue as PrologueDriverScript).found_capital(pid) - if result.is_empty(): - push_warning("WorldMap: PrologueDriver.found_capital returned empty for player %d" % pid) - return - var pop: int = int(result.get("population", 1)) - var q: int = int(result.get("q", tribe_unit.position.x)) - var r: int = int(result.get("r", tribe_unit.position.y)) var player: RefCounted = GameState.get_player(pid) if player == null: return - var city: RefCounted = CityScript.new() - city.owner = pid - var city_name: String = "%s Hold" % str(player.player_name) if str(player.player_name) != "" else "Capital" - city.found_with_population(city_name, q, r, true, 1, pop) - player.cities.append(city) - # Consume the Dwarf Tribe unit and forward chronicle events. - _units_helper.remove_unit(tribe_unit, player) - EventBus.unit_destroyed.emit(tribe_unit, null) - EventBus.city_founded.emit(city, pid) - PrologueDriverScript.dispatch_chronicle_events( - result.get("chronicle_events", []) as Array + var city_name: String = ( + "%s Hold" % str(player.player_name) if str(player.player_name) != "" else "Capital" ) + var city: RefCounted = (TurnManager.prologue as PrologueDriverScript).found_capital_for_tribe( + tribe_unit, player, city_name + ) + if city == null: + return _deselect_unit() _sync_units() diff --git a/src/game/engine/src/modules/ai/ai_turn_bridge_dispatch.gd b/src/game/engine/src/modules/ai/ai_turn_bridge_dispatch.gd index ea4b555b..d997b22f 100644 --- a/src/game/engine/src/modules/ai/ai_turn_bridge_dispatch.gd +++ b/src/game/engine/src/modules/ai/ai_turn_bridge_dispatch.gd @@ -145,6 +145,15 @@ static func dispatch_found_city( return false if settler.position != Vector2i(int(at_hex[0]), int(at_hex[1])): return false + # Dwarf Tribe (prologue founder) carries a Lucky-mode founding_pop_override + # computed at convergence; route through PrologueDriver so AI capitals + # receive the same bonus pop the player path applies. + if settler.type_id == "dwarf_tribe" and TurnManager.prologue != null: + var prologue: RefCounted = TurnManager.prologue + var founded: RefCounted = prologue.call( + "found_capital_for_tribe", settler, player, city_name + ) + return founded != null var city: RefCounted = CityScript.new() city.player = player city.owner = player.index diff --git a/src/game/engine/src/modules/management/prologue_driver.gd b/src/game/engine/src/modules/management/prologue_driver.gd index c2917150..38ae62b9 100644 --- a/src/game/engine/src/modules/management/prologue_driver.gd +++ b/src/game/engine/src/modules/management/prologue_driver.gd @@ -117,6 +117,45 @@ func found_capital(player_id: int) -> Dictionary: return _inner.call("found_capital", player_id) as Dictionary +## Found the capital from a Dwarf Tribe unit, applying the prologue's +## `founding_pop_override` (Lucky-mode bonus pop) and consuming the unit. +## Used by both the player path (world_map.gd:_found_capital_from_tribe) +## and the AI dispatch path (ai_turn_bridge_dispatch.dispatch_found_city) +## so AI capitals receive the same Lucky bonus the player does. +## +## Returns the founded City on success, null when the prologue is unavailable +## or returned an empty result. Caller is responsible for any post-found +## bookkeeping (deselect, sync renderers). +func found_capital_for_tribe( + tribe_unit: RefCounted, player: RefCounted, city_name: String +) -> RefCounted: + if not _available or tribe_unit == null or player == null: + return null + var pid: int = int(tribe_unit.owner) + var result: Dictionary = found_capital(pid) + if result.is_empty(): + push_warning( + "PrologueDriver: found_capital returned empty for player %d" % pid + ) + return null + var pop: int = int(result.get("population", 1)) + var q: int = int(result.get("q", tribe_unit.position.x)) + var r: int = int(result.get("r", tribe_unit.position.y)) + var city_script: GDScript = load("res://engine/src/entities/city.gd") as GDScript + var city: RefCounted = city_script.new() + city.owner = pid + city.found_with_population(city_name, q, r, true, 1, pop) + player.cities.append(city) + player.units.erase(tribe_unit) + var primary: Dictionary = GameState.get_primary_layer() + var layer_units: Array = primary.get("units", []) + layer_units.erase(tribe_unit) + EventBus.unit_destroyed.emit(tribe_unit, null) + EventBus.city_founded.emit(city, pid) + dispatch_chronicle_events(result.get("chronicle_events", []) as Array) + return city + + ## Forward chronicle events through EventBus. Called internally on state ## transitions and after found_capital. static func dispatch_chronicle_events(events: Array) -> void: