diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm
index 637b2df815f..0271b2e4601 100644
--- a/code/__HELPERS/maths.dm
+++ b/code/__HELPERS/maths.dm
@@ -159,10 +159,11 @@
* Args:
* - power: The value of power to format.
* - convert: Whether to convert this from joules.
+ * - datum/controller/subsystem/scheduler: used in the conversion
* Returns: The string containing the formatted power.
*/
-/proc/display_power(power, convert = TRUE)
- power = convert ? energy_to_power(power) : power
+/proc/display_power(power, convert = TRUE, datum/controller/subsystem/scheduler = SSmachines)
+ power = convert ? energy_to_power(power, scheduler) : power
return siunit(power, "W", 3)
/**
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index 1fdb5fa1302..58ef3d8bbef 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -2,6 +2,7 @@
#define HEATER_MODE_HEAT "heat"
#define HEATER_MODE_COOL "cool"
#define HEATER_MODE_AUTO "auto"
+#define BASE_HEATING_ENERGY (40 KILO JOULES)
/obj/machinery/space_heater
anchored = FALSE
@@ -27,10 +28,8 @@
var/set_mode = HEATER_MODE_AUTO
///The temperature we trying to get to
var/target_temperature = T20C
- ///How much heat/cold we can deliver per tier
- var/base_heating_power = 40 KILO JOULES
///How much heat/cold we can deliver
- var/heating_power = 40 KILO JOULES
+ var/heating_energy = 40 KILO JOULES
///How efficiently we can deliver that heat/cold (higher indicates less cell consumption)
var/efficiency = 20
///The amount of degrees above and below the target temperature for us to change mode to heater or cooler
@@ -97,12 +96,16 @@
else
. += span_warning("There is no power cell installed.")
if(in_range(user, src) || isobserver(user))
- var/target_temp = round(target_temperature - T0C, 1)
- var/min_temp = max(settable_temperature_median - settable_temperature_range, TCMB) - T0C
- var/max_temp = settable_temperature_median + settable_temperature_range - T0C
- . += span_info("The status display reads:
Heating power: [siunit(heating_power, "W", 1)] at [(efficiency / 20) * 100]% efficiency.
Target temperature: [target_temp]°C \[[min_temp]°C - [max_temp]°C]") // Base efficiency 100%, higher with upgraded components
+ . += heating_examine()
. += span_notice("Right-click to toggle [on ? "off" : "on"].")
+///Returns the heating power of this machine as an examine
+/obj/machinery/space_heater/proc/heating_examine()
+ var/target_temp = round(target_temperature - T0C, 1)
+ var/min_temp = max(settable_temperature_median - settable_temperature_range, TCMB) - T0C
+ var/max_temp = settable_temperature_median + settable_temperature_range - T0C
+ return span_notice("The status display reads:
Heating power: [display_power(heating_energy, convert = TRUE, scheduler = SSair)] at [(efficiency / 20) * 100]% efficiency.
Target temperature: [target_temp]°C [min_temp]°C - [max_temp]°C]\n")
+
/obj/machinery/space_heater/update_icon_state()
. = ..()
icon_state = "[base_icon_state]-[on ? mode : "off"]"
@@ -117,14 +120,10 @@
return ..()
/obj/machinery/space_heater/process_atmos()
- if(!on || !is_operational)
+ if(!on || !is_operational || QDELETED(cell) || cell.charge <= 1)
if (on) // If it's broken, turn it off too
on = FALSE
- return PROCESS_KILL
-
- if(!cell || cell.charge <= 1)
- on = FALSE
- update_appearance()
+ update_appearance()
return PROCESS_KILL
var/turf/local_turf = loc
@@ -149,25 +148,23 @@
if(mode == HEATER_MODE_STANDBY)
return
- var/heat_capacity = enviroment.heat_capacity()
- var/required_energy = abs(enviroment.temperature - target_temperature) * heat_capacity
- required_energy = min(required_energy, heating_power)
-
+ var/list/turfs = (local_turf.atmos_adjacent_turfs || list()) + local_turf
+ var/required_energy = abs(enviroment.temperature - target_temperature) * enviroment.heat_capacity()
+ required_energy = min(required_energy, heating_energy, (cell.charge * efficiency) / length(turfs))
if(required_energy < 1)
return
- var/delta_temperature = required_energy / heat_capacity
+ var/delta_energy = required_energy
if(mode == HEATER_MODE_COOL)
- delta_temperature *= -1
-
- if(delta_temperature == 0)
+ delta_energy *= -1
+ if(delta_energy == 0)
return
- for(var/turf/open/turf in ((local_turf.atmos_adjacent_turfs || list()) + local_turf))
+ for(var/turf/open/turf in turfs)
var/datum/gas_mixture/turf_gasmix = turf.return_air()
- turf_gasmix.temperature += delta_temperature
+ turf_gasmix.temperature += delta_energy / turf_gasmix.heat_capacity()
air_update_turf(FALSE, FALSE)
- cell.use(required_energy / efficiency)
+ cell.use((required_energy * length(turfs)) / efficiency, force = TRUE)
/obj/machinery/space_heater/RefreshParts()
. = ..()
@@ -178,7 +175,7 @@
for(var/datum/stock_part/capacitor/capacitor in component_parts)
cap += capacitor.tier
- heating_power = laser * base_heating_power
+ heating_energy = laser * BASE_HEATING_ENERGY
settable_temperature_range = cap * 30
efficiency = (cap + 1) * 10
@@ -321,38 +318,52 @@
. = ..()
QDEL_NULL(beaker)
+/obj/machinery/space_heater/improvised_chem_heater/heating_examine()
+ . = ..()
+
+ var/power_mod = 0.1 * chem_heating_power
+ if(set_mode == HEATER_MODE_AUTO)
+ power_mod *= 0.5
+ . += span_notice("Heating power for beaker: [display_power(heating_energy * power_mod, convert = TRUE)]")
+
+/obj/machinery/space_heater/improvised_chem_heater/toggle_power(user)
+ . = ..()
+ if(on)
+ begin_processing()
+
/obj/machinery/space_heater/improvised_chem_heater/process(seconds_per_tick)
- if(!on)
- update_appearance()
+ if(!on || !is_operational || QDELETED(cell) || cell.charge <= 1 || QDELETED(beaker))
+ if (on) // If it's broken, turn it off too
+ on = FALSE
+ update_appearance()
return PROCESS_KILL
- if(!is_operational || !cell || cell.charge <= 0)
- on = FALSE
- update_appearance()
- return PROCESS_KILL
-
- if(!beaker)//No beaker to heat
- update_appearance()
- return
-
if(beaker.reagents.total_volume)
var/power_mod = 0.1 * chem_heating_power
switch(set_mode)
if(HEATER_MODE_AUTO)
power_mod *= 0.5
- beaker.reagents.adjust_thermal_energy((target_temperature - beaker.reagents.chem_temp) * power_mod * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume)
- beaker.reagents.handle_reactions()
if(HEATER_MODE_HEAT)
if(target_temperature < beaker.reagents.chem_temp)
return
- beaker.reagents.adjust_thermal_energy((target_temperature - beaker.reagents.chem_temp) * power_mod * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume)
if(HEATER_MODE_COOL)
if(target_temperature > beaker.reagents.chem_temp)
return
- beaker.reagents.adjust_thermal_energy((target_temperature - beaker.reagents.chem_temp) * power_mod * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume)
- var/required_energy = heating_power * seconds_per_tick * (power_mod * 4)
- cell.use(required_energy / efficiency)
+
+ var/required_energy = abs(target_temperature - beaker.reagents.chem_temp) * power_mod * seconds_per_tick * beaker.reagents.heat_capacity()
+ required_energy = min(required_energy, heating_energy, cell.charge * efficiency)
+ if(required_energy < 1)
+ return
+
+ var/delta_energy = required_energy
+ if(mode == HEATER_MODE_COOL)
+ delta_energy *= -1
+ if(delta_energy == 0)
+ return
+
+ beaker.reagents.adjust_thermal_energy(delta_energy)
beaker.reagents.handle_reactions()
+ cell.use(required_energy / efficiency, force = TRUE)
update_appearance()
/obj/machinery/space_heater/improvised_chem_heater/ui_data()
@@ -403,7 +414,6 @@
item.afterattack(beaker, user, 1)
return
-
/obj/machinery/space_heater/improvised_chem_heater/on_deconstruction(disassembled = TRUE)
. = ..()
if(disassembled)
@@ -458,7 +468,7 @@
for(var/datum/stock_part/capacitor/capacitor in component_parts)
capacitors_rating += capacitor.tier
- heating_power = lasers_rating * 20000
+ heating_energy = lasers_rating * 20000
settable_temperature_range = capacitors_rating * 50 //-20 - 80 at base
efficiency = (capacitors_rating + 1) * 10
@@ -473,3 +483,4 @@
#undef HEATER_MODE_HEAT
#undef HEATER_MODE_COOL
#undef HEATER_MODE_AUTO
+#undef BASE_HEATING_ENERGY