Skip to content

Commit

Permalink
Merge pull request #1412 from Yawn-Wider/heatengine
Browse files Browse the repository at this point in the history
Boiler/Heat Engine Atmospheric engine changes [MDB IGNORE] [IDB IGNORE]
  • Loading branch information
izac112 committed Mar 30, 2024
2 parents 977c50d + eba08d6 commit 6b4c617
Show file tree
Hide file tree
Showing 26 changed files with 4,795 additions and 2,774 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"**/.pnp.*": true
},
"workbench.editorAssociations": {
"*.dmi": "imagePreview.previewEditor"
"*.dmi": "dmiEditor.dmiEditor"
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
Expand Down
215 changes: 215 additions & 0 deletions code/ATMOSPHERICS/components/station_boiler.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
var/global/list/stationboilers = list() //Should only ever have one, caching to locate easily by radiators

/obj/machinery/atmospherics/binary/stationboiler
name = "Station Boiler"
desc = "A large, phoron-infused wood powered, super boiler. Capable of keeping a entire colony heated up"
icon = 'icons/obj/machines/heat_boiler_yw.dmi'
icon_state = "boiler_off"
use_power = USE_POWER_OFF
bullet_vulnerability = 0
anchored = TRUE
density = TRUE
pixel_x = -32

var/is_active = FALSE
var/ignited = TRUE
var/target_heat_temperature = T20C //The temperature we want the pipes to be heated to
var/wood_per_process = 1SECOND
var/list/stored_material = list(MAT_LOG = 1HOUR) //1 hour of mats free
var/list/storage_capacity = list(MAT_LOG = 4HOUR) //can hold enough for 4 hours

/obj/machinery/atmospherics/binary/stationboiler/New()
..()
stationboilers.Add(src)

/obj/machinery/atmospherics/binary/stationboiler/process()
..()
//STEP 1 - Pump gas through - using the passive gate method
var/output_starting_pressure = air2.return_pressure()
var/input_starting_pressure = air1.return_pressure()
var/pressure_delta = input_starting_pressure - output_starting_pressure
var/datum/gas_mixture/source = air1
var/datum/gas_mixture/sink = air2

if((pressure_delta > 0.01) && (air1.temperature > 0 || air2.temperature > 0))
// If node1 is a network of more than 1 pipe, we want to transfer from that whole network, otw use just node1, as current
if(istype(node1, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/p = node1
if(istype(p.parent, /datum/pipeline)) // Nested if-blocks to avoid the mystical :
var/datum/pipeline/l = p.parent
if(istype(l.air, /datum/gas_mixture))
source = l.air
// If node2 is a network of more than 1 pipe, we want to transfer to that whole network, otw use just node2, as current
if(istype(node2, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/p = node2
if(istype(p.parent, /datum/pipeline))
var/datum/pipeline/l = p.parent
if(istype(l.air, /datum/gas_mixture))
sink = l.air

var/transfer_moles = max(0, calculate_equalize_moles(source, sink)) // Not regulated, don't care about flow rate
var/returnval = pump_gas_passive(src, source, sink, transfer_moles)

if(returnval >= 0)
if(network1)
network1.update = 1
if(network2)
network2.update = 1

//STEP 2 - Check if we can heat the gas
if(!ignited || stored_material[MAT_LOG] < wood_per_process) //Out of wood
ignited = FALSE
is_active = 0
SSair.handle_planet_temperature_change = 1 //Start cooling down the world
update_icon()
return

is_active = 1
//We have wood - SSAir can stop handling temperatures
SSair.handle_planet_temperature_change = 0

//STEP 3 - Consume the resources
stored_material[MAT_LOG] -= wood_per_process
stored_material[MAT_LOG] = max(stored_material[MAT_LOG], 0)

//Heat up the air instantly, magically
if(sink)
sink.temperature = target_heat_temperature
else
air2.temperature = target_heat_temperature
update_icon()

/obj/machinery/atmospherics/binary/stationboiler/update_icon()
if(ignited)
icon_state = "boiler_on"
else
icon_state = "boiler_off"
return 1

// Attept to load materials. Returns 0 if item wasn't a stack of materials, otherwise 1 (even if failed to load)
/obj/machinery/atmospherics/binary/stationboiler/proc/try_load_materials(var/mob/user, var/obj/item/stack/material/S)
if(!istype(S))
return 0
if(!(S.material.name in stored_material))
to_chat(user, "<span class='warning'>\The [src] doesn't accept [material_display_name(S.material)]!</span>")
return 1
var/max_res_amount = storage_capacity[S.material.name]
if(stored_material[S.material.name] + S.perunit <= max_res_amount)
var/count = 0
while(stored_material[S.material.name] + S.perunit <= max_res_amount && S.get_amount() >= 1)
stored_material[S.material.name] += S.perunit
S.use(1)
count++
user.visible_message("\The [user] inserts [S.name] into \the [src].", "<span class='notice'>You insert [count] [S.name] into \the [src].</span>")
updateUsrDialog()
else
to_chat(user, "<span class='warning'>\The [src] cannot hold more [S.name].</span>")
return 1

/obj/machinery/atmospherics/binary/stationboiler/attackby(obj/item/weapon/W as obj, mob/user as mob)
add_fingerprint(user)
if(try_load_materials(user, W))
return
else
to_chat(user, "<span class='notice'>You cannot insert this item into \the [src]!</span>")
return

// Start of "TGUI stuff"
/obj/machinery/atmospherics/binary/stationboiler/attack_ai(mob/user)
add_hiddenprint(user)
tgui_interact(user)

/obj/machinery/atmospherics/binary/stationboiler/attack_hand(mob/user)
add_fingerprint(user)
tgui_interact(user)

/obj/machinery/atmospherics/binary/stationboiler/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "StationBoiler", name)
ui.open()

/obj/machinery/atmospherics/binary/stationboiler/tgui_act(action, params)
if(..())
return TRUE
add_fingerprint(usr)

switch(action)
if("ejectMaterial")
var/matName = params["mat"]
if(!(matName in stored_material))
return
var/choice = tgui_alert(usr, "Would you like to eject a stack, everything or a specific amount from the boiler ","Station Boiler - Eject",list("Stack","Everything","Specific Amount"))
switch(choice)
if("Stack")
eject_materials(matName, 0)
. = TRUE
if("Everything")
eject_materials(matName, -1)
. = TRUE
if("Specific Amount")
var/amount = tgui_input_number(usr, "How many logs would you like to Eject", "Station Boiler - Eject")
if(amount <= 0)
return
eject_materials(matName, amount)
. = TRUE

if("ignite")
try_ignite()
. = TRUE

/obj/machinery/atmospherics/binary/stationboiler/tgui_data(mob/user)
var/data[0]

var/materials_ui[0]
for(var/M in stored_material)
materials_ui[++materials_ui.len] = list(
"name" = M,
"display" = material_display_name(M),
"qty" = stored_material[M],
"max" = storage_capacity[M],
"percent" = (stored_material[M] / storage_capacity[M] * 100))
data["materials"] = materials_ui

data["timeleft"] = get_time_left()

if(air1 && network1 && node1)
data["input"] = list(
"pressure" = air1.return_pressure(),
"temp" = convert_k2c(air1.temperature))
if(air2 && network2 && node2)
data["output"] = list(
"pressure" = air2.return_pressure(),
"temp" = convert_k2c(air2.temperature))

return data
// End of "TGUI stuff"

/obj/machinery/atmospherics/binary/stationboiler/proc/get_time_left()
if(stored_material[MAT_LOG] <= 0)
return SecondsToTimestamp(0)
return SecondsToTimestamp(stored_material[MAT_LOG]/wood_per_process)

/obj/machinery/atmospherics/binary/stationboiler/fall_apart(var/severity = 3, var/scatter = TRUE)
return //Invincible machine

/obj/machinery/atmospherics/binary/stationboiler/proc/try_ignite()
if(stored_material[MAT_LOG] >= wood_per_process)
ignited = TRUE
update_icon()

// 0 amount = 0 means ejecting a full stack; -1 means eject everything
/obj/machinery/atmospherics/binary/stationboiler/proc/eject_materials(var/material_name, var/amount)
var/recursive = amount == -1 ? 1 : 0
var/datum/material/matdata = get_material_by_name(material_name)
var/stack_type = matdata.stack_type
var/obj/item/stack/material/S = new stack_type(loc)
if(amount <= 0)
amount = S.max_amount
var/ejected = min(round(stored_material[material_name] / S.perunit), amount)
if(!S.set_amount(min(ejected, amount)))
return
S.update_icon()
stored_material[material_name] -= ejected * S.perunit
if(recursive && stored_material[material_name] >= S.perunit)
eject_materials(material_name, -1)
37 changes: 37 additions & 0 deletions code/ATMOSPHERICS/components/station_boiler_radiator.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/obj/machinery/stationboiler_radiator
name = "Station Radiator"
desc = "A radiator pipe connected to the station boiler, used to keep the rooms warm"
icon = 'icons/obj/machines/floor_radiator_yw.dmi'

plane = PLATING_PLANE
layer = FLOOR_HEATER_LAYER

icon_state = "off"
use_power = USE_POWER_OFF
bullet_vulnerability = 0 //Invincible machine
anchored = TRUE
density = FALSE
var/target_heat_temperature = T20C //The temperature we want the room to reach
var/thermal_energy_change = 4000 //How much energy we can process
var/obj/machinery/atmospherics/binary/stationboiler/assignedBoiler

/obj/machinery/stationboiler_radiator/process()
..()
if(!assignedBoiler && stationboilers)
assignedBoiler = pick(stationboilers)
if(!assignedBoiler || !assignedBoiler.is_active)
if(icon_state != "off")
icon_state = "off"
return

if(icon_state != "on")
icon_state = "on"
if(istype(loc, /turf/simulated/))
var/datum/gas_mixture/environment = loc.return_air()
var/neededEnergy = environment.get_thermal_energy_change(target_heat_temperature)
if(neededEnergy > 0)
neededEnergy = min(neededEnergy, thermal_energy_change)
environment.add_thermal_energy(neededEnergy)

/obj/machinery/atmospherics/binary/stationboiler/fall_apart(var/severity = 3, var/scatter = TRUE)
return //Invincible machine
3 changes: 3 additions & 0 deletions code/ZAS/Controller.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Class Procs:
var/list/active_fire_zones = list()
var/list/active_hotspots = list()
var/list/active_edges = list()
var/list/zones_planet_temperature_to_update = list() // YW Addition - zones_planet_temperature_to_update

var/active_zones = 0
var/current_cycle = 0
Expand All @@ -87,11 +88,13 @@ Class Procs:
/datum/controller/subsystem/air/proc/add_zone(zone/z)
zones.Add(z)
z.name = "Zone [next_id++]"
zones_planet_temperature_to_update.Add(z) //YW Addition - planet temp
mark_zone_update(z)

/datum/controller/subsystem/air/proc/remove_zone(zone/z)
zones.Remove(z)
zones_to_update.Remove(z)
zones_planet_temperature_to_update.Remove(z) //YW Addition - planet temp

/datum/controller/subsystem/air/proc/air_blocked(turf/A, turf/B)
#ifdef ZASDBG
Expand Down
1 change: 1 addition & 0 deletions code/__defines/_planes+layers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ What is the naming convention for planes or layers?

// Turf Planes
#define PLATING_PLANE -44 // Plating
#define FLOOR_HEATER_LAYER 2.03 // YW Addition: Under objects, even when planeswapped
#define DISPOSAL_LAYER 2.1 // Under objects, even when planeswapped
#define PIPES_LAYER 2.2 // Under objects, even when planeswapped
#define WIRES_LAYER 2.3 // Under objects, even when planeswapped
Expand Down
1 change: 1 addition & 0 deletions code/__defines/map.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define MAP_LEVEL_PERSIST 0x100 // Z-levels where SSpersistence should persist between rounds
#define MAP_LEVEL_MAPPABLE 0x200 // Z-levels where mapping units will work fully
#define MAP_LEVEL_BELOW_BLOCKED 0x400 // Z-levels in multiz with level below not meant to be 'normally' accessible
#define MAP_LEVEL_TEMPERATURE_CHANGEABLE 0x800 // YW Addition: Z-levels in multiz where we can make the station interior math the exterior temps

// Misc map defines.
#define SUBMAP_MAP_EDGE_PAD 8 // Automatically created submaps are forbidden from being this close to the main map's edge. //VOREStation Edit
3 changes: 2 additions & 1 deletion code/__defines/misc_vr.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#define SHUTTLE_CRASHED 3 // Yup that can happen now

#define BLUE_SHIELDED 2 // Shield from bluespace teleportation (telescience)
#define TEMPERATURE_SHIELDED 4 // YW Addition: Temperature change shielding

//Assistant/Visitor/Whatever
#define USELESS_JOB "Visitor"
Expand Down Expand Up @@ -81,4 +82,4 @@
#define RESIZE_A_HUGEBIG (RESIZE_HUGE + RESIZE_BIG) / 2
#define RESIZE_A_BIGNORMAL (RESIZE_BIG + RESIZE_NORMAL) / 2
#define RESIZE_A_NORMALSMALL (RESIZE_NORMAL + RESIZE_SMALL) / 2
#define RESIZE_A_SMALLTINY (RESIZE_SMALL + RESIZE_TINY) / 2
#define RESIZE_A_SMALLTINY (RESIZE_SMALL + RESIZE_TINY) / 2
9 changes: 9 additions & 0 deletions code/_helpers/time.dm
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,12 @@ GLOBAL_VAR_INIT(round_start_time, 0)
if(hour)
hourT = " and [hour] hour[(hour != 1)? "s":""]"
return "[day] day[(day != 1)? "s":""][hourT][minuteT][secondT]"

//YW ADDITIONS START
//Takes seconds, returns in hh:mm:ss
/proc/SecondsToTimestamp(seconds)
var/second = seconds%60
var/minute = FLOOR((seconds/60), 1)%60
var/hours = FLOOR((seconds/3600), 1)
return "[hours]:[minute]:[second]"
//YW ADDITIONS END
Loading

0 comments on commit 6b4c617

Please sign in to comment.