From 6d889fac5eb5cc6719398b40c77e2abe62ee4c39 Mon Sep 17 00:00:00 2001 From: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Date: Mon, 1 Apr 2024 20:51:15 +0530 Subject: [PATCH] Space heater power and heating tweaks (#82344) ## About The Pull Request - Fixes #82342 - Space heater computes total power for heating adjacent turfs and uses cell energy once rather multiple times per turf - Improvised space heater actually works & uses beaker heat capacity and not a constant of 200 for heating beaker contents ## Changelog :cl: SyncIt21,Pickle-Coding fix: space heater(including improvised) turns off when cell is drained fix: optimized power usage for both improvised and main space heater. Improvised heater now works & uses beaker heat capacity /:cl: --- code/__HELPERS/maths.dm | 5 +- code/game/machinery/spaceheater.dm | 99 +++++++++++++++++------------- 2 files changed, 58 insertions(+), 46 deletions(-) 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