// 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 with a bare NetworkResourceInput, the same component an // overclocked part pushes its heat through (base_part_overclock.rules: // NetworkHeatInput), so this is exactly the producer's view of the network. // // Its Value, from Cosmoteer.dll (PartNetworkResourceInput.get_Value, see // tools/ildump.py), is the FREE FRACTION of the connected heat storage: // 1 - stored / total capacity -> 1.0 empty, 0.0 full, 0 if nothing attached // and a ThresholdToggle compares that against MinAmount/MaxAmount as plain // floats, so the amounts below are fractions too ("5%" is 0.05). AutoRad_NetworkSpace { Type = NetworkResourceInput ResourceType = heat Mode = DistributeProportionallyByAvailable Categories = [ thermal_storage ] } // Vent while less than VENT_BELOW_FREE of the network is still free. AutoRad_SpaceLow { Type = ThresholdToggle ValueFrom = AutoRad_NetworkSpace VENT_BELOW_FREE = 5% MaxAmount = &VENT_BELOW_FREE } // Hold heat again once at least HOLD_ABOVE_FREE is free. The gap between the // two is a deadband so radiators do not chatter at the threshold. AutoRad_SpaceAmple { Type = ThresholdToggle ValueFrom = AutoRad_NetworkSpace HOLD_ABOVE_FREE = 10% MinAmount = &HOLD_ABOVE_FREE } 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 }