diff --git a/_maps/RandomRuins/SandRuins/whitesands_surface_waterplant.dmm b/_maps/RandomRuins/SandRuins/whitesands_surface_waterplant.dmm index 0babadd59a8d..fe95fca0e82b 100644 --- a/_maps/RandomRuins/SandRuins/whitesands_surface_waterplant.dmm +++ b/_maps/RandomRuins/SandRuins/whitesands_surface_waterplant.dmm @@ -1482,7 +1482,7 @@ /turf/open/floor/plating, /area/ruin/powered) "LM" = ( -/obj/machinery/power/turbine, +/obj/machinery/power/shuttle/engine/turbine, /turf/open/floor/plating/asteroid/whitesands, /area/overmap_encounter/planetoid/sand/explored) "LN" = ( diff --git a/code/game/machinery/shuttle/shuttle_engine.dm b/code/game/machinery/shuttle/shuttle_engine.dm index 267c8d102918..c4fd424d4076 100644 --- a/code/game/machinery/shuttle/shuttle_engine.dm +++ b/code/game/machinery/shuttle/shuttle_engine.dm @@ -12,7 +12,7 @@ var/enabled = TRUE ///How much thrust this engine generates when burned fully. var/thrust = 0 - ///I don't really know what this is but it's used a lot + ///Whether this engine is actively providing thrust to the ship var/thruster_active = FALSE /** diff --git a/code/modules/power/turbine.dm b/code/game/machinery/shuttle/turbine.dm similarity index 54% rename from code/modules/power/turbine.dm rename to code/game/machinery/shuttle/turbine.dm index ba390b1cf873..7d310d37cd30 100644 --- a/code/modules/power/turbine.dm +++ b/code/game/machinery/shuttle/turbine.dm @@ -25,48 +25,60 @@ /obj/machinery/power/compressor name = "compressor" desc = "The compressor stage of a gas turbine generator." - icon = 'icons/obj/atmospherics/pipes/simple.dmi' + icon = 'icons/obj/atmospherics/components/turbine.dmi' icon_state = "compressor" density = TRUE resistance_flags = FIRE_PROOF CanAtmosPass = ATMOS_PASS_DENSITY + use_power = NO_POWER_USE // powered by gas flow + interacts_with_air = TRUE circuit = /obj/item/circuitboard/machine/power_compressor - var/obj/machinery/power/turbine/turbine + var/obj/machinery/power/shuttle/engine/turbine/turbine var/datum/gas_mixture/gas_contained - var/turf/inturf var/starter = 0 var/rpm = 0 var/rpmtarget = 0 var/capacity = 1e6 var/comp_id = 0 - var/efficiency + var/efficiency = 1 + var/intake_ratio = 0.1 // might add a way to adjust this in-game later -/obj/machinery/power/turbine/lavaland +/obj/machinery/power/shuttle/engine/turbine/lavaland destroy_output = TRUE /obj/machinery/power/compressor/Destroy() + SSair.stop_processing_machine(src) if (turbine && turbine.compressor == src) turbine.compressor = null + if(isopenturf(loc)) + loc.assume_air(gas_contained) + loc.air_update_turf() turbine = null return ..() -/obj/machinery/power/turbine +/obj/machinery/power/shuttle/engine/turbine name = "gas turbine generator" desc = "A gas turbine used for backup power generation." - icon = 'icons/obj/atmospherics/pipes/simple.dmi' + icon = 'icons/obj/atmospherics/components/turbine.dmi' icon_state = "turbine" density = TRUE resistance_flags = FIRE_PROOF CanAtmosPass = ATMOS_PASS_DENSITY + use_power = NO_POWER_USE // powered by gas flow + interacts_with_air = TRUE circuit = /obj/item/circuitboard/machine/power_turbine + thrust = 0 // no thrust by default + icon_state_closed = "turbine" + icon_state_open = "turbine" + icon_state_off = "turbine" var/opened = 0 var/obj/machinery/power/compressor/compressor - var/turf/outturf - var/lastgen + var/lastgen = 0 var/productivity = 1 var/destroy_output = FALSE //Destroy the output gas instead of actually outputting it. Used on lavaland to prevent cooking the zlevel -/obj/machinery/power/turbine/Destroy() +/obj/machinery/power/shuttle/engine/turbine/Destroy() + SSair.stop_processing_machine(src) if (compressor && compressor.turbine == src) compressor.turbine = null compressor = null @@ -74,29 +86,39 @@ // the inlet stage of the gas turbine electricity generator -/obj/machinery/power/compressor/Initialize() +/obj/machinery/power/compressor/Initialize(mapload) . = ..() // The inlet of the compressor is the direction it faces gas_contained = new - inturf = get_step(src, dir) + SSair.start_processing_machine(src, mapload) locate_machinery() if(!turbine) obj_break() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/power/compressor/LateInitialize() + . = ..() + var/turf/comp_turf = get_turf(src) + comp_turf.ImmediateCalculateAdjacentTurfs() // turbine blocks atmos so update the turf it's on or stuff breaks #define COMPFRICTION 5e5 /obj/machinery/power/compressor/locate_machinery() if(turbine) return - turbine = locate() in get_step(src, get_dir(inturf, src)) + turbine = locate() in get_step(src, turn(dir, 180)) if(turbine) + set_machine_stat(machine_stat & ~BROKEN) turbine.locate_machinery() + else + turbine = null + obj_break() /obj/machinery/power/compressor/RefreshParts() var/E = 0 for(var/obj/item/stock_parts/manipulator/M in component_parts) E += M.rating - efficiency = E / 6 + efficiency = max(E / 6, 1) /obj/machinery/power/compressor/examine(mob/user) . = ..() @@ -108,49 +130,63 @@ return if(default_change_direction_wrench(user, I)) - turbine = null - inturf = get_step(src, dir) - locate_machinery() if(turbine) to_chat(user, "Turbine connected.") set_machine_stat(machine_stat & ~BROKEN) else to_chat(user, "Turbine not connected.") - obj_break() return default_deconstruction_crowbar(I) -/obj/machinery/power/compressor/process() - if(!starter) - return - if(!turbine || (turbine.machine_stat & BROKEN)) - starter = FALSE - if(machine_stat & BROKEN || panel_open) - starter = FALSE - return - cut_overlays() - - rpm = 0.9* rpm + 0.1 * rpmtarget +/obj/machinery/power/compressor/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I) + . = ..() + if(panel_open) + set_machine_stat(machine_stat | MAINT) + else + set_machine_stat(machine_stat & ~MAINT) - // It's a simplified version taking only 1/10 of the moles from the turf nearby. It should be later changed into a better version - // above todo 7 years and counting +//update when moved or changing direction +/obj/machinery/power/compressor/setDir(newdir) + . = ..() + locate_machinery() - inturf.transfer_air_ratio(gas_contained, 0.1) +/obj/machinery/power/compressor/Move(atom/newloc, direct, glide_size_override) + . = ..() + locate_machinery() -// RPM function to include compression friction - be advised that too low/high of a compfriction value can make things screwy +/obj/machinery/power/compressor/process(delta_time) + return +/obj/machinery/power/compressor/process_atmos(delta_time) + // RPM function to include compression friction - be advised that too low/high of a compfriction value can make things screwy + rpm -= 1 + rpm = (0.9 * rpm) + (0.1 * rpmtarget) rpm = min(rpm, (COMPFRICTION*efficiency)/2) - rpm = max(0, rpm - (rpm*rpm)/(COMPFRICTION*efficiency)) + rpm = max(0, rpm - (rpm**2)/(COMPFRICTION*efficiency)) - if(starter && !(machine_stat & NOPOWER)) - use_power(2800) - if(rpm<1000) - rpmtarget = 1000 - else - if(rpm<1000) - rpmtarget = 0 + update_overlays() + + if(!turbine || (turbine.machine_stat & BROKEN)) + locate_machinery() // try to find the other part if we somehow got disconnected + + if((machine_stat & (BROKEN|MAINT)) || !starter) // if we didn't find it... + rpmtarget = 0 + return + + var/turf/inturf = get_step(src, dir) + var/datum/gas_mixture/environment = inturf.return_air() + var/external_pressure = environment.return_pressure() + var/pressure_delta = external_pressure - gas_contained.return_pressure() + + // Equalize the gas between the environment and the internal gas mix + if(pressure_delta > 0) + var/datum/gas_mixture/removed = environment.remove_ratio((1 - ((1 - intake_ratio)**delta_time)) * pressure_delta / (external_pressure * 2)) // silly math to keep it consistent with delta_time + gas_contained.merge(removed) + inturf.air_update_turf() +/obj/machinery/power/compressor/update_overlays() + . = ..() if(rpm>50000) add_overlay(mutable_appearance(icon, "comp-o4", FLY_LAYER)) else if(rpm>10000) @@ -159,91 +195,122 @@ add_overlay(mutable_appearance(icon, "comp-o2", FLY_LAYER)) else if(rpm>500) add_overlay(mutable_appearance(icon, "comp-o1", FLY_LAYER)) - //TODO: DEFERRED // These are crucial to working of a turbine - the stats modify the power output. TurbGenQ modifies how much raw energy can you get from // rpms, TurbGenG modifies the shape of the curve - the lower the value the less straight the curve is. #define TURBGENQ 100000 #define TURBGENG 0.5 +#define POWER_TO_THRUST 0.001 // power production to thrust ratio -/obj/machinery/power/turbine/Initialize() +/obj/machinery/power/shuttle/engine/turbine/Initialize(mapload) . = ..() -// The outlet is pointed at the direction of the turbine component - outturf = get_step(src, dir) + SSair.start_processing_machine(src, mapload) locate_machinery() if(!compressor) obj_break() connect_to_network() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/power/shuttle/engine/turbine/LateInitialize() + . = ..() + var/turf/comp_turf = get_turf(src) + comp_turf.ImmediateCalculateAdjacentTurfs() // turbine blocks atmos so update the turf it's on or stuff breaks -/obj/machinery/power/turbine/RefreshParts() +/obj/machinery/power/shuttle/engine/turbine/RefreshParts() var/P = 0 for(var/obj/item/stock_parts/capacitor/C in component_parts) P += C.rating productivity = P / 6 -/obj/machinery/power/turbine/examine(mob/user) +/obj/machinery/power/shuttle/engine/turbine/examine(mob/user) . = ..() if(in_range(user, src) || isobserver(user)) . += "The status display reads: Productivity at [productivity*100]%." -/obj/machinery/power/turbine/locate_machinery() +/obj/machinery/power/shuttle/engine/turbine/locate_machinery() if(compressor) return - compressor = locate() in get_step(src, get_dir(outturf, src)) + compressor = locate() in get_step(src, turn(dir, 180)) if(compressor) + set_machine_stat(machine_stat & ~BROKEN) compressor.locate_machinery() + else + compressor = null + obj_break() -/obj/machinery/power/turbine/process() +/obj/machinery/power/shuttle/engine/turbine/process(delta_time) + add_avail(lastgen) // add power in process() so it doesn't update power output separately from the rest of the powernet (bad) + update_overlays() +/obj/machinery/power/shuttle/engine/turbine/process_atmos(delta_time) if(!compressor) set_machine_stat(BROKEN) + locate_machinery() // try to find the missing piece - if((machine_stat & BROKEN) || panel_open) + if(machine_stat & (BROKEN|MAINT)) // we're only running half a turbine, don't continue return - if(!compressor.starter) - return - cut_overlays() // This is the power generation function. If anything is needed it's good to plot it in EXCEL before modifying // the TURBGENQ and TURBGENG values lastgen = ((compressor.rpm / TURBGENQ)**TURBGENG) * TURBGENQ * productivity + thrust = lastgen * POWER_TO_THRUST // second law - add_avail(lastgen) - - // Weird function but it works. Should be something else... - - var/newrpm = ((compressor.gas_contained.return_temperature()) * compressor.gas_contained.total_moles())/4 + var/turf/outturf = get_step(src, dir) + if(!LAZYLEN(outturf.atmos_adjacent_turfs)) + compressor.rpmtarget = 0 + return - newrpm = max(0, newrpm) + // Move gas from the compressor to the outlet + var/datum/gas_mixture/environment = outturf.return_air() + var/internal_pressure = compressor.gas_contained.return_pressure() + var/pressure_delta = internal_pressure - environment.return_pressure() - if(!compressor.starter || newrpm > 1000) - compressor.rpmtarget = newrpm + // Now set the compressor's RPM target based on how much gas is flowing through + compressor.rpmtarget = max(0, pressure_delta * compressor.gas_contained.return_volume() / (R_IDEAL_GAS_EQUATION * 4)) - if(compressor.gas_contained.total_moles()>0) - var/oamount = min(compressor.gas_contained.total_moles(), (compressor.rpm+100)/35000*compressor.capacity) + // Equalize the gas between the internal gas mix and the environment + if(pressure_delta > 0) + var/datum/gas_mixture/removed = compressor.gas_contained.remove_ratio(pressure_delta / (internal_pressure * 2)) if(destroy_output) - compressor.gas_contained.set_moles(compressor.gas_contained.get_moles() - oamount) - else - outturf.assume_air_moles(compressor.gas_contained, oamount) + qdel(removed) + return + outturf.assume_air(removed) + outturf.air_update_turf() + +// Return the current thrust amount +/obj/machinery/power/shuttle/engine/turbine/burn_engine(percentage, deltatime) + return thrust * deltatime * (percentage / 100) + +// Return the current power output +/obj/machinery/power/shuttle/engine/turbine/return_fuel() + return lastgen + +// Return the maximum power output +/obj/machinery/power/shuttle/engine/turbine/return_fuel_cap() + return ((COMPFRICTION*(compressor ? compressor.efficiency : 1) / (TURBGENQ*4))**TURBGENG) * TURBGENQ * productivity + +// Return the maximum power output +/obj/machinery/power/shuttle/engine/turbine/update_engine() + if(!(flags_1 & INITIALIZED_1)) + return FALSE + thruster_active = !panel_open && compressor + return thruster_active // If it works, put an overlay that it works! - +/obj/machinery/power/shuttle/engine/turbine/update_overlays() + . = ..() if(lastgen > 100) add_overlay(mutable_appearance(icon, "turb-o", FLY_LAYER)) -/obj/machinery/power/turbine/attackby(obj/item/I, mob/user, params) +/obj/machinery/power/shuttle/engine/turbine/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I)) return if(default_change_direction_wrench(user, I)) - compressor = null - outturf = get_step(src, dir) - locate_machinery() if(compressor) to_chat(user, "Compressor connected.") - set_machine_stat(machine_stat & ~BROKEN) else to_chat(user, "Compressor not connected.") obj_break() @@ -251,25 +318,42 @@ default_deconstruction_crowbar(I) -/obj/machinery/power/turbine/ui_interact(mob/user, datum/tgui/ui) +/obj/machinery/power/shuttle/engine/turbine/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I) + . = ..() + if(panel_open) + set_machine_stat(machine_stat | MAINT) + else + set_machine_stat(machine_stat & ~MAINT) + +// update if it moves or changes direction +/obj/machinery/power/shuttle/engine/turbine/setDir(newdir) + . = ..() + locate_machinery() + +/obj/machinery/power/shuttle/engine/turbine/Move(atom/newloc, direct, glide_size_override) + . = ..() + locate_machinery() + +/obj/machinery/power/shuttle/engine/turbine/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "TurbineComputer", name) ui.open() -/obj/machinery/power/turbine/ui_data(mob/user) +/obj/machinery/power/shuttle/engine/turbine/ui_data(mob/user) var/list/data = list() data["compressor"] = compressor ? TRUE : FALSE - data["compressor_broke"] = (!compressor || (compressor.machine_stat & BROKEN)) ? TRUE : FALSE + data["compressor_broke"] = (!compressor || (compressor.machine_stat & (BROKEN|MAINT))) ? TRUE : FALSE data["turbine"] = compressor?.turbine ? TRUE : FALSE - data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.machine_stat & BROKEN)) ? TRUE : FALSE + data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.machine_stat & (BROKEN|MAINT))) ? TRUE : FALSE data["online"] = compressor?.starter data["power"] = DisplayPower(compressor?.turbine?.lastgen) data["rpm"] = compressor?.rpm data["temp"] = compressor?.gas_contained.return_temperature() + data["pressure"] = compressor?.gas_contained.return_pressure() return data -/obj/machinery/power/turbine/ui_act(action, params) +/obj/machinery/power/shuttle/engine/turbine/ui_act(action, params) . = ..() if(.) return @@ -306,7 +390,7 @@ /obj/machinery/computer/turbine_computer/locate_machinery() if(id) - for(var/obj/machinery/power/compressor/C in GLOB.machines) + for(var/obj/machinery/power/compressor/C in SSair.atmos_air_machinery) if(C.comp_id == id) compressor = C return @@ -322,13 +406,14 @@ /obj/machinery/computer/turbine_computer/ui_data(mob/user) var/list/data = list() data["compressor"] = compressor ? TRUE : FALSE - data["compressor_broke"] = (!compressor || (compressor.machine_stat & BROKEN)) ? TRUE : FALSE + data["compressor_broke"] = (!compressor || (compressor.machine_stat & (BROKEN|MAINT))) ? TRUE : FALSE data["turbine"] = compressor?.turbine ? TRUE : FALSE - data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.machine_stat & BROKEN)) ? TRUE : FALSE + data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.machine_stat & (BROKEN|MAINT))) ? TRUE : FALSE data["online"] = compressor?.starter data["power"] = DisplayPower(compressor?.turbine?.lastgen) data["rpm"] = compressor?.rpm data["temp"] = compressor?.gas_contained.return_temperature() + data["pressure"] = compressor?.gas_contained.return_pressure() return data /obj/machinery/computer/turbine_computer/ui_act(action, params) @@ -345,6 +430,7 @@ locate_machinery() . = TRUE +#undef POWER_TO_THRUST #undef COMPFRICTION #undef TURBGENQ #undef TURBGENG diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 306634a639fc..13576abf2f43 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -257,7 +257,7 @@ /obj/item/circuitboard/machine/power_turbine name = "Power Turbine (Machine Board)" icon_state = "engineering" - build_path = /obj/machinery/power/turbine + build_path = /obj/machinery/power/shuttle/engine/turbine req_components = list( /obj/item/stack/cable_coil = 5, /obj/item/stock_parts/capacitor = 6) diff --git a/icons/obj/atmospherics/components/turbine.dmi b/icons/obj/atmospherics/components/turbine.dmi new file mode 100644 index 000000000000..6e499911a75b Binary files /dev/null and b/icons/obj/atmospherics/components/turbine.dmi differ diff --git a/shiptest.dme b/shiptest.dme index 9840f4d4cc9c..80ff9340a083 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -956,6 +956,7 @@ #include "code\game\machinery\shuttle\shuttle_engine.dm" #include "code\game\machinery\shuttle\shuttle_engine_types.dm" #include "code\game\machinery\shuttle\shuttle_heater.dm" +#include "code\game\machinery\shuttle\turbine.dm" #include "code\game\machinery\telecomms\broadcasting.dm" #include "code\game\machinery\telecomms\machine_interactions.dm" #include "code\game\machinery\telecomms\telecomunications.dm" @@ -2915,7 +2916,6 @@ #include "code\modules\power\solar.dm" #include "code\modules\power\terminal.dm" #include "code\modules\power\tracker.dm" -#include "code\modules\power\turbine.dm" #include "code\modules\power\singularity\boh_tear.dm" #include "code\modules\power\singularity\collector.dm" #include "code\modules\power\singularity\containment_field.dm" diff --git a/tgui/packages/tgui/interfaces/TurbineComputer.js b/tgui/packages/tgui/interfaces/TurbineComputer.js index f11eb9880728..f8c9e2677ff3 100644 --- a/tgui/packages/tgui/interfaces/TurbineComputer.js +++ b/tgui/packages/tgui/interfaces/TurbineComputer.js @@ -1,5 +1,6 @@ import { useBackend } from '../backend'; import { Button, LabeledList, Section } from '../components'; +import { formatSiUnit } from '../format'; import { Window } from '../layouts'; export const TurbineComputer = (props, context) => { @@ -11,7 +12,7 @@ export const TurbineComputer = (props, context) => { !data.turbine_broke ); return ( - +
{ {data.temp} K + + {formatSiUnit(data.pressure * 1000, 1, 'Pa')} + {data.power}