// ABOUT ME // Components merged into the Radiator. They decide whether this radiator should // vent or hold, and combine that into a single gate, AutoPowerToggle, which // mod.rules substitutes for the radiator's vanilla PowerToggle on the parts of // the radiator that actually dissipate heat. // // The player's manual on/off switch (PowerToggle) is preserved and still wins: // a radiator the player has switched off stays off. The automation can only // idle a radiator the player has left on. // // A radiator vents when EITHER: // - the heat network is running out of room, or // - no launcher on the network is using thermal ammunition // // The design is fail-safe: holding requires positive evidence that the network // has room to spare. Anything missing, disconnected or unmeasurable results in // venting, which is vanilla behaviour. // --- Is the heat network running out of room? ------------------------------- // // Measured locally, exactly the way the heat exchanger decides whether it can // still push heat into the network (heat_exchanger.rules: IsNetworkHeatNonFull // reads a bare NetworkResourceInput). A NetworkResourceInput's value is how much // the network can still accept. // // Reading a thermal battery's own HeatStorage does NOT work for this. That // storage is wrapped by a NetworkResourceStore, and v2.0.0 held heat forever -- // batteries visibly full, parts cooking -- because a local percentage threshold // on it never crossed. This measures the network itself instead, from the part // that acts on the answer, so no cross-part broadcast is involved at all. // // Amounts are resource units: 1 status heat = 1000 resource units // (statuses/heat/heat.rules: STATUS_TO_RESOURCE_RATIO). AutoRad_NetworkSpace { Type = NetworkResourceInput ResourceType = heat Mode = DistributeProportionallyByAvailable } // Under ~2000 status heat of headroom left: vent. AutoRad_SpaceLow { Type = ThresholdToggle ValueFrom = AutoRad_NetworkSpace MaxAmount = 2000000 } // Back above ~6000 status heat of headroom: safe to bank heat again. AutoRad_SpaceAmple { Type = ThresholdToggle ValueFrom = AutoRad_NetworkSpace MinAmount = 6000000 } AutoRad_LowTrigger { Type = ToggleTrigger Toggle = AutoRad_SpaceLow TriggerWhenOn = true TriggerWhenOff = false } AutoRad_AmpleTrigger { Type = ToggleTrigger Toggle = AutoRad_SpaceAmple TriggerWhenOn = true TriggerWhenOff = false } // The deadband, so radiators do not chatter at the threshold. AutoRad_VentLatch { Type = TriggeredToggle OnTrigger = AutoRad_LowTrigger OffTrigger = AutoRad_AmpleTrigger } // OR the raw low reading back in, so a ship that loads already out of room // vents at once instead of waiting for a crossing that never comes. AutoRad_MustVent { Type = MultiToggle Toggles = [ AutoRad_VentLatch, AutoRad_SpaceLow ] Mode = Any } // --- Is anything actually spending heat as ammunition? ---------------------- // // Broadcast by the missile launcher over the heat network. Confirmed working in // game: with a launcher on Thermal Canister ammo this reads 1, and with the // launcher on anything else it reads 0 and radiators behave exactly as vanilla. AutoRad_ThermalAmmoSignal { Type = NetworkValueReceiver Categories = [ auto_radiator_ammo_user ] Mode = Max AllowUncategorized = false } AutoRad_ThermalAmmoInUse { Type = ThresholdToggle ValueFrom = AutoRad_ThermalAmmoSignal MinAmount = 0 MaxAmount = 0 Invert = true } // --- The gate --------------------------------------------------------------- AutoRad_VentAllowed { Type = MultiToggle Toggles [ AutoRad_MustVent { Toggle = AutoRad_ThermalAmmoInUse; Invert = true } ] Mode = Any } // PowerToggle is the radiator's vanilla UIToggle, so the player's switch remains // the master control: it can turn a radiator off, and the automation can only // idle one the player has left on. AutoPowerToggle { Type = MultiToggle Toggles = [ PowerToggle, AutoRad_VentAllowed ] Mode = All }