From 1c0c0805a2e28ecb4b3c8305e38cd378b8f3ece8 Mon Sep 17 00:00:00 2001 From: lessthanthree <83487515+lessthnthree@users.noreply.github.com> Date: Tue, 30 Jan 2024 23:05:58 +0000 Subject: [PATCH] Fixes the tram's schrodinger-like power consumption (#81122) ## About The Pull Request Fixes https://github.com/tgstation/tgstation/issues/81106. The tram's dynamic power use does not get recalculated when leaving an area because the powernet between areas is made for static loads, This leads to APCs being drained quickly consuming too much power, or consuming negative energy leading to an APC being charged. The amount of times use_power is called on tram crossing signals during processing also leads to unexpected power consumption. This moves tram power to a rectifier machinery object in each area, controlled by signals from the tram. Tram crossing signals are fixed in how they consume power, changing between power use states instead of consuming during processing, and moved from the transport subsystem to fastprocess because they don't need to be running at 20fps. ## Why It's Good For The Game Tram draining an APC in a matter of seconds is bad. Tram having negative power draw at other times is also bad. ![image](https://github.com/tgstation/tgstation/assets/83487515/e49cbabe-1b21-4af2-b940-c3ab9fcdbcda) ## Changelog :cl: LT3 fix: Tram power consumption will no longer will randomly drain APCs fix: Tram power moved to area based rectifiers /:cl: --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- _maps/map_files/Birdshot/birdshot.dmm | 20 ++++- _maps/map_files/tramstation/tramstation.dmm | 32 ++++++-- .../modules/transport/tram/tram_controller.dm | 9 ++- code/modules/transport/tram/tram_controls.dm | 5 ++ code/modules/transport/tram/tram_power.dm | 73 ++++++++++++++++++ code/modules/transport/tram/tram_signals.dm | 16 ++-- code/modules/transport/transport_module.dm | 2 - icons/obj/tram/tram_controllers.dmi | Bin 800 -> 1338 bytes tgstation.dme | 1 + 9 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 code/modules/transport/tram/tram_power.dm diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 93dcf7fa11b..17239304e83 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -19967,6 +19967,9 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/transport/power_rectifier{ + configured_transport_id = "bird_2" + }, /turf/open/floor/iron, /area/station/maintenance/department/medical/central) "hic" = ( @@ -38174,6 +38177,13 @@ "nCH" = ( /turf/closed/wall/r_wall, /area/station/security) +"nCL" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/transport/power_rectifier{ + configured_transport_id = "bird_2" + }, +/turf/open/floor/iron, +/area/station/maintenance/port/aft) "nCR" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line, @@ -39094,6 +39104,12 @@ /obj/machinery/camera/autoname/directional/south, /turf/open/floor/iron, /area/station/hallway/secondary/dock) +"nTy" = ( +/obj/machinery/transport/power_rectifier{ + configured_transport_id = "bird_1" + }, +/turf/open/floor/plating, +/area/station/security/tram) "nTz" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted, /obj/machinery/chem_dispenser{ @@ -86835,7 +86851,7 @@ dwa dBr eWB lzM -aFR +nTy mnb cDt xpV @@ -91471,7 +91487,7 @@ trp trp trp trp -nFu +nCL xqd xul trp diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 6db0f6b6efc..8aab047a7de 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -4436,6 +4436,7 @@ /obj/effect/turf_decal/siding/thinplating/corner{ dir = 4 }, +/obj/machinery/airalarm/directional/north, /turf/open/floor/iron, /area/station/hallway/primary/tram/center) "aEn" = ( @@ -25158,6 +25159,16 @@ }, /turf/open/floor/glass/reinforced, /area/station/science/genetics) +"hXW" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/neutral/filled/warning{ + dir = 1 + }, +/obj/machinery/transport/power_rectifier, +/turf/open/floor/iron, +/area/station/hallway/primary/tram/right) "hYd" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/smart/simple/green/visible, @@ -48464,6 +48475,7 @@ "qfQ" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/east, +/obj/machinery/transport/power_rectifier, /turf/open/floor/catwalk_floor, /area/station/hallway/primary/tram/right) "qfS" = ( @@ -52307,6 +52319,16 @@ }, /turf/open/floor/iron, /area/station/commons/dorms) +"rxI" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/transport/power_rectifier, +/turf/open/floor/iron, +/area/station/hallway/primary/tram/left) "rxN" = ( /obj/machinery/photocopier, /obj/structure/extinguisher_cabinet/directional/north, @@ -58208,7 +58230,7 @@ /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 1 }, -/obj/machinery/airalarm/directional/north, +/obj/machinery/transport/power_rectifier, /turf/open/floor/iron, /area/station/hallway/primary/tram/center) "tBa" = ( @@ -154215,7 +154237,7 @@ aQO aQO aQO aQO -qhM +rxI nYq yiM cFs @@ -167835,7 +167857,7 @@ izU izU izU izU -hce +izU tAL sOD izU @@ -170405,7 +170427,7 @@ izU izU izU izU -izU +hce aEm gnK izU @@ -180943,7 +180965,7 @@ jnJ ged whL vUE -aEz +hXW yeB ipC seR diff --git a/code/modules/transport/tram/tram_controller.dm b/code/modules/transport/tram/tram_controller.dm index ab6838c49ea..5665755520e 100644 --- a/code/modules/transport/tram/tram_controller.dm +++ b/code/modules/transport/tram/tram_controller.dm @@ -128,6 +128,7 @@ /datum/transport_controller/linear/tram/Destroy() paired_cabinet = null set_status_code(SYSTEM_FAULT, TRUE) + SEND_SIGNAL(SStransport, COMSIG_TRANSPORT_ACTIVE, src, FALSE, controller_status, travel_direction, destination_platform) tram_registration.active = FALSE SSblackbox.record_feedback("amount", "tram_destroyed", 1) SSpersistence.save_tram_history(specific_transport_id) @@ -528,6 +529,7 @@ paired_cabinet = null log_transport("TC: [specific_transport_id] received QDEL from controller cabinet.") set_status_code(SYSTEM_FAULT, TRUE) + send_transport_active_signal() /** * Tram malfunction random event. Set comm error, increase tram lethality. @@ -686,8 +688,8 @@ integrity_failure = 0.25 layer = SIGN_LAYER req_access = list(ACCESS_TCOMMS) - idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 4.8 - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 4.8 + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.25 + power_channel = AREA_USAGE_ENVIRON var/datum/transport_controller/linear/tram/controller_datum /// If the cover is open var/cover_open = FALSE @@ -742,6 +744,9 @@ return CONTEXTUAL_SCREENTIP_SET +/obj/machinery/transport/tram_controller/update_current_power_usage() + return // We get power from area rectifiers + /obj/machinery/transport/tram_controller/examine(mob/user) . = ..() . += span_notice("The door appears to be [cover_locked ? "locked. Swipe an ID card to unlock" : "unlocked. Swipe an ID card to lock"].") diff --git a/code/modules/transport/tram/tram_controls.dm b/code/modules/transport/tram/tram_controls.dm index 2ecdad304bb..db8fe767155 100644 --- a/code/modules/transport/tram/tram_controls.dm +++ b/code/modules/transport/tram/tram_controls.dm @@ -9,6 +9,8 @@ density = FALSE max_integrity = 400 integrity_failure = 0.1 + power_channel = AREA_USAGE_ENVIRON + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.25 armor_type = /datum/armor/transport_machinery circuit = /obj/item/circuitboard/computer/tram_controls light_color = COLOR_BLUE_LIGHT @@ -64,6 +66,9 @@ if(tram) RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(update_display)) +/obj/machinery/computer/tram_controls/update_current_power_usage() + return // We get power from area rectifiers + /** * Finds the tram from the console * diff --git a/code/modules/transport/tram/tram_power.dm b/code/modules/transport/tram/tram_power.dm new file mode 100644 index 00000000000..ff0251e9090 --- /dev/null +++ b/code/modules/transport/tram/tram_power.dm @@ -0,0 +1,73 @@ +/obj/machinery/transport/power_rectifier + name = "tram power rectifier" + desc = "An electrical device that converts alternating current (AC) to direct current (DC) for powering the tram." + icon = 'icons/obj/tram/tram_controllers.dmi' + icon_state = "rectifier" + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 11.4 + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 114 + power_channel = AREA_USAGE_ENVIRON + anchored = TRUE + density = FALSE + armor_type = /datum/armor/transport_module + resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + max_integrity = 750 + pixel_y = 32 + /// The tram platform we're connected to and providing power + var/obj/effect/landmark/transport/nav_beacon/tram/platform/connected_platform + +/obj/machinery/transport/power_rectifier/Initialize(mapload) + . = ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/transport/power_rectifier/LateInitialize(mapload) + . = ..() + RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(power_tram)) + find_platform() + +/** + * The mapper should have placed the rectifier in the area containing the station, the object will search for a landmark within + * its control area and set its idle position. + */ +/obj/machinery/transport/power_rectifier/proc/find_platform() + var/area/my_area = get_area(src) + for(var/obj/effect/landmark/transport/nav_beacon/tram/platform/candidate_platform in SStransport.nav_beacons[configured_transport_id]) + if(get_area(candidate_platform) == my_area) + connected_platform = candidate_platform + RegisterSignal(connected_platform, COMSIG_QDELETING, PROC_REF(on_landmark_qdel)) + log_transport("[id_tag]: Power rectifier linked to landmark [connected_platform.name]") + return + +/obj/machinery/transport/power_rectifier/proc/power_tram(datum/source, datum/transport_controller/linear/tram/controller, controller_active, controller_status, travel_direction, obj/effect/landmark/transport/nav_beacon/tram/platform/destination_platform) + SIGNAL_HANDLER + + if(controller_active && destination_platform == connected_platform) + update_use_power(ACTIVE_POWER_USE) + else + update_use_power(IDLE_POWER_USE) + + update_appearance() + +/** + * Update the lights based on the rectifier status. + */ +/obj/machinery/transport/power_rectifier/update_overlays() + . = ..() + + if(machine_stat & NOPOWER) + . += mutable_appearance(icon, "rec-power-0") + . += emissive_appearance(icon, "rec-power-0", src, alpha = src.alpha) + return + + . += mutable_appearance(icon, "rec-power-1") + . += emissive_appearance(icon, "rec-power-1", src, alpha = src.alpha) + + var/is_active = use_power == ACTIVE_POWER_USE + . += mutable_appearance(icon, "rec-active-[is_active]") + . += emissive_appearance(icon, "rec-active-[is_active]", src, alpha = src.alpha) + +/** + * Clear reference to the connected landmark if it gets destroyed. + */ +/obj/machinery/transport/power_rectifier/proc/on_landmark_qdel() + log_transport("[id_tag]: Power rectifier received QDEL from landmark [connected_platform.name]") + connected_platform = null diff --git a/code/modules/transport/tram/tram_signals.dm b/code/modules/transport/tram/tram_signals.dm index 9e297e8e829..904bb162c45 100644 --- a/code/modules/transport/tram/tram_signals.dm +++ b/code/modules/transport/tram/tram_signals.dm @@ -10,13 +10,13 @@ integrity_failure = 0.25 light_range = 2 light_power = 0.7 - idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 2.4 - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.48 + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 3.6 + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.72 anchored = TRUE density = FALSE circuit = /obj/item/circuitboard/machine/crossing_signal // pointless if it only takes 2 seconds to cross but updates every 2 seconds - subsystem_type = /datum/controller/subsystem/processing/transport + subsystem_type = /datum/controller/subsystem/processing/fastprocess light_color = LIGHT_COLOR_BABY_BLUE /// green, amber, or red for tram, blue if it's emag, tram missing, etc. var/signal_state = XING_STATE_MALF @@ -74,8 +74,7 @@ layer = TRAM_SIGNAL_LAYER max_integrity = 250 integrity_failure = 0.25 - idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 2.4 - active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.74 + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 3.6 anchored = TRUE density = FALSE light_range = 1.5 @@ -308,13 +307,14 @@ * Returns whether we are still processing. */ /obj/machinery/transport/crossing_signal/proc/update_operating() - use_power(idle_power_usage) update_appearance() // Immediately process for snappy feedback var/should_process = process() != PROCESS_KILL if(should_process) + update_use_power(ACTIVE_POWER_USE) begin_processing() return + update_use_power(IDLE_POWER_USE) end_processing() /obj/machinery/transport/crossing_signal/process() @@ -328,8 +328,6 @@ set_signal_state(XING_STATE_MALF, force = !is_operational) return PROCESS_KILL - use_power(active_power_usage) - var/obj/structure/transport/linear/tram_part = tram.return_closest_platform_to(src) if(QDELETED(tram_part)) @@ -499,7 +497,7 @@ icon_state = "sensor-base" desc = "Uses an infrared beam to detect passing trams. Works when paired with a sensor on the other side of the track." layer = TRAM_RAIL_LAYER - use_power = 0 + use_power = NO_POWER_USE circuit = /obj/item/circuitboard/machine/guideway_sensor /// Sensors work in a married pair var/datum/weakref/paired_sensor diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index 7a7facea1b3..7a57529b8ff 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -931,8 +931,6 @@ addtimer(CALLBACK(src, PROC_REF(clear_turfs), turfs, iterations), 1) /obj/structure/transport/linear/tram/proc/estop_throw(throw_direction) - if(prob(50)) - do_sparks(2, FALSE, src) for(var/mob/living/passenger in transport_contents) to_chat(passenger, span_userdanger("The tram comes to a sudden, grinding stop!")) var/throw_target = get_edge_target_turf(src, throw_direction) diff --git a/icons/obj/tram/tram_controllers.dmi b/icons/obj/tram/tram_controllers.dmi index 93462e0b41e0b4d85057857bc5452dc52f2bed23..aea1f691af2411df01a408222aac46884e031164 100644 GIT binary patch delta 1247 zcmV<51R(pM2D%C*iBL{Q4GJ0x0000DNk~Le0002M0002M2m=5B0A&K4H2?qrtC1yb ze{XYjueG|NrmI3kN0617Q&w3hDl4)sX;8WA&D8)H86U5<0QUa?G&VSTe*rW9|2nHj zIiu89|7u0V|G>b&yTSl^;%1xx0004WQchCV=- z0C=30Q^AhHAP_y5uONDDH?6XX7cWM$fAOIIKw!EhQl=SL&HlY;4|X?gsNpgb-n{qb z5te*+_&T2X{&ZwlAaBs|Ef*gp%Wg)8CN}F8%Nj7>P3RjRWPn&M6uLlYEl{B>de94& zX+u8VRV=GXw$RsO6WD=!2X9eb-c#tL1DhP^@CKAbIiyym$uuJQBno`MZX6Y(f7W2- z@1x8IQP=Xvh9q$lKOl}ZOVT0|N9R}CKLy+Cvw4-{BYhsf7Trx^!7M_nV_=(00S^dL_t(| zobB2HbJ8#v2H*~uG#O(KodY)%f9+Nq9b@X;?f?HW((`gq0CPjd0K46~#27@kUe_$e!S33iz zLLQ*!85qkM(9c_(>Er)117m($czfJq05JoO0nYXD;~BpL5i-l~Lc`(kUDvl!^9)p+ zw|K9Qe^KC9q95pGpD&@x^A@E5WG=T^?*UYWx(!$gp!z2w0PQ;fZ69E!%=uW0#o}_& zV*v3cb_`G&|Kg+A^7lZ`f1d+X-bUL7xVpZ&US2Pk%e{RLjMS!8I-7x|*!DOBQL+86 zs~NbMt2aU241BT<^4WL+LjW-Y?Y_|P07PxYU9IB)(=DwcXMnbyf$26tah00000000000EBI2te!=sAF!Q#vDDARR`09*e-bOp1%eL%00000 z0MNUnf=k`I@-SnA%ftc1DL zy<^$;A1}S#RRl2Cz2ndDONV#syNVew*1gMLB1MPyoAu_t;w5CNd$)atA9#c7pX-VM z#=3XKYdp;x%+gpFFxI_es=ItwpS8@T?j5V(QU?G4fY1cI5ZO#37x3hw9s+oP0KOeYfZIeJe0Q@0 zxg?(?0WQWjld5%WdGOuM4pQEH{!bo!ce4Yr2(Q-S1N%9oe;JnXZ~hrm2jAW7fMw}g z23Uu-2-6G#_;v^ZQW+q)g~(>)l00Jp{v_DUt}ChMmU_JB$8YUA11n3N?D_FqOf17Q zb!hsifM78m00000000000N@q*ZU2);vDb?&tN4$WdfaOKKceQ+n+i#9s)1y#@9YFe?B6002ov JPDHLkV1k3~LB#+7 delta 705 zcmV;y0zUn^3ZMohiBL{Q4GJ0x0000DNk~Le0001h0001h2m=5B0QBII`2YX_Y>_2x ze>4C8&?ed!00001bW%=J06^y0W&i*H&3aT=bVOxyV{&P5bZKvH004NLl~TP5!Y~k? zlcxxEtzy-|#YI}AgT6yZt~QwFN^-XN_C_64P@>y+-1oT2 zO0J&q#X4W)Zylr}Gr%|diKq_c{f(|ehpJ;X&vsY<00D_fL_t(|obA|aPlGTNe+FP~ z6MDu#(K&G7y!`+F=%J-777A&K(V6$@hb1lHyg6$LTMz(%5{~9pBevE3=j()VqRrHf zcFeE-_5OG2BmSNsOj6AZ&===v&j3l52`M90CNTn#Jpj*?bW79GeH@oOD8e@J}*#}1^b1LpjSauVR$ft0uP{mvnP?0{o{2Qxrc z@d*&3>Q6x&$B*VQT<*Zk{E8v z1A!is0Go8+SPz@P+5vk2*#W;75)L4Sp-+_&pcqX9a0ke@1H~9X*D+s-Y_DWooapCY z$?PKk;s5{u0001RD_&QxxU63BwzygblRq&3Q~&?~0000009g0FvR=wz_i^(900000 n0001Bi=Wq@Hyr=~{--Z&6Ve>1IAI4n00000NkvXXu0mjf4lg#f diff --git a/tgstation.dme b/tgstation.dme index 270a74ffa35..cc526cfe433 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5816,6 +5816,7 @@ #include "code\modules\transport\tram\tram_doors.dm" #include "code\modules\transport\tram\tram_floors.dm" #include "code\modules\transport\tram\tram_machinery.dm" +#include "code\modules\transport\tram\tram_power.dm" #include "code\modules\transport\tram\tram_remote.dm" #include "code\modules\transport\tram\tram_signals.dm" #include "code\modules\transport\tram\tram_structures.dm"