[MIRROR] Thermomachine heat exploit fix (#5216)

* Thermomachine heat exploit fix (#58390)

Stops thermomachines from going over the fusion max temperature with the safeties on (safeties can only be disabled after emag or EMP).
Without the safeties on the machine has a chance of explosion (0, 0, 3)

* Thermomachine heat exploit fix

Co-authored-by: Ghilker <42839747+Ghilker@users.noreply.github.com>
This commit is contained in:
SkyratBot
2021-04-26 12:01:21 +01:00
committed by GitHub
co-authored by Ghilker
parent 0ad8f0298b
commit 614d01c1f7
4 changed files with 104 additions and 8 deletions
+8
View File
@@ -142,6 +142,14 @@
#define REACTING 1
#define STOP_REACTIONS 2
//Fusion
///Max amount of radiation that can be emitted per reaction cycle
#define FUSION_RAD_MAX 5000
///Maximum instability before the reaction goes endothermic
#define FUSION_INSTABILITY_ENDOTHERMALITY 4
///Maximum reachable fusion temperature
#define FUSION_MAXIMUM_TEMPERATURE 1e8
// Pressure limits.
/// This determins at what pressure the ultra-high pressure red icon is displayed. (This one is set as a constant)
#define HAZARD_HIGH_PRESSURE 550
@@ -1,3 +1,5 @@
#define THERMOMACHINE_SAFE_TEMPERATURE 500000
/obj/machinery/atmospherics/components/binary/thermomachine
icon = 'icons/obj/atmospherics/components/thermomachine.dmi'
icon_state = "freezer"
@@ -33,6 +35,8 @@
var/use_enviroment_heat = FALSE
var/skipping_work = FALSE
var/auto_thermal_regulator = FALSE
var/safeties = TRUE
var/lastwarning
var/color_index = 1
/obj/machinery/atmospherics/components/binary/thermomachine/Initialize()
@@ -104,6 +108,8 @@
/obj/machinery/atmospherics/components/binary/thermomachine/examine(mob/user)
. = ..()
if(obj_flags & EMAGGED)
. += "<span class='notice'>Something seems wrong with [src]'s thermal safeties.</span>"
. += "<span class='notice'>With the panel open:</span>"
. += "<span class='notice'>-use a wrench with left-click to rotate [src] and right-click to unanchor it.</span>"
. += "<span class='notice'>-use a multitool with left-click to change the piping layer and right-click to change the piping color.</span>"
@@ -156,13 +162,25 @@
var/temperature_difference = 0
var/skip_tick = TRUE
if(!use_enviroment_heat && main_port.total_moles() > 0.01)
if(cooling && thermal_exchange_port.total_moles() > 0.01 && nodes[2])
if(cooling && thermal_exchange_port.total_moles() > 0.01 && nodes[2] && (thermal_exchange_port.temperature <= THERMOMACHINE_SAFE_TEMPERATURE || !safeties))
thermal_exchange_port.temperature = max(thermal_exchange_port.temperature + heat_amount / thermal_heat_capacity + motor_heat / thermal_heat_capacity, TCMB)
else if(cooling && (!thermal_exchange_port.total_moles() || !nodes[2]))
skipping_work = skip_tick
update_appearance()
update_parents()
return
if(thermal_exchange_port.temperature > THERMOMACHINE_SAFE_TEMPERATURE && safeties)
on = FALSE
visible_message("<span class='warning'>The thermal exchange port's temperature has reached critical levels, shutting down...</span>")
update_appearance()
return
else if(thermal_exchange_port.temperature > THERMOMACHINE_SAFE_TEMPERATURE && !safeties)
if((REALTIMEOFDAY - lastwarning) / 5 >= WARNING_DELAY)
lastwarning = REALTIMEOFDAY
visible_message("<span class='warning'>The thermal exchange port's temperature has reached critical levels!</span>")
if(check_explosion(thermal_exchange_port.temperature))
explode()
return PROCESS_KILL //we dying anyway, so let's stop processing
temperature_difference = thermal_exchange_port.temperature - main_port.temperature
temperature_difference = cooling ? temperature_difference : 0
if(temperature_difference > 0)
@@ -171,7 +189,7 @@
skip_tick = FALSE
if(use_enviroment_heat && main_port.total_moles() > 0.01)
var/enviroment_efficiency = 1
if(cooling && enviroment.total_moles() > 0.01)
if(cooling && enviroment.total_moles() > 0.01 && (thermal_exchange_port.temperature <= THERMOMACHINE_SAFE_TEMPERATURE || !safeties))
var/enviroment_heat_capacity = enviroment.heat_capacity()
if(enviroment.total_moles())
enviroment_efficiency = clamp(log(1.55, enviroment.total_moles()) * 0.15, 0.65, 1)
@@ -182,6 +200,18 @@
update_appearance()
update_parents()
return
if(enviroment.temperature > THERMOMACHINE_SAFE_TEMPERATURE && safeties)
on = FALSE
visible_message("<span class='warning'>The enviroment's temperature has reached critical levels, shutting down...</span>")
update_appearance()
return
else if(enviroment.temperature > THERMOMACHINE_SAFE_TEMPERATURE && !safeties)
if((REALTIMEOFDAY - lastwarning) / 5 >= WARNING_DELAY)
lastwarning = REALTIMEOFDAY
visible_message("<span class='warning'>The enviroment's temperature has reached critical levels!</span>")
if(check_explosion(enviroment.temperature))
explode()
return PROCESS_KILL //we dying anyway, so let's stop processing
temperature_difference = enviroment.temperature - main_port.temperature
temperature_difference = cooling ? temperature_difference : 0
if(temperature_difference > 0)
@@ -297,6 +327,37 @@
return TRUE
return FALSE
/obj/machinery/atmospherics/components/binary/thermomachine/multitool_act(mob/living/user, obj/item/multitool/multitool)
if(!istype(multitool))
return
if(panel_open && !anchored)
piping_layer = (piping_layer >= PIPING_LAYER_MAX) ? PIPING_LAYER_MIN : (piping_layer + 1)
to_chat(user, "<span class='notice'>You change the circuitboard to layer [piping_layer].</span>")
update_appearance()
/obj/machinery/atmospherics/components/binary/thermomachine/emag_act(mob/user)
. = ..()
if(!(obj_flags & EMAGGED))
if(!do_after(user, 1 SECONDS, src))
return
var/datum/effect_system/spark_spread/sparks = new
sparks.set_up(5, 0, src)
sparks.attach(src)
sparks.start()
obj_flags |= EMAGGED
user.visible_message("<span class='warning'>You emag [src], overwriting thermal safety restrictions.</span>")
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)], overwriting thermal safety restrictions.")
/obj/machinery/atmospherics/components/binary/thermomachine/emp_act()
. = ..()
if(!(obj_flags & EMAGGED))
var/datum/effect_system/spark_spread/sparks = new
sparks.set_up(5, 0, src)
sparks.attach(src)
sparks.start()
obj_flags |= EMAGGED
safeties = FALSE
/obj/machinery/atmospherics/components/binary/thermomachine/proc/replace_tank(mob/living/user, obj/item/tank/new_tank)
if(!user)
return FALSE
@@ -308,6 +369,23 @@
update_appearance()
return TRUE
/obj/machinery/atmospherics/components/binary/thermomachine/proc/check_explosion(temperature)
if(temperature < THERMOMACHINE_SAFE_TEMPERATURE + 2000)
return FALSE
if(prob(log(6, temperature) * 10)) //75% at 500000, 100% at 1e8
return TRUE
/obj/machinery/atmospherics/components/binary/thermomachine/proc/explode()
explosion(loc, 0, 0, 3, 3, TRUE)
var/datum/gas_mixture/main_port = airs[1]
var/datum/gas_mixture/thermal_exchange_port = airs[2]
if(main_port)
loc.assume_air(main_port.remove_ratio(1))
if(thermal_exchange_port)
loc.assume_air(thermal_exchange_port.remove_ratio(1))
air_update_turf(FALSE, FALSE)
qdel(src)
/obj/machinery/atmospherics/components/binary/thermomachine/ui_status(mob/user)
if(interactive)
return ..()
@@ -342,6 +420,9 @@
data["use_env_heat"] = use_enviroment_heat
data["skipping_work"] = skipping_work
data["auto_thermal_regulator"] = auto_thermal_regulator
data["safeties"] = safeties
var/hacked = (obj_flags & EMAGGED) ? TRUE : FALSE
data["hacked"] = hacked
return data
/obj/machinery/atmospherics/components/binary/thermomachine/ui_act(action, params)
@@ -391,6 +472,10 @@
if("auto_thermal_regulator")
auto_thermal_regulator = !auto_thermal_regulator
. = TRUE
if("safeties")
safeties = !safeties
investigate_log("[key_name(usr)] turned off the [src] safeties", INVESTIGATE_ATMOS)
. = TRUE
update_appearance()
@@ -437,3 +522,5 @@
/obj/machinery/atmospherics/components/binary/thermomachine/heater/on
on = TRUE
icon_state = "heater_1"
#undef THERMOMACHINE_SAFE_TEMPERATURE
@@ -1,9 +1,3 @@
///Max amount of radiation that can be emitted per reaction cycle
#define FUSION_RAD_MAX 5000
///Maximum instability before the reaction goes endothermic
#define FUSION_INSTABILITY_ENDOTHERMALITY 4
///Maximum reachable fusion temperature
#define FUSION_MAXIMUM_TEMPERATURE 1e8
///Speed of light, in m/s
#define LIGHT_SPEED 299792458
///Calculation between the plank constant and the lambda of the lightwave
@@ -48,6 +48,13 @@ export const ThermoMachine = (props, context) => {
onClick={() => act('power')} />
)}>
<LabeledList>
<LabeledList.Item label="Safeties">
<Button
content={data.safeties ? 'Safeties ON' : 'Safeties OFF'}
color={data.safeties ? "green" : "red"}
disabled={!data.hacked}
onClick={() => act('safeties')} />
</LabeledList.Item>
<LabeledList.Item label="Use tank gas">
<Button
content={data.tank_gas ? 'Push gas' : 'Empty'}