refactor(@projects/@magic-civilization): 📜 rename chronicle filter bucket military → combat

The turn-notification filter bucket and its label change from "military" to
"combat" to match the entry category, with richer combat log lines (attacker vs
defender, siege HP). Updates the proof scene and unit test accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Natalie 2026-06-21 07:59:40 -05:00
parent 30697898df
commit f3c1cb5564
3 changed files with 31 additions and 16 deletions

View file

@ -16,13 +16,13 @@ var _category_colors: Dictionary = {}
## is a meta-bucket that flips every other filter in lockstep.
const FILTER_BUCKETS: Dictionary = {
"all": [],
"military": ["combat"],
"combat": ["combat"],
"research": ["tech"],
"city": ["founding", "economy"],
"diplomacy": ["event", "magic"],
}
const FILTER_ORDER: Array[String] = [
"all", "military", "research", "city", "diplomacy",
"all", "combat", "research", "city", "diplomacy",
]
## Sentinel for "no hex position available" returned by `_extract_hex_pos`.
## Entities lacking a Vector2i position map to this value; callers guard via
@ -40,7 +40,7 @@ var _entries: Array[Dictionary] = []
var _is_processing: bool = false
## Per-bucket visibility. Default: everything shown.
var _filter_state: Dictionary = {
"military": true, "research": true, "city": true, "diplomacy": true,
"combat": true, "research": true, "city": true, "diplomacy": true,
}
var _filter_checks: Dictionary = {}
@ -549,7 +549,7 @@ func _on_unit_destroyed(unit: Variant, killer: Variant) -> void:
## EventBus.combat_resolved(attacker: Variant, defender: Variant, result: Dictionary)
func _on_combat_resolved(attacker: Variant, defender: Variant, _result: Dictionary) -> void:
func _on_combat_resolved(attacker: Variant, defender: Variant, result: Dictionary) -> void:
var human_idx: int = _human_player_index()
if human_idx < 0:
return
@ -559,13 +559,25 @@ func _on_combat_resolved(attacker: Variant, defender: Variant, _result: Dictiona
return
var att_name: String = _extract_display_name(attacker, "unit")
var def_name: String = _extract_display_name(defender, "unit")
# p3-15: log the damage exchanged [attacker vs defender]. City defenders show
# HP loss (+ capture note); unit duels show damage dealt and taken.
var text: String
var city_dmg: int = int(result.get("city_damage", 0))
if city_dmg > 0:
text = "%s besieges %s: -%d HP" % [att_name, def_name, city_dmg]
if bool(result.get("captured", false)):
text += " (captured)"
else:
var dealt: int = int(result.get("damage_dealt", 0))
var taken: int = int(result.get("damage_taken", 0))
text = "%s vs %s: dealt %d, took %d" % [att_name, def_name, dealt, taken]
var hex: Vector2i = _extract_hex_pos(defender)
if not _has_hex_pos(hex):
hex = _extract_hex_pos(attacker)
if _has_hex_pos(hex):
_add_entry_now("%s attacked %s" % [att_name, def_name], "combat", hex)
_add_entry_now(text, "combat", hex)
else:
_add_entry_now("%s attacked %s" % [att_name, def_name], "combat")
_add_entry_now(text, "combat")
## EventBus.victory_achieved(player_index: int, victory_type: String)

View file

@ -22,7 +22,10 @@ func _ready() -> void:
"Research complete: Metallurgy", "tech"
)
panel._add_entry_now(
"Erebor has been captured", "combat", Vector2i(11, 7)
"Shield Bearer vs Berserker: dealt 12, took 8", "combat", Vector2i(11, 7)
)
panel._add_entry_now(
"Catapult Crew besieges Erebor: -47 HP (captured)", "combat", Vector2i(11, 7)
)
panel._add_entry_now(
"Forge completed in Khazad-dûm", "economy"

View file

@ -32,7 +32,7 @@ func after_each() -> void:
func test_filter_buckets_contain_required_categories() -> void:
var buckets: Dictionary = TurnNotificationScript.FILTER_BUCKETS
assert_true(buckets.has("all"), "filter must include 'all' meta-bucket")
assert_true(buckets.has("military"), "filter must include 'military'")
assert_true(buckets.has("combat"), "filter must include 'combat'")
assert_true(buckets.has("research"), "filter must include 'research'")
assert_true(buckets.has("city"), "filter must include 'city'")
assert_true(buckets.has("diplomacy"), "filter must include 'diplomacy'")
@ -41,15 +41,15 @@ func test_filter_buckets_contain_required_categories() -> void:
func test_filter_order_is_five_checkboxes() -> void:
var order: Array[String] = TurnNotificationScript.FILTER_ORDER
assert_eq(order.size(), 5,
"FILTER_ORDER must have 5 entries: all + military + research + city + diplomacy")
"FILTER_ORDER must have 5 entries: all + combat + research + city + diplomacy")
assert_eq(order[0], "all", "'all' must be the first checkbox")
func test_combat_category_maps_to_military_bucket() -> void:
func test_combat_category_maps_to_combat_bucket() -> void:
var buckets: Dictionary = TurnNotificationScript.FILTER_BUCKETS
var military: Array = buckets["military"] as Array
assert_true(military.has("combat"),
"combat-tagged entries belong in the military bucket")
var combat: Array = buckets["combat"] as Array
assert_true(combat.has("combat"),
"combat-tagged entries belong in the combat bucket")
func test_tech_category_maps_to_research_bucket() -> void:
@ -65,11 +65,11 @@ func test_tech_category_maps_to_research_bucket() -> void:
func test_entry_passes_filter_respects_filter_state() -> void:
var panel: CanvasLayer = TurnNotificationScene.instantiate()
add_child_autofree(panel)
panel._filter_state["military"] = false
panel._filter_state["combat"] = false
var combat_entry: Dictionary = {"text": "kill", "category": "combat"}
assert_false(panel._entry_passes_filter(combat_entry),
"combat entry hidden when military filter off")
panel._filter_state["military"] = true
"combat entry hidden when combat filter off")
panel._filter_state["combat"] = true
assert_true(panel._entry_passes_filter(combat_entry),
"combat entry shown when military filter on")