diff --git a/README.md b/README.md index 003b698..ed98ead 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,25 @@ An auto-idled radiator shows the same "powered off" indicator icon as a manually switched-off one, and stops emitting its steam plume. That icon appearing on a radiator you did *not* switch off is the mod working. +## Reading the diagnostic icons + +The radiator reports its own internal state through indicator icons. An icon is +drawn while its toggle is **off**, so: + +| Icon on a radiator | Meaning | +|---|---| +| 🔧 wrench (`MissingComponent`) | **Always expected.** Its absence means the mod's components never merged onto the part, and nothing else in the mod is running. | +| thermal missile | No thermal-ammo signal is reaching this radiator — no launcher on its heat network is set to Thermal Canister Missiles. | +| resource | No hold signal is reaching this radiator — no thermal battery on its network is asking it to hold. | +| power-off | The radiator is idle: either you switched it off, or the automation idled it. | + +A correctly working setup, on a ship with a thermal launcher and a battery below +the vent ceiling, shows **the wrench alone**. + +These make the failure legible rather than guessable: wrench missing points at +the patch mechanism, either other icon points at the specific signal that is +dead. + ## Status Validated against game data version 0.30.4c, and confirmed to load cleanly diff --git a/components/radiator_auto.rules b/components/radiator_auto.rules index 73d51d5..a327d9f 100644 --- a/components/radiator_auto.rules +++ b/components/radiator_auto.rules @@ -83,3 +83,14 @@ AutoPowerToggle Toggles = [ PowerToggle, AutoRad_VentAllowed ] Mode = All } + +// Diagnostic anchor. An indicator icon shows while its toggle is OFF, so an +// icon bound to this one is visible whenever these components were merged onto +// the part at all. If that icon is absent, the AddBase in mod.rules did not +// take effect and nothing else in this file is running either -- which is the +// single most useful thing to be able to tell apart from a dead signal. +AutoRad_AlwaysOff +{ + Type = StaticToggle + ToggleOn = false +} diff --git a/mod.rules b/mod.rules index c19bb87..e7807b4 100644 --- a/mod.rules +++ b/mod.rules @@ -16,7 +16,7 @@ ID = ganter.auto_radiator Name = "Auto Radiator" -Version = 1.1.0 +Version = 1.2.0 CompatibleGameVersions = ["0.30.4c", "0.30.4"] ModifiesGameplay = true Author = "Tobias Ganter" @@ -118,4 +118,49 @@ Actions Toggle = AutoPowerToggle } } + + // --- Diagnostic indicators ------------------------------------------- + // + // An indicator icon is drawn while its toggle is OFF. These three make the + // radiator report its own internal state, so a radiator that is not + // behaving can be read directly instead of guessed at: + // + // wrench icon always visible -> these components merged onto the part + // absent -> the AddBase did not take effect + // thermal missile visible -> no thermal-ammo signal is arriving + // resource icon visible -> no hold signal is arriving from a battery + // + // A working setup on a ship with a thermal launcher and a battery below the + // vent ceiling shows the wrench alone. + { + Action = AddMany + AddTo = "/Part/Components/Indicators/Indicators" + ManyToAdd + [ + { + Toggle = AutoRad_AlwaysOff + AtlasSprite + { + File = &/INDICATORS/MissingComponent + Size = [1, 1] + } + } + { + Toggle = AutoRad_ThermalAmmoInUse + AtlasSprite + { + File = &/INDICATORS/NoThermalMissiles + Size = [1, 1] + } + } + { + Toggle = AutoRad_IsHolding + AtlasSprite + { + File = &/INDICATORS/NoResource + Size = [1, 1] + } + } + ] + } ] diff --git a/tests/test_mod.py b/tests/test_mod.py index a1dd9d2..2d3ba7f 100644 --- a/tests/test_mod.py +++ b/tests/test_mod.py @@ -365,7 +365,50 @@ def test_no_name_collisions_with_vanilla(): # --------------------------------------------------------------------------- -# 7. The mod manifest must declare the fields Cosmoteer requires. +# 7. Added indicators must bind to a real toggle and a real atlas sprite. +# --------------------------------------------------------------------------- + +def test_added_indicators_are_valid(): + mod = rules_parser.parse_file(os.path.join(MOD_ROOT, "mod.rules")) + radiator_components = resolve("/Part/Components") + added = rules_parser.parse_file(os.path.join(MOD_ROOT, "components", "radiator_auto.rules")) + known = set(added.order) | set(radiator_components.order if radiator_components else []) + + atlas = vanilla("gui/game/indicators/indicators.rules") + check(atlas is not None, "cannot read the indicators atlas") + + for action in iter_actions(mod): + kind = action.get("Action") + add_to = action.get("AddTo") + if not kind or kind.value != "AddMany" or add_to is None: + continue + if "Indicators" not in add_to.value: + continue + entries = action.get("ManyToAdd") + check(entries is not None, "indicator AddMany has no ManyToAdd list") + if entries is None: + continue + for key in entries.order: + entry = entries.children[key] + toggle = entry.get("Toggle") + check(toggle is not None, "an added indicator has no Toggle") + if toggle is not None: + check( + toggle.value.strip() in known, + f"added indicator binds to unknown component '{toggle.value.strip()}'", + ) + sprite = entry.get("AtlasSprite/File") + check(sprite is not None, "an added indicator has no AtlasSprite/File") + if sprite is not None and atlas is not None: + name = sprite.value.strip().rsplit("/", 1)[-1] + check( + name in atlas.children, + f"added indicator uses unknown atlas sprite '{name}'", + ) + + +# --------------------------------------------------------------------------- +# 8. The mod manifest must declare the fields Cosmoteer requires. # --------------------------------------------------------------------------- def test_manifest_is_well_formed():