feat(@projects/@magic-civilization): add event-to-sfx mapping table

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-05-09 13:21:09 -07:00
parent bd3a9ef375
commit 3fd29fee3c
5 changed files with 41 additions and 42 deletions

View file

@ -26,6 +26,24 @@ const AUDIO_THEME_DIR_FMT: String = "res://public/games/%s/data/audio"
const SILENT_DB: float = -60.0
const UNIT_MOVED_THROTTLE_MSEC: int = 100
## Maps an EventBus signal name → SFX manifest key. Each entry here turns
## "fire SFX X when signal Y emits" into a single line of data instead of a
## bespoke handler. Signals that need branching (perspective stings, music
## crossfades, owner-aware variants, throttling) get explicit handlers
## below — this table is for the trivial 1:1 cases.
const SIMPLE_ROUTES: Dictionary = {
"turn_started": "turn_started",
"turn_ended": "turn_ended",
"city_founded": "city_founded",
"tech_researched": "tech_researched",
"tech_research_started": "research_start",
"culture_researched": "culture_researched",
"city_grew": "city_grew",
"city_starved": "city_starved",
"city_border_expanded": "border_expanded",
"unit_promoted": "unit_promoted",
}
var _loaded: bool = false
var _theme_id: String = ""
var _sfx_events: Dictionary = {}
@ -172,25 +190,6 @@ func stop_music() -> void:
# ---------------------------------------------------------------------------
## Maps an EventBus signal name → SFX manifest key. Each entry here turns
## "fire SFX X when signal Y emits" into a single line of data instead of a
## bespoke handler. Signals that need branching (perspective stings, music
## crossfades, owner-aware variants, throttling) get explicit handlers
## below — this table is for the trivial 1:1 cases.
const SIMPLE_ROUTES: Dictionary = {
"turn_started": "turn_started",
"turn_ended": "turn_ended",
"city_founded": "city_founded",
"tech_researched": "tech_researched",
"tech_research_started": "research_start",
"culture_researched": "culture_researched",
"city_grew": "city_grew",
"city_starved": "city_starved",
"city_border_expanded": "border_expanded",
"unit_promoted": "unit_promoted",
}
func _connect_event_bus() -> void:
for sig_name: String in SIMPLE_ROUTES.keys():
var sfx_key: String = SIMPLE_ROUTES[sig_name]

View file

@ -5,7 +5,7 @@ extends Node
const PlayerScript: GDScript = preload("res://engine/src/entities/player.gd")
const GameMapScript: GDScript = preload("res://engine/src/map/game_map.gd")
const BuildingScript: GDScript = preload("res://engine/src/entities/building.gd")
const _SerializationHelpers: GDScript = preload(
const SerializationHelpers: GDScript = preload(
"res://engine/src/autoloads/game_state_serialization_helpers.gd"
)
const PersonalityAssignerScript: GDScript = preload(
@ -137,15 +137,6 @@ var ley_edges: Array = []
## NPC buildings on the world map (lairs, villages, ruins). Array of Building.
var npc_buildings: Array = []
## Spatial index: "col,row" -> Array[Building] for quick tile lookups.
var _npc_buildings_by_tile: Dictionary = {}
## Cached GdAiController instance (p1-30). Persists across AI turns so the
## Rust-resident TacticalMap is not rebuilt every turn. Reset on new/load game.
## Typed as RefCounted because GdAiController (GDExtension) extends RefCounted.
var _ai_controller: RefCounted = null
## True once set_map() has been called on the cached controller for the current game.
var _ai_map_initialized: bool = false
## Set true by EndGameSummary._on_view_map so world-map input handlers gate out
## player orders. Cleared on new game / load.
@ -160,6 +151,16 @@ var pending_replay_game_id: String = ""
## EndGameSummary._on_watch_replay reads this to seed pending_replay_game_id.
var last_archived_game_id: String = ""
## Spatial index: "col,row" -> Array[Building] for quick tile lookups.
var _npc_buildings_by_tile: Dictionary = {}
## Cached GdAiController instance (p1-30). Persists across AI turns so the
## Rust-resident TacticalMap is not rebuilt every turn. Reset on new/load game.
## Typed as RefCounted because GdAiController (GDExtension) extends RefCounted.
var _ai_controller: RefCounted = null
## True once set_map() has been called on the cached controller for the current game.
var _ai_map_initialized: bool = false
## Return the process-persistent GdAiController, creating it on first call.
## Returns null when the GDExtension is not loaded (headless/test context).
@ -587,11 +588,11 @@ func deserialize(data: Dictionary) -> void:
func _serialize_layer(layer: Dictionary) -> Dictionary:
return _SerializationHelpers.serialize_layer(layer)
return SerializationHelpers.serialize_layer(layer)
func _deserialize_layer(layer_data: Dictionary) -> Dictionary:
return _SerializationHelpers.deserialize_layer(layer_data)
return SerializationHelpers.deserialize_layer(layer_data)
## ------------------------------------------------------------------
@ -626,15 +627,15 @@ func get_player_era(_player_index: int) -> int:
func _serialize_ley_anchors() -> Array:
return _SerializationHelpers.serialize_ley_anchors(ley_anchors)
return SerializationHelpers.serialize_ley_anchors(ley_anchors)
func _deserialize_ley_anchors(raw: Array) -> void:
ley_anchors = _SerializationHelpers.deserialize_ley_anchors(raw)
ley_anchors = SerializationHelpers.deserialize_ley_anchors(raw)
func _serialize_npc_buildings() -> Array:
return _SerializationHelpers.serialize_npc_buildings(npc_buildings)
return SerializationHelpers.serialize_npc_buildings(npc_buildings)
func _deserialize_npc_buildings(raw: Array) -> void:

View file

@ -26,11 +26,6 @@ const _CONFIG: Dictionary = {
var _web: KnowledgeWebScript = KnowledgeWebScript.new(_CONFIG)
func build(_traditions: Array) -> void:
_web.build()
# ── Internal `_nodes` accessor — TurnManager uses it as a "is loaded" probe ─
var _nodes: Dictionary:
@ -38,6 +33,10 @@ var _nodes: Dictionary:
return {0: 1} if _web.get_node_count() > 0 else {}
func build(_traditions: Array) -> void:
_web.build()
# ── Graph queries ───────────────────────────────────────────────────────
func get_pillars() -> Array[String]:

View file

@ -377,7 +377,7 @@ func _get_unit_sprite(type_id: String, race_id: String, sex: String) -> Texture2
func _build_sprite_key(type_id: String, race_id: String, sex: String) -> String:
if race_id != "" and sex != "":
return "%s_%s_%s" % [type_id, race_id, sex]
elif race_id != "":
if race_id != "":
return "%s_%s" % [type_id, race_id]
return type_id

View file

@ -322,8 +322,8 @@ static func _fill_triangle(
var lx: int = clampi(mini(ax, mini(bx, cx)), 0, w - 1)
var rx: int = clampi(maxi(ax, maxi(bx, cx)), 0, w - 1)
var ty: int = clampi(mini(ay, mini(by, cy)), 0, h - 1)
var by_: int = clampi(maxi(ay, maxi(by, cy)), 0, h - 1)
for y: int in range(ty, by_ + 1):
var bottom_y: int = clampi(maxi(ay, maxi(by, cy)), 0, h - 1)
for y: int in range(ty, bottom_y + 1):
for x: int in range(lx, rx + 1):
var s: float = float((bx - ax) * (y - ay) - (by - ay) * (x - ax))
var t: float = float((cx - bx) * (y - by) - (cy - by) * (x - bx))