feat(@projects/@magic-civilization): ✨ add per-tile fauna density updates
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
d0a74e5122
commit
27ade4cd43
4 changed files with 40 additions and 0 deletions
|
|
@ -46,6 +46,17 @@ func tick(grid: RefCounted, seed: int) -> void:
|
|||
fauna_ecology.call("tick_populations", grid, seed)
|
||||
|
||||
|
||||
## Per-tile total fauna population for the live-map fauna overlay
|
||||
## (`fauna_overlay_renderer.gd`). One bulk bridge read per refresh: a Dictionary
|
||||
## keyed by `Vector2i(col, row)` → total population (float). Empty when no
|
||||
## engine or no populations yet (emergence has not fired). The overlay reads
|
||||
## this on each `EventBus.worldsim_updated` and normalizes for its heatmap.
|
||||
func tile_densities() -> Dictionary:
|
||||
if fauna_ecology == null:
|
||||
return {}
|
||||
return fauna_ecology.call("populated_tile_densities")
|
||||
|
||||
|
||||
func _ensure_species_registered() -> void:
|
||||
## Idempotent: a non-empty registry short-circuits via the engine's
|
||||
## `population_slot_count` proxy on subsequent ticks (slots only appear
|
||||
|
|
|
|||
|
|
@ -272,6 +272,11 @@ signal creature_died(pos: Vector2i, species_name: String, quality: int)
|
|||
signal creature_born(pos: Vector2i, species_name: String)
|
||||
## Tile crossed Q4 threshold — natural wonder emerged from ecology.
|
||||
signal landmark_formed(pos: Vector2i, name: String, quality: int)
|
||||
## Emitted once per full game turn after the continuous worldsim has advanced
|
||||
## (climate physics + fauna `EcologyState.tick` + `WorldsimState.dispatch`).
|
||||
## The fauna overlay subscribes to refresh its per-tile density heatmap so the
|
||||
## evolving living world is visible on the playable map (p2-80 render hook).
|
||||
signal worldsim_updated(turn: int)
|
||||
|
||||
# -- Natural event signals --
|
||||
signal natural_event_spawned(event_type: String, position: Vector2i, intensity: float)
|
||||
|
|
|
|||
|
|
@ -301,6 +301,10 @@ func next_player() -> void:
|
|||
WorldsimState.dispatch(
|
||||
fauna_grid, GameState.turn_number, GameState.map_seed
|
||||
)
|
||||
# p2-80 render hook: signal the fauna overlay to refresh its
|
||||
# per-tile density heatmap so the evolving living world is
|
||||
# visible on the playable map, not just simulated.
|
||||
EventBus.worldsim_updated.emit(GameState.turn_number)
|
||||
GameState.current_player_index = 0
|
||||
GameState.turn_number += 1
|
||||
# Check victory conditions after all players have moved
|
||||
|
|
|
|||
|
|
@ -851,6 +851,26 @@ impl GdFaunaEcology {
|
|||
fn populated_tile_count(&self) -> i64 {
|
||||
self.inner.tile_populations.len() as i64
|
||||
}
|
||||
|
||||
/// Per-tile total fauna population, as a `Dictionary` keyed by
|
||||
/// `Vector2i(col, row)` → total population (`f64`, summed across all species
|
||||
/// slots on the tile). One bulk read so the live-map fauna overlay
|
||||
/// (`fauna_overlay_renderer.gd`) refreshes per turn with a single bridge
|
||||
/// call instead of `populated_tile_count`×`populations_on_tile`. Tiles with
|
||||
/// zero population are omitted (the map is sparse, mirroring the engine's
|
||||
/// own `tile_populations`). Deterministic order is irrelevant here — the
|
||||
/// renderer keys by position, not iteration order.
|
||||
#[func]
|
||||
fn populated_tile_densities(&self) -> Dictionary {
|
||||
let mut out = Dictionary::new();
|
||||
for (&(col, row), slots) in &self.inner.tile_populations {
|
||||
let total: f32 = slots.iter().map(|s| s.population).sum();
|
||||
if total > 0.0 {
|
||||
out.set(Vector2i::new(col, row), f64::from(total));
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
// ── GdAtmosphericChemistry ──────────────────────────────────────────────
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue