feat(@projects/@magic-civilization): ✨ add mc-flora biome migration task
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
d3c484a5a4
commit
62a74b9af4
8 changed files with 111 additions and 33 deletions
|
|
@ -308,6 +308,7 @@
|
|||
| [p2-60](p2-60-weather-lens-godot-ui.md) | 🔴 stub | P2 | Weather / observation lens switcher in the Godot HUD | [unassigned](../team-leads/unassigned.md) | 🟢 |
|
||||
| [p2-61](p2-61-observation-recording-gates-from-tech.md) | 🔴 stub | P2 | Bind mc-observation gate_bits to player tech state — recording gates per-field | [unassigned](../team-leads/unassigned.md) | 🟢 |
|
||||
| [p2-62](p2-62-procedural-unit-and-building-renderer.md) | 🔴 stub | P2 | Procedural unit/building renderer — alpha-only visual substitute | [unassigned](../team-leads/unassigned.md) | 🟢 |
|
||||
| [p2-63](p2-63-mc-flora-biome-substrate-migration.md) | 🔴 stub | P2 | mc-flora generation: migrate biome filter to substrate_climate-aware path | [unassigned](../team-leads/unassigned.md) | 🟢 |
|
||||
| [p3-01](p3-01-courier-diplomacy.md) | ✅ done | P3 | Courier-gated diplomacy — open borders + shared maps via tech-tiered courier units | [envoy](../team-leads/envoy.md) | 🟢 |
|
||||
| [p3-02](p3-02-hybrid-merged-structures.md) | ❌ missing | P3 | Hybrid merged structures — war_academy, assault_citadel, cavalry_corps, gunnery_corps | — | 🟢 |
|
||||
| [p3-03](p3-03-courier-route-resolver.md) | ✅ done | P3 | Courier route resolver — real hex pathfinding, per-tier movement, severable infrastructure | [envoy](../team-leads/envoy.md) | 🟢 |
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
|---|---|---|---|---|---|---|---|
|
||||
| **P0** | 43 | 0 | 0 | 0 | 0 | 0 | 43 |
|
||||
| **P1** | 47 | 1 | 13 | 3 | 7 | 1 | 72 |
|
||||
| **P2** | 52 | 0 | 7 | 14 | 3 | 6 | 82 |
|
||||
| **P2** | 52 | 0 | 7 | 15 | 3 | 6 | 83 |
|
||||
| **P3 (oos)** | 3 | 0 | 0 | 18 | 1 | 21 | 43 |
|
||||
| **total** | **145** | **1** | **20** | **35** | **11** | **28** | **240** |
|
||||
| **total** | **145** | **1** | **20** | **36** | **11** | **28** | **241** |
|
||||
|
||||
</td><td valign='top' style='padding-left:2em'>
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
| Team Lead | Remaining |
|
||||
|---|---|
|
||||
| [unassigned](../team-leads/unassigned.md) | 30 |
|
||||
| [unassigned](../team-leads/unassigned.md) | 31 |
|
||||
| [warcouncil](../team-leads/warcouncil.md) | 6 |
|
||||
| [asset-sprite](../team-leads/asset-sprite.md) | 6 |
|
||||
| [shipwright](../team-leads/shipwright.md) | 5 |
|
||||
|
|
@ -241,6 +241,7 @@
|
|||
| [p2-60](p2-60-weather-lens-godot-ui.md) | 🔴 stub | "Weather / observation lens switcher in the Godot HUD" | [unassigned](../team-leads/unassigned.md) | 2026-05-03 |
|
||||
| [p2-61](p2-61-observation-recording-gates-from-tech.md) | 🔴 stub | "Bind mc-observation gate_bits to player tech state — recording gates per-field" | [unassigned](../team-leads/unassigned.md) | 2026-05-03 |
|
||||
| [p2-62](p2-62-procedural-unit-and-building-renderer.md) | 🔴 stub | "Procedural unit/building renderer — alpha-only visual substitute" | [unassigned](../team-leads/unassigned.md) | 2026-05-03 |
|
||||
| [p2-63](p2-63-mc-flora-biome-substrate-migration.md) | 🔴 stub | "mc-flora generation: migrate biome filter to substrate_climate-aware path" | [unassigned](../team-leads/unassigned.md) | 2026-05-04 |
|
||||
|
||||
## Out of Scope (Game 2 / Game 3)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"generated_at": "2026-05-04T04:50:40Z",
|
||||
"generated_at": "2026-05-04T05:13:02Z",
|
||||
"totals": {
|
||||
"done": 146,
|
||||
"in_progress": 1,
|
||||
"partial": 20,
|
||||
"stub": 35,
|
||||
"stub": 36,
|
||||
"missing": 11,
|
||||
"oos": 28,
|
||||
"total": 241
|
||||
"total": 242
|
||||
},
|
||||
"objectives": [
|
||||
{
|
||||
|
|
@ -2176,6 +2176,17 @@
|
|||
"blocked_by": [],
|
||||
"summary": ""
|
||||
},
|
||||
{
|
||||
"id": "p2-63",
|
||||
"title": "mc-flora generation: migrate biome filter to substrate_climate-aware path",
|
||||
"priority": "p2",
|
||||
"status": "stub",
|
||||
"scope": "game1",
|
||||
"owner": "unassigned",
|
||||
"updated_at": "2026-05-04",
|
||||
"blocked_by": [],
|
||||
"summary": "Authored flora JSON files have migrated from a top-level `biomes: [...]`\narray to the `substrate_climate` ontology\n(see `p2-52-substrate-flora-cover-ontology-split.md`). The biome-filter\nloop in `mc-flora/src/generation.rs` was not updated, so the\n`AuthoredSpeciesFile.biomes` field is now empty for every authored file\nand the candidate-pool query returns nothing.\n\nTwo pre-existing regression tests in `mc-flora` document the gap:\n\n- `load_authored_returns_species_for_known_biome` (generation.rs:645)\n- `generate_flora_for_biome_more_species_with_authored_files`\n (generation.rs:695)\n\nBoth fail because the biome filter at `generation.rs:508-510` still\nchecks `raw.biomes.iter().any(|b| b == biome_id)` while the JSON now\nencodes biome eligibility through `substrate_climate` blocks the loader\ndoes not currently inspect."
|
||||
},
|
||||
{
|
||||
"id": "g2-01",
|
||||
"title": "Ley lines — Game 2 (Age of Kzzykt)",
|
||||
|
|
@ -2798,7 +2809,7 @@
|
|||
"remaining_by_lead": [
|
||||
{
|
||||
"owner": "unassigned",
|
||||
"remaining": 30
|
||||
"remaining": 31
|
||||
},
|
||||
{
|
||||
"owner": "asset-sprite",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ evidence:
|
|||
- "src/simulator/crates/mc-tech/src/web.rs:74"
|
||||
- "src/simulator/crates/mc-tech/src/web.rs:248"
|
||||
- "src/simulator/crates/mc-tech/src/web.rs:399"
|
||||
- "src/simulator/api-gdext/src/lib.rs:4953 (GdTechWeb::domains/techs_by_domain/research_history_by_domain)"
|
||||
- "src/game/engine/src/modules/tech/tech_web.gd:88 (get_domains/get_techs_by_domain/get_research_history_by_domain)"
|
||||
- "src/game/engine/scenes/knowledge_tree/knowledge_tree.gd:96 (tab axis hooks + tab bar + float-to-top sort)"
|
||||
- "src/game/engine/scenes/tech_tree/tech_tree.gd:36 (TechTree overrides _get_tab_axis_values/_node_in_tab)"
|
||||
- "src/game/engine/tests/unit/test_knowledge_tree_domain_tabs.gd (3/3 GUT pass on apricot, headless)"
|
||||
- "tools/validate-game-data.py:178 (validate_tech_domains: 10-value enum membership check)"
|
||||
assigned_by: simulator-infra
|
||||
---
|
||||
## Summary
|
||||
|
|
@ -54,15 +60,39 @@ node.
|
|||
for culture data, matching the design note that culture uses `pillar`
|
||||
as its tab axis.)
|
||||
|
||||
- [ ] **GDExtension** — `GdTechWeb` exposes `domains() ->
|
||||
PackedStringArray` and `techs_by_domain(domain) -> Array<Dictionary>`.
|
||||
`tech_data_json(id)` includes `domain` in returned dict. Build clean:
|
||||
`bash src/simulator/build-gdext.sh`.
|
||||
- [x] **GDExtension** — `GdTechWeb` exposes `domains() ->
|
||||
PackedStringArray` (returns the canonical 10 `TechDomain::ALL`
|
||||
variants regardless of loaded data) and `techs_by_domain(domain) ->
|
||||
PackedStringArray` (parses the PascalCase string back to the typed
|
||||
enum, then delegates to `mc_tech::TechWeb::techs_by_domain`).
|
||||
`tech_data_json(id)` already includes `domain` for free via serde
|
||||
(proven by the round-trip test in `mc-tech/src/web.rs:399`).
|
||||
`research_history_by_domain(researched_techs) -> Dictionary` added
|
||||
for the player-analysis bullet (Dictionary keyed by all 10 domain
|
||||
strings, values are `PackedStringArray` of completed tech ids).
|
||||
Built clean on apricot (`bash build-gdext.sh`, release profile, 17
|
||||
pre-existing doc warnings unrelated to this change). Files:
|
||||
`src/simulator/api-gdext/src/lib.rs:4953-5031`.
|
||||
|
||||
- [ ] **GDScript** — `tech_web.gd` exposes `get_domains()` and
|
||||
`get_nodes_by_domain(domain)`. `knowledge_tree.gd` renders a domain
|
||||
tab bar above the existing pillar columns. Active tab causes matching
|
||||
nodes to float to the top within each era column.
|
||||
- [x] **GDScript** — `tech_web.gd` exposes `get_domains()`,
|
||||
`get_techs_by_domain(domain)`, and
|
||||
`get_research_history_by_domain(player_index)` — all pass-through
|
||||
wrappers that call directly into the GDExtension bridge. No GDScript-
|
||||
side enum or string list. `knowledge_tree.gd` gains an opt-in tab-axis
|
||||
hook (`_get_tab_axis_values()` / `_node_in_tab()`), a tab bar above
|
||||
the body, and float-to-top sort within each pillar column when an
|
||||
explicit tab is active. The "All" sentinel preserves original order.
|
||||
`tech_tree.gd` overrides the hooks to surface the 10 `TechDomain`
|
||||
values from `TechWeb.get_domains()`. Culture trees opt out by leaving
|
||||
the default empty hook; the tab bar hides itself when no axis is
|
||||
declared. Files: `src/game/engine/src/modules/tech/tech_web.gd:88`,
|
||||
`src/game/engine/scenes/knowledge_tree/knowledge_tree.gd:96`,
|
||||
`src/game/engine/scenes/tech_tree/tech_tree.gd:36`. Headless GUT
|
||||
proof: `test_knowledge_tree_domain_tabs.gd` (3/3 pass on apricot,
|
||||
108 asserts) — covers tab-bar rendering of all 10 domains + "All"
|
||||
sentinel, float-to-top partition order with the Science tab active,
|
||||
and round-trip equivalence of `get_domains()` with
|
||||
`TechDomain::ALL` order.
|
||||
|
||||
- [ ] **Gameplay proof** — `tech_tree_proof.tscn` captures a screenshot
|
||||
showing the domain tab bar, with one tab (e.g. "Science") active and
|
||||
|
|
@ -78,9 +108,17 @@ node.
|
|||
in-game stats screen renders a domain-binned breakdown of a player's
|
||||
research history. Driven by deterministic replay fixture data.
|
||||
|
||||
- [ ] **Cross-reference validation** — `tools/` validator script (or new
|
||||
one) confirms every tech in `public/resources/techs/*.json` has a
|
||||
`domain` field set to one of the 10 canonical values.
|
||||
- [x] **Cross-reference validation** — `tools/validate-game-data.py`
|
||||
gained a `validate_tech_domains()` pass that walks
|
||||
`public/resources/techs/*.json` and asserts every entry's `domain`
|
||||
field exists and ∈ the canonical 10-value enum (mirrored from
|
||||
`mc_core::TechDomain::ALL` as a class constant — update both sites
|
||||
if the enum ever changes). Verified clean across the 60+ shipped
|
||||
techs (`tech domain enum membership (10 canonical values)` section
|
||||
in the validator output is failure-free). The legacy
|
||||
`game_data/techs/` fallback was intentionally dropped from this
|
||||
pass per post-p1-40 SSoT (single source at `resources/techs/`).
|
||||
Files: `tools/validate-game-data.py:178`.
|
||||
|
||||
- [ ] **Phase-gate proof screenshot** — captured per
|
||||
`phase-gate-protocol.md`. Archived under `.project/screenshots/`.
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@ scope: game1
|
|||
owner: simulator-infra
|
||||
updated_at: 2026-05-04
|
||||
evidence:
|
||||
- "src/simulator/crates/mc-core/src/ids.rs:1 — typed BuildingId/SpecialistId/GreatPersonClass/HarvestPolicyId newtypes (transparent serde, mc-core test suite green)"
|
||||
- "src/simulator/crates/mc-core/src/gpp.rs:1 — closed GppType + GreatWorkType enums with effect-key mapping (snake_case round-trip)"
|
||||
- "src/simulator/crates/mc-city/src/building.rs:42 — typed BuildingEffect enum covering gpp_* and great_work_slots_* with Other catch-all; specialist_slots: Vec<SpecialistId>; requires_buildings_all_cities: Vec<BuildingId>"
|
||||
- "src/simulator/crates/mc-city/src/building.rs:567 — test_building_deserialises_new_fields green for saga_arena + saga_chronicle"
|
||||
- "src/simulator/crates/mc-city/src/building.rs:625 — test_all_authored_buildings_deserialize green over 178 building JSONs"
|
||||
- "public/games/age-of-dwarves/docs/BUILDING_SCHEMA.md:99 — Civics extensions section documents new effect-array variants and typed wrappers"
|
||||
- "src/simulator/crates/mc-city/src/great_works.rs:1 — static GreatWorkRegistry with 3/3 tests green over the 4 authored category JSONs (≥30 works)"
|
||||
- "src/simulator/api-gdext/src/civics.rs:1 — GdSpecialistRegistry / GdHarvestPolicyRegistry / GdGreatWorkRegistry / GdBuildingCivics; cargo build -p magic-civ-physics-gdext clean on apricot"
|
||||
- "src/game/engine/scenes/city/specialists_panel.gd:1 — VBoxContainer panel rendering specialist slots, 7-channel GPP/turn sums, 4-category great-work slot capacity from typed Rust accessors"
|
||||
- src/game/engine/tests/unit/test_city_screen_specialist_slots.gd + test_city_screen_gpp.gd — 11 new tests; headless GUT 25/25 city_screen tests passing on apricot
|
||||
- "src/simulator/crates/mc-city/src/harvest_policy.rs:91 — HarvestPolicyRegistry::all() accessor for UI dropdown enumeration"
|
||||
assigned_by: simulator-infra
|
||||
---
|
||||
## Summary
|
||||
|
|
@ -232,6 +231,7 @@ Unit fields added (additive, optional):
|
|||
- Dependencies: GPP bullet.
|
||||
- Acceptance gate: `cargo test -p mc-city test_great_work_slot_assignment` green; removal on building destruction tested.
|
||||
- SOLID/DRY/SSoT rails: registry typed; effect chains in `mc-city`.
|
||||
- **Sub-bullet (closed 2026-05-04 — registry only)** ✓ Static `GreatWorkRegistry` lives at `src/simulator/crates/mc-city/src/great_works.rs:1` with `from_json` / `from_json_files` / `by_type` / `get`, mirrors `SpecialistRegistry` shape. `mc-city` re-exports `GreatWork` + `GreatWorkRegistry` (`src/simulator/crates/mc-city/src/lib.rs:35`). Tests `great_works::tests::great_work_round_trips_via_json`, `all_authored_great_works_deserialize` (loads all 4 authored JSONs, ≥30 works), `by_type_filters_correctly` green (`cargo test -p mc-city --lib great_works` 3/3). Per-city occupation (which work fills which slot, removal on building destruction, GP-spawn assignment) NOT yet implemented — depends on per-city runtime state still missing in `mc-city`.
|
||||
|
||||
### Bullet: `mc-turn::process_buildings` calls per-turn GPP/specialist/harvest/great-work ticks
|
||||
|
||||
|
|
@ -246,6 +246,13 @@ Unit fields added (additive, optional):
|
|||
- Dependencies: Rust bullets above.
|
||||
- Acceptance gate: `bash src/simulator/build-gdext.sh` clean; smoke probe in proof scene.
|
||||
- SOLID/DRY/SSoT rails: bridge marshals JSON; tier-cap enforced server-side in Rust.
|
||||
- **Sub-bullet (closed 2026-05-04 — static-registry surface only)** ✓ `src/simulator/api-gdext/src/civics.rs:1` registers four `RefCounted` GDExt classes:
|
||||
- `GdSpecialistRegistry::from_json` / `get_specialist` / `for_building` / `count` — wraps `mc_city::SpecialistRegistry`.
|
||||
- `GdHarvestPolicyRegistry::from_json` / `get_policy` / `ids` / `count` — wraps `mc_city::HarvestPolicyRegistry`. New `HarvestPolicyRegistry::all` accessor at `src/simulator/crates/mc-city/src/harvest_policy.rs:91`.
|
||||
- `GdGreatWorkRegistry::from_json_files` / `get_great_work` / `by_type` / `count` — wraps `mc_city::GreatWorkRegistry`.
|
||||
- `GdBuildingCivics::from_defs_json` / `insert_def_json` / `specialist_slots` / `gpp_yield` / `great_work_slots` / `sum_gpp_yield` / `sum_great_work_slots` — exposes the cycle-1 typed `BuildingDef` accessors per building and as city-wide sums for UI.
|
||||
- Verified by `cargo build -p magic-civ-physics-gdext` clean (Finished `dev` in 23.18s on apricot, 17 doc warnings, 0 errors).
|
||||
- NOT bridged this cycle: `GdGreatPersonAction.activate(...)` (no Rust runtime), `set_tile_policy` (no `Tile.harvest_policy` field), per-city GPP accumulator readback (no per-city state). Tier-cap enforcement, GP spawn dispatch, and great-work occupation depend on the Rust runtime bullets above and stay ❌.
|
||||
|
||||
### Bullet: Godot UI — specialist drag, harvest dropdown, great-person spawn modal, throne-room layer slots
|
||||
|
||||
|
|
@ -254,11 +261,19 @@ Unit fields added (additive, optional):
|
|||
- Dependencies: GDExtension bullet.
|
||||
- Acceptance gate: gdlint clean; manual smoke + proof scene.
|
||||
- SOLID/DRY/SSoT rails: presentation only; no game rules in GDScript.
|
||||
- **Sub-bullet (closed 2026-05-04 — capacity panel only)** ✓ `src/game/engine/scenes/city/specialists_panel.gd:1` — VBoxContainer panel renders three sections:
|
||||
- Specialist slots — one row per (building_id, specialist_id) sourced from `GdBuildingCivics.specialist_slots(bid)`. Specialist name resolved via `GdSpecialistRegistry.get_specialist(sid)`.
|
||||
- GPP per turn — all 7 GPP types (`writing`, `music`, `art`, `statuary`, `scholarship`, `trade`, `engineering`) summed across the city's built buildings via `GdBuildingCivics.sum_gpp_yield`.
|
||||
- Great-Work slot capacity — all 4 work types summed via `GdBuildingCivics.sum_great_work_slots`, rendered as `0 / cap` (occupants placeholder — runtime occupation not yet bridged).
|
||||
- Vocab keys added at `public/games/age-of-dwarves/vocabulary.json:584` (`city_screen_section_specialists`, `city_screen_section_gpp`, `city_screen_section_great_works`, `city_screen_no_specialist_slots`).
|
||||
- Pure presentation — no game rules in GDScript; `setup(specialist_registry, great_work_registry, building_civics)` accepts null registries and degrades gracefully (renders empty rows) when the GDExtension isn't loaded.
|
||||
- Drag-to-employ, harvest-policy dropdown on tile rows, great-person spawn modal, and throne-room layer slot rendering remain ❌ — they require runtime employ/unemploy/policy-set/spawn APIs in mc-city.
|
||||
|
||||
### Bullet: GUT tests + proof screenshot
|
||||
|
||||
- Files to touch: `src/game/engine/src/tests/test_specialist_slots.gd`, `test_gpp_accumulation.gd`, `test_great_person_spawn.gd`, `test_harvest_policy_yield.gd`, `test_great_work_slot_assignment.gd`, `test_national_wonder_requirement.gd`; proof scene `scenes/tests/proof_civics_buildings.tscn`.
|
||||
- Dependencies: all above.
|
||||
- Acceptance gate: `godot --headless --test ...` green; screenshot approved per `phase-gate-protocol.md`.
|
||||
- **Sub-bullet (closed 2026-05-04 — UI-side tests for capacity panel)** ✓ `src/game/engine/tests/unit/test_city_screen_specialist_slots.gd` (6 tests, 6 passing) and `test_city_screen_gpp.gd` (5 tests, 5 passing) verify aggregation contract against mock GdBuildingCivics + GdSpecialistRegistry surfaces. Headless GUT run on apricot via `flatpak run org.godotengine.Godot --headless --script gut_cmdln.gd -gprefix=test_city_screen_`: `25/25 passed` across 4 city-screen test files (the 2 new + 2 pre-existing). Includes negative test `test_panel_does_not_render_runtime_progress` enforcing Rail-1: no GDScript shadow accumulator. Proof screenshot + per-system Rust tests (`test_specialist_yields_and_population`, `test_gpp_accumulation_and_spawn`, `test_great_person_spawn`, `test_harvest_policy_remove_chop_oneshot`, `test_great_work_slot_assignment`, `test_national_wonder_requirement`) remain ❌ — depend on Rust runtime bullets above.
|
||||
|
||||
Bullets remaining: 10 (deserialise bullet closed 2026-05-04).
|
||||
Bullets remaining: 10 parents still ❌; this cycle landed three closed sub-bullets (great-works static registry, GDExt static-registry surface, capacity-only specialists panel + GUT tests). Next cycle: Rust runtime (Specialist yields, GPP accumulator, Tile.harvest_policy, national-wonder gates).
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"generated_at": "2026-05-04T04:53:17Z",
|
||||
"generated_at": "2026-05-04T05:14:49Z",
|
||||
"totals": {
|
||||
"in_progress": 1,
|
||||
"missing": 11,
|
||||
"done": 145,
|
||||
"oos": 28,
|
||||
"partial": 20,
|
||||
"stub": 35,
|
||||
"total": 240
|
||||
"oos": 28,
|
||||
"in_progress": 1,
|
||||
"done": 145,
|
||||
"missing": 11,
|
||||
"stub": 36,
|
||||
"total": 241
|
||||
},
|
||||
"objectives": [
|
||||
{
|
||||
|
|
@ -1980,6 +1980,16 @@
|
|||
"updated_at": "2026-05-03",
|
||||
"summary": ""
|
||||
},
|
||||
{
|
||||
"id": "p2-63",
|
||||
"title": "\"mc-flora generation: migrate biome filter to substrate_climate-aware path\"",
|
||||
"priority": "p2",
|
||||
"status": "stub",
|
||||
"scope": "game1",
|
||||
"owner": "unassigned",
|
||||
"updated_at": "2026-05-04",
|
||||
"summary": "Authored flora JSON files have migrated from a top-level `biomes: [...]`\narray to the `substrate_climate` ontology\n(see `p2-52-substrate-flora-cover-ontology-split.md`). The biome-filter\nloop in `mc-flora/src/generation.rs` was not updated, so the\n`AuthoredSpeciesFile.biomes` field is now empty for every authored file\nand the candidate-pool query returns nothing.\n\nTwo pre-existing regression tests in `mc-flora` document the gap:\n\n- `load_authored_returns_species_for_known_biome` (generation.rs:645)\n- `generate_flora_for_biome_more_species_with_authored_files`\n (generation.rs:695)\n\nBoth fail because the biome filter at `generation.rs:508-510` still\nchecks `raw.biomes.iter().any(|b| b == biome_id)` while the JSON now\nencodes biome eligibility through `substrate_climate` blocks the loader\ndoes not currently inspect."
|
||||
},
|
||||
{
|
||||
"id": "g2-01",
|
||||
"title": "Ley lines — Game 2 (Age of Kzzykt)",
|
||||
|
|
|
|||
|
|
@ -49,4 +49,5 @@ func _node_in_tab(node_id: String, tab: String) -> bool:
|
|||
if tab.is_empty() or _web == null:
|
||||
return true
|
||||
var data: Dictionary = (_web as TechWeb).get_node_data(node_id)
|
||||
return String(data.get("domain", "")) == tab
|
||||
var domain_val: String = str(data.get("domain", ""))
|
||||
return domain_val == tab
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ fn outcome_str(o: CombatOutcome) -> &'static str {
|
|||
CombatOutcome::Captured => "captured",
|
||||
CombatOutcome::RansomOffered => "ransom_offered",
|
||||
CombatOutcome::Destroyed => "destroyed",
|
||||
CombatOutcome::Devastated => "devastated",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue