## About The Pull Request
I heard you liked commas.
## Why It's Good For The Game
Trailing commas make everyone happy!
## Changelog
Nothing anyone will notice besides downstreams adding to these lists
## About The Pull Request
As the title says.
`init_order` is no more, subsystems ordering now depends on their
declared dependencies.
Subsystems can now declare which other subsystems need to init before
them using a list and the subsystem's typepath
I.e.
```dm
dependencies = list(
/datum/controller/subsystem/atoms,
/datum/controller/subsystem/mapping
)
```
The reverse can also be done, if a subsystem must initialize after your
own:
```dm
dependents = list(
/datum/controller/subsystem/atoms
)
```
Cyclical dependencies are not allowed and will throw an error on
initialization if one is found.
There's also a debug tool to visualize the dependency graph, although
it's a bit basic:

Subsystem load ordering can still be controlled using `init_stage`, some
subsystems use this in cases where they must initialize first or last
regardless of dependencies. An error will be thrown if a subsystem has
an `init_stage` before one of their dependencies.
## Why It's Good For The Game
Makes dealing with subsystem dependencies easier, and reduces the chance
of making a dependency error when needing to shift around subsystem
inits.
## Changelog
🆑
refactor: Refactored subsystem initialization
/🆑
* Converts arbitrary energy units to the joule. Fixes conservation of energy issues relating to charging cells. (#81579)
Removes all arbitrary energy and power units in the codebase. Everything
is replaced with the joule and watt, with 1 = 1 joule, or 1 watt if you
are going to multiply by time. This is a visible change, where all
arbitrary energy units you see in the game will get proper prefixed
units of energy.
With power cells being converted to the joule, charging one joule of a
power cell will require one joule of energy.
The grid will now store energy, instead of power. When an energy usage
is described as using the watt, a power to energy conversion based on
the relevant subsystem's timing (usually multiplying by seconds_per_tick
or applying power_to_energy()) is needed before adding or removing from
the grid. Power usages that are described as the watt is really anything
you would scale by time before applying the load. If it's described as a
joule, no time conversion is needed. Players will still read the grid as
power, having no visible change.
Machines that dynamically use power with the use_power() proc will
directly drain from the grid (and apc cell if there isn't enough)
instead of just tallying it up on the dynamic power usages for the area.
This should be more robust at conserving energy as the surplus is
updated on the go, preventing charging cells from nothing.
APCs no longer consume power for the dynamic power usage channels. APCs
will consume power for static power usages. Because static power usages
are added up without checking surplus, static power consumption will be
applied before any machine processes. This will give a more truthful
surplus for dynamic power consumers.
APCs will display how much power it is using for charging the cell. APC
cell charging applies power in its own channel, which gets added up to
the total. This will prevent invisible power usage you see when looking
at the power monitoring console.
After testing in MetaStation, I found roundstart power consumption to be
around 406kW after all APCs get fully charged. During the roundstart APC
charge rush, the power consumption can get as high as over 2MW (up to
25kW per roundstart APC charging) as long as there's that much
available.
Because of the absurd potential power consumption of charging APCs near
roundstart, I have changed how APCs decide to charge. APCs will now
charge only after all other machines have processed in the machines
processing subsystem. This will make sure APC charging won't disrupt
machines taking from the grid, and should stop APCs getting their power
drained due to others demanding too much power while charging. I have
removed the delays for APC charging too, so they start charging
immediately whenever there's excess power. It also stops them turning
red when a small amount of cell gets drained (airlocks opening and shit
during APC charge rush), as they immediately become fully charged
(unless too much energy got drained somehow) before changing icon.
Engineering SMES now start at 100% charge instead of 75%. I noticed
cells were draining earlier than usual after these changes, so I am
making them start maxed to try and combat that.
These changes will fix all conservation of energy issues relating to
charging powercells.
Closes#73438Closes#75789Closes#80634Closes#82031
Makes it much easier to interface with the power system in the codebase.
It's more intuitive. Removes a bunch of conservation of energy issues,
making energy and power much more meaningful. It will help the
simulation remain immersive as players won't encounter energy
duplication so easily. Arbitrary energy units getting replaced with the
joule will also tell people more meaningful information when reading it.
APC charging will feel more snappy.
🆑
fix: Fixes conservation of energy issues relating to charging
powercells.
qol: APCs will display how much power they are using to charge their
cell. This is accounted for in the power monitoring console.
qol: All arbitrary power cell energy units you see are replaced with
prefixed joules.
balance: As a consequence of the conservation of energy issues getting
fixed, the power consumption for charging cells is now very significant.
balance: APCs only use surplus power from the grid after every machine
processes when charging, preventing APCs from causing others to
discharge while charging.
balance: Engineering SMES start at max charge to combat the increased
energy loss due to conservation of energy fixes.
/🆑
---------
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
* Corrects Suit Storage Unit charge rate (#82192)
## About The Pull Request
Adjusts SSU charge rate according to the new conversion ratio.
Betcha didn't know SSUs recharge suit and MOD cells?
This number is actually supposed to be equal to the rate a recharger
station does it.
I don't know if we have some macro for it.
## Changelog
🆑 Melbert
fix: Fixed Suit Storage Unit cell charging rate
/🆑
* Corrects EVA thermal regulator cell cost (#82195)
## About The Pull Request
Another unit not converted to watts / joules
## Changelog
🆑 Melbert
fix: Fixed space suit thermal regulators cell usage.
/🆑
* Fixing cell power usage (Part 1) (#82197)
## About The Pull Request
Yeah i am not about to create 30 different PR's to address 1 issue at a
time. The changes are small enough to be grouped together in bulk.
This fixes the following issues specified in #82196
- Borg & exosuit RCD (Fixes#82193)
- Motorized wheelchair
- Canister shielding
- Electrolyser
- Potato cell
- Space heater
- Microwave
## Changelog
🆑
fix: Fixed cell energy usage for a bunch of stuff(Part 1). See PR 82197
for details
/🆑
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
* Fixing cell power usage (Part 2) (#82198)
## About The Pull Request
Continuation of #82197.
Fixes these issues in #82196
- Cyborg self repair
- Cyborg lollipop dispenser
- Mauna mug
- Plasma cutter (Initial charge not the number of laser shots so partial
fix)
## Changelog
🆑
fix: Fixed more energy usages for cells(Part 2). See PR 82198 for
details
/🆑
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
* Fixing cell power usage (Part 3) (#82204)
## About The Pull Request
Continuation of #82198
Fixes these issues in #82196
- Borg hypo spray
- Borg projectile dampen
- Borg chameleon
- Firelance
- MODlink scryer
- Emergency light usage
## Changelog
🆑
fix: Fixed more energy usages for cells(Part 3). See PR 82204 for
details
/🆑
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
* [NO GBP]Fixes static power usage not always drawing the remaining energy of an APC cell. (#82205)
## About The Pull Request
Makes APC static power draw consume the remaining energy of the cell if
there's not enough energy.
## Why It's Good For The Game
Prevents a niche issue where an area composed entirely of static power
users with no dynamic users from running forever with no power supply.
## Changelog
🆑
fix: Fixes static power usage from being able to not draw power.
/🆑
* Fixes recharge stations charge rates (#82191)
## About The Pull Request
- Fixes#82190
Have to now use the assigned constants and not magic number `10000`.
Also stuff will take the exact charge needed without any wastage.
## Changelog
🆑
fix: recharge stations draw the same amount of power as before but
directly from grid(without using apc cell power) and won't waste any
excess power
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
* Fixes space heater power usage (#82208)
## About The Pull Request
Related to https://github.com/tgstation/tgstation/issues/82196 fixes the
space heater power cell usage relating to power per tile heated.
Space heater calculates the amount of power required to heat a tile, but
only uses power at the end of the processing loop. Fixes so the power
consumption matches the calculated usage per tile.
Reverts changes to space heater power efficiency in
https://github.com/tgstation/tgstation/pull/82197 that causes the heater
to instantly drain the cell.
Fixes https://github.com/tgstation/tgstation/issues/82228
## Changelog
🆑 LT3
fix: Fixes Schrödinger's space heater, where a space heater both
consumes a power cell instantly while also not consuming power when
heating adjacent tiles
/🆑
* General maintenance for reagent grinder (#82161)
## About The Pull Request
**1. Qol**
- Adds examines & screentips for screwdriver, crowbar & wrench acts.
- Adds examines & screentips for inserting, replacing & removing beaker,
Also for inserting items from bags or directly
- Adds an off icon overlay for when the reagent grinder is either
screwed open or loses power,
**2. Code Improvements**
- Replaced `attackby()` with `item_interaction()` so we can end the
attack chain early for non combat operations like inserting beakers/
ingredients for grinding etc.
- Removed custom shake animations & replaced it with the global
`Shake()` proc cause it did the same thing
- Removed constructed version of reagent grinder. We instead just check
`mapload` to see if we need the beaker to be created or not for round
start reagent grinders
- Grinding & Juicing use the same `operate_for()` rather than having
seperate procs for each operation
- Removed trait `TRAIT_MAY_CONTAIN_BLENDED_DUST`. Why do we have this?
Its just used to change the grinder description to warn it may contain
dust. It's a waste.
**3. Fixes**
- You cannot insert hologram items into the grinder. Rather than
destroying that item & making it vanish you simply won't be allowed to
put it inside the grinder so you can save that item
- You can hit the grinder with items like screwdriver, wrench, crowbar,
beaker & even with stuff you would normally put in the grinder when in
combat mode
- Adds `can_interact()` checks for using the UI & other stuff
- Fixes#46356. All items of type `obj/item/grown` can be put from any
bag into the grinder
- The item "and its contents" are now grinded/juiced recursively to get
all the reagents it has to offer just like a real grinder would
- An AI/Human with AI access examining the reagent grinder now actually
works.
**4. Refactors**
- The grinder now measures its available capacity based on the "total
weight" of all items present & not its number. This is more realistic
because the grinder has limited space inside & so inserting huge items
should have greater impact rather than deciding on an arbitrary number
like 10(The grinder having the capacity for 10 items of any size inside
its small compartment makes no sense). Examines are displayed to show
how much capacity of the grinder has been filled. Upgrading the grinder
with better matter bins will allow for higher storage capacities.
- Total power consumed is measured based on the duration & weight of all
items grinded cause you know its realistic.
🆑
qol: adds examines & screentips for tool acts & other operations for
reagent grinder
qol: adds an off icon for when the grinder panel is open/not powered
code: auto docs vars & procs. Shared common proc for grinding or juicing
code: removed trait for blended dust, changed some item interactions to
end the attack chain early & save time
fix: no inserting hologram items into the reagent grinder
fix: you can hit the reagent grinder tools like screwdriver, wrench,
crowbar & even beakers/ingredients etc when in combat mode
fix; adds sanity checks for when & how mobs interact with the reagent
grinder
fix: examining a reagent grinder by an AI/Human with AI access now
actually works.
fix: you can insert Nova flowers & other food items from any bag type
fix: reagent grinder now grinds all the contents of an item recursively
to produce maximum reagents like a real grinder would
refactor: reagent grinder now measures available capacity to store items
as total weight of stored items & not number. Capacity can be increased
with upgraded matter bin
refactor: reagent grinder power usage is now a function of duration &
total weight of items blended, meaining blending more number of
items/larger items will consume more power
refactor: reagent grinder code has been optimized overall. Report bugs
on github
/🆑
---------
Co-authored-by: Timberpoes <silent_insomnia_pp@hotmail.co.uk>
* Suit Storage Units / Inducers can charge MODsuits without necessitating them be screwdrivered opened (#82194)
## About The Pull Request
So MODsuits do this thing here with `get_cell` in that they don't return
anything when they're closed

And I... can't tell why they do this.
I looked through every use of `get_cell` and the only things affected by
this are
A. Suit Storage Units, which I believe have always been intended to
charge MODsuits?
and
B. Inducers
So I removed the `open` check. Allowing both Inducers and Suit Storage
Units to charge mods without needing you screwdriver their panel open
first.
I also took the opportunity to allow SSUs to charge multiple items at
once (divvying charge accross all items)
## Why It's Good For The Game
I asked Fikou and they said it was "probably not" intended that you need
to screwdriver them open so yeah.
I think I remember charging my MODs during the original test merges
years back but I can't remember if I opened the suit first when I did or
not.
Either way, it's not super intuitive. Though it's already not very
intuitive that SSUs charge things.
## Changelog
🆑 Melbert
qol: Suit Storage Units charge MODsuits while their cell panel is closed
or open, rather than only when screwed open
qol: Inducers can charge MODsuits while their cell panel is closed or
open, rather than only when screwed open
qol: Suit Storage Units will charge all items within simultaneously (if
possible)
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
* Fixes modular computer boot-up (#82254)
## About The Pull Request
Fixes a bug where modular computers (specifically PDAs) will fail to
start up if there is zero required application power draw.
PDA will now consume base active power usage during startup.
Related https://github.com/tgstation/tgstation/issues/82196
Fixes https://github.com/tgstation/tgstation/issues/82245
Fixes https://github.com/tgstation/tgstation/issues/82229
## Changelog
🆑 LT3
fix: Fixed modular computers failing to boot up using cell power (eg:
contractor tablet)
/🆑
* Fixing cell power usage (Part 4) (#82227)
## About The Pull Request
Continuation of #82204
Fixes these issues in #82196
- Cyborg Electroadaptive Pseudocircuit
- Defib EMP
- Cell EMP
- `/datum/action/cooldown/mob_cooldown/charge_apc` stuff
- Mecha movement, melee, light ,weapon & tool energy drains
- Ninja drain
## Changelog
🆑
fix: Fixed more energy usages for cells(Part 4). See PR 82227 for
details
/🆑
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
* Fixing cell power usage (Part 5) (#82296)
## About The Pull Request
Continuation of #82227
Fixes these issues in
https://github.com/tgstation/tgstation/issues/82196 and others that
weren't noticed.
- Batton emp protection
- Cyborg stun arm
- Cyborg energy sword
- Cyborg hug attack
- Mechanical god religious sect charge check
- Mecha fixes
- Phasing energy drain
- Short circuit energy drain
- Durand shield damage energy drain
- Plasma engine recharge rate
- Mechbay recharge power rate
- Recharge station charge rate
Stuff that was already working & didn't require fixing.
- Plasma cutter energy shots
- Botany cell charging
## Changelog
🆑
fix: Fixed cell energy usage for a bunch of stuff(Part 5). See PR 82296
for details
/🆑
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
* Ties power limit of anchored circuits to 20 * standard cell charge to make it consistent with power changes. (#82287)
## About The Pull Request
It just makes the power requirement 20 * standard cell charge instead of
20000
## Why It's Good For The Game
This is too restrictive to make anything with.
https://github.com/tgstation/tgstation/assets/62126254/e39dcf27-8793-42b0-84a0-7f747e95efcc
## Changelog
🆑
fix: anchored circuits no longer blow up after 2 components are used.
/🆑
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
* 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
🆑 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
/🆑
* Improved lathe error message (#82260)
## About The Pull Request
Improves the auto/protolathe low charge error message. Instead of simply
saying low power, it will tell you how long until it has enough charge
to print.

## Why It's Good For The Game
Less mashing the lathe over and over with no idea how much APC charge it
needs to start printing again
## Changelog
🆑 LT3
code: APCs can now calculate time-to-charge
qol: Overloaded lathes will now tell you the wait time until they're
ready to print again
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
* Fixes issues with multitools on power objects (#82389)
## About The Pull Request
So at some point the power object's `multitool_act(...)` proc was set to
_always_ block, for what I could find to be no discernable reason.
### The Main Thing
https://github.com/tgstation/tgstation/blob/d38f9385b863e49f83455a227764d302629e2867/code/modules/power/power.dm#L62-L74
Now, of course, it shouldn't, because this cuts the entire chain short
and thus blocks any other multitool interactions. Like opening the wires
panel with a multitool, in this case. Even if `can_change_cable_layer`
were to be false and thus the object would never actually care about
having this interaction, it'd _still_ block it.
So we don't do that. But what _do_ we do?
I decided to just split off the actual cable changing part into its own
proc, `cable_layer_act(...)`.
```dm
/obj/machinery/power/proc/cable_layer_act(mob/living/user, obj/item/tool)
var/choice = tgui_input_list(user, "Select Power Line For Operation", "Select Cable Layer", GLOB.cable_name_to_layer)
if(isnull(choice))
return ITEM_INTERACT_BLOCKING
cable_layer = GLOB.cable_name_to_layer[choice]
balloon_alert(user, "now operating on the [choice]")
return ITEM_INTERACT_SUCCESS
```
Which is then called on `multitool_act(...)`, if
`can_change_cable_layer` is true.
```dm
/obj/machinery/power/multitool_act(mob/living/user, obj/item/tool)
if(can_change_cable_layer)
return cable_layer_act(user, tool)
```
Which continues with the chain if we can't change layers by default, and
otherwise lets `cable_layer_act(...)` work out whether we should block
or continue.
Notably, we've removed the `cable_layer_change_checks(...)` proc from
the equation, and just let inheritors override it to add their own
preconditions and what flags they should return.
On its own this fixes the APC wire panel interactions, but also lets us
just return `NONE` when we need to.
```dm
/obj/machinery/power/emitter/cable_layer_act(mob/living/user, obj/item/tool)
if(panel_open)
return NONE
if(welded)
balloon_alert(user, "unweld first!")
return ITEM_INTERACT_BLOCKING
return ..()
```
### The OTHER Things
While doing this I noticed there's actually very little sanity checks
after we close our input list.
```dm
var/choice = tgui_input_list(user, "Select Power Line For Operation", "Select Cable Layer", GLOB.cable_name_to_layer)
if(isnull(choice))
return ITEM_INTERACT_BLOCKING
```
We only care about whether we made a choice!
Testing this, lo and behold, this can cause runtimes if the power object
gets qdeleted before you close the menu.
As a funny side, it _also_ doesn't care about whether you're on the
other side of the station, while your multitool is on a different
z-level, or just doesn't exist anymore.
So we just add a few basic sanity checks while we're at it.
```dm
var/choice = tgui_input_list(user, "Select Power Line For Operation", "Select Cable Layer", GLOB.cable_name_to_layer)
if(isnull(choice) || QDELETED(src) || QDELETED(user) || QDELETED(tool) || !user.Adjacent(src) || !user.is_holding(tool))
return ITEM_INTERACT_BLOCKING
```
That's all. Having done some basic testing, I believe the behaviour is
otherwise unaffected.
## Why It's Good For The Game
It's annoying to need to swap to an empty hand or wirecutters to
interact with APC, emitter, or tesla coil wires.
This fixes that. (Fixes #81745.)
...and then a few other tidbits I realized existed.
## Changelog
🆑
fix: Fix using a multitool on a power object with wires not actually
opening the wires menu when it should.
fix: Fix a runtime from a power object being deleted before selecting
what cable layer to put it at.
fix: Fix power object cable changing not caring about whether you were
still adjacent, still holding your multitool, or whether it even still
existed after the selection menu was closed.
/🆑
* Updates cyborg cells created from borgifier to the SI standard (#82437)
## About The Pull Request
Unchanged value in transformer.dm resulted in borg charge draining to
zero immediately after forced conversion in the borgifer. Changing the
value of robot cell charge to 5 MJs to fix this.
## Why It's Good For The Game
Fixes#82426
## Changelog
🆑
fix: changed value of cell charge from 5000 to 5 megajoules
/🆑
* cell chargers now bypass APCs (#82309)
## About The Pull Request
This makes cell chargers and suit storage units draw from the grid
before the local apc
## Why It's Good For The Game
Upgraded Cell chargers have a charging power of 1MW leading to them
instantly draining the apc of any room they are in,
this Pr makes them draw from the grid preventing immediate blackout.
This is a stopgap until someone smarter than me changes power values so
a pocket-sized battery won't require the same power to charge then over
600 average suburban homes.
## Changelog
🆑
balance: suit and cell chargers should draw from grid preventing instant
apc blackouts in most cases.
/🆑
* Let ethereals starve again (#82308)
## About The Pull Request
Ethereals use energy as 'food', so of course #81579 had to touch them.
To bring them in line with the new standard, the Ethereal charge levels
were updated to be in megajoules.
https://github.com/tgstation/tgstation/blob/466b3df0483162c3900e411c25dfe15c2320786e/code/__DEFINES/mobs.dm#L292-L299https://github.com/tgstation/tgstation/blob/7fa8daad63f49a11e22ab64a984d29b35619852c/code/__DEFINES/mobs.dm#L285-L292
However! This forgot to update the rate at which Ethereals passively
discharge.
https://github.com/tgstation/tgstation/blob/7fa8daad63f49a11e22ab64a984d29b35619852c/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm#L11-L14https://github.com/tgstation/tgstation/blob/7fa8daad63f49a11e22ab64a984d29b35619852c/code/__DEFINES/mobs.dm#L437
Meaning it's effectively a thousand times less with the new charge
levels.
So we simply update this define to be in kilowatts.
```dm
#define ETHEREAL_CHARGE_FACTOR (0.8 KILO WATTS) //factor at which ethereal's charge decreases per second
```
## Why It's Good For The Game
Fixes issue with ethereal hunger caused by #81579.
## Changelog
🆑
fix: Ethereal starvation has been updated to the new joules/watts
standard. Congratulations Ethereals! You can starve again!
/🆑
* [NO GBP]Fixes ethereal charging and recharge station charge speed. (#82483)
## About The Pull Request
Fixes many instances of things not charging ethereals properly. Scales
all things that are meant for charging/taking from the ethereal stomach
by STANDARD_CELL_CHARGE, so we never run into this issue again. Ethereal
stomachs now store a cell inside them, and uses that for the charge
instead of tracking a variable. Fixes recharging stations not being able
to charge ethereal stomachs. The ethereal signal proc attempted to feed
a callback datum to adjust_charge(), which caused a runtime. Changes
that by invoking the charge_cell callback instead.
Also fixes recharge station charging speed. They weren't converted
correctly. Also formats their charging speed in their description, and
displays power rather than referencing cycles.
## Why It's Good For The Game
So ethereals charge properly.
Closes#82470
## Changelog
🆑
fix: Fixes many instances of energy sources for ethereals supplying a
thousand times less energy than intended.
fix: Fixes recharging stations not being able to charge ethereals.
fix: Fixes recharge stations charging too fast.
qol: Recharge stations display their recharging speed in formatted
power, rather than unformatted energy per cycle.
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
* Update lead acid batteries charge values (#82510)
## About The Pull Request
So during the whole power consistency update thing, it seems lead acid
batteries were entirely forgotten about.
Which, well, is easy, because they never actually used
`STANDARD_CELL_CHARGE`.
https://github.com/tgstation/tgstation/blob/c34d56a45b0461f5e0fad3cc75e81580c3357119/code/game/objects/items/maintenance_loot.dm#L32-L33
Looking into it, the previous value for `STANDARD_CELL_CHARGE` seemed to
have been 1000, so we convert it directly:
```dm
maxcharge = STANDARD_CELL_CHARGE * 20
chargerate = STANDARD_CELL_CHARGE * 1.4
```
But, comparing this to the normal power cells, it seems their charge
rates got _halved_ during the update.
So, we do that too.
```dm
maxcharge = STANDARD_CELL_CHARGE * 20
chargerate = STANDARD_CELL_CHARGE * 0.7
```
And that fixes it.
## Why It's Good For The Game
Fixes lead acid batteries still using the old power amounts, and not
being relative to `STANDARD_CELL_CHARGE`.
## Changelog
🆑
fix: Lead acid batteries have had their power values fixed.
/🆑
* This should do for modular code, for now.
* Fixing cell power usage (Part 5) (#82296)
Continuation of #82227
Fixes these issues in
https://github.com/tgstation/tgstation/issues/82196 and others that
weren't noticed.
- Batton emp protection
- Cyborg stun arm
- Cyborg energy sword
- Cyborg hug attack
- Mechanical god religious sect charge check
- Mecha fixes
- Phasing energy drain
- Short circuit energy drain
- Durand shield damage energy drain
- Plasma engine recharge rate
- Mechbay recharge power rate
- Recharge station charge rate
Stuff that was already working & didn't require fixing.
- Plasma cutter energy shots
- Botany cell charging
🆑
fix: Fixed cell energy usage for a bunch of stuff(Part 5). See PR 82296
for details
/🆑
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
* [NO GBP]Fixes some mapped SMES starting with low energy. (#82203)
## About The Pull Request
Scales them all by up to 20 to account for removing the dumb SMESRATE
define. This isn't a 100% conversion for every SMES because it would go
beyond their capacity (old SMES use to duplicate cell energy, so they
had a higher capacity than their cell parts imply). Also removes
instances of varediting their capacity to fucking 1e+600 and replaces
them with magical SMES.
## Why It's Good For The Game
So lavaland and crap don't instantly run out of power. Also I don't
think we should be varediting anything to 1e+600.
## Changelog
🆑
fix: Fixes lavaland SMES and other crap from not starting with enough
energy.
fix: The pirate SMES are now magical instead of secretly infinite.
/🆑
* Mechbay & modsuit recharger tweaks (#82337)
## About The Pull Request
- Both mechbay & modsuit rechargers now waste a small amount of energy
as heat like it did before
- Fixes#82332. Mechbay recharger displays the energy of the mech in
joules & charges the cell with the exact energy required directly from
the grid thus not causing the room to blackout
## Changelog
🆑
fix: Mechbay & modsuit rechargers waste a small amount of energy as heat
fix: Mechbay recharger console displays mech charge as joules & charges
directly from the grid thus sparing the rooms apc cell from huge loads
/🆑
* Refactor APCs interaction chain from attackby to item_interaction (#82390)
## About The Pull Request
For how many lines this is, there's not a lot to really say.
In general, we simply move all item interactions from `attackby(...)` to
`item_interaction(...)`, split each item interaction off into a separate
proc, and make them all return the proper item interaction flags.
We _do_ kill some probably dead code, and remove a call to
`attackby(...)` elsewhere. Then, for clarity, we move the cell check
below the ID check so it can be next to the other item type checks, as
the priority between cell and ID is unlikely to matter anyway.
Other than what's described above and detailed below, each section's
functionality should be the same.
Now, for the parts that _do_ need to be explained more.
### Killing Probably Dead Code
Alright, so, the first part that does not have the cleanest transition.
https://github.com/tgstation/tgstation/blob/d38f9385b863e49f83455a227764d302629e2867/code/modules/power/apc/apc_attack.dm#L22-L23
Whatever the fuck this is.
Asking around, this seems to just be dead code.
For sanity's sake removing it and testing, silicon interactions with it
seem to work just fine.
So we kill it. We just kill it. We Just Kill It.
Closest we could find requires the distance check there to be false, so
it wouldn't apply. But it _does_ bring us to the second bit of weird
code.
### Calling APC Attackby Elsewhere?
So wallframes let you screwdriver them to put them up, which from a
comment seems to be because of cyborgs.
APC wallframes of course override this with their own implementation,
that allows you to also replace a damaged cover or frame like that!
https://github.com/tgstation/tgstation/blob/d38f9385b863e49f83455a227764d302629e2867/code/game/objects/items/apc_frame.dm#L29-L39
...By just calling the wholeass `attackby(...)` proc on the APC and
calling it a day.
But hey, this is where our previous splitting up comes in handy, because
we just have a `wallframe_act(...)` proc!
So we just call that instead.
```dm
var/obj/machinery/power/apc/mounted_apc = locate(/obj/machinery/power/apc) in get_turf(user)
mounted_apc.wallframe_act(user, src)
return ITEM_INTERACT_SUCCESS
```
...And not use single letter variables, while we're at it.
That should be all.
Remember to get snacks and drinks.
## Why It's Good For The Game
Split off 178 line `attackby(...)` item interaction chain into separate
procs called in `item_interaction(...)`.
Screwdrivering APC wallframes no longer calls the wholeass
`attackby(...)` on the APC, but just call the new sub-proc for the
specific interaction it cares about.
## Changelog
🆑
refactor: APCs have had their item interaction chain refactored. This
should functionally be the same, but please report any issues.
/🆑
* [NO GBP]Cells will only consider 0.1% of their charge when shocking a user. (#82456)
## About The Pull Request
Makes cells only consider 0.1% of their charge when calculating the
damage for shocking someone. This makes the minimum damage 20, and goes
up to 22 (previous behaviour, even though that's a shockingly small
difference) with a 50 MJ cell, which is the highest capacity crew can
get. This makes it inversely scale with the standard cell charge define,
so if that gets changed, cells will use a different composition of their
charge to consider.
## Why It's Good For The Game
Airlocks instantly critting people when shocked regardless of what's in
the grid wasn't previous behaviour.
* Oops. There we go.
* Oh, these two too.
---------
Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
Co-authored-by: Timberpoes <silent_insomnia_pp@hotmail.co.uk>
Co-authored-by: moocowswag <62126254+moocowswag@users.noreply.github.com>
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
Co-authored-by: Archie700 <archie712@hotmail.com>
Co-authored-by: Blacklist897 <149209377+Blacklist897@users.noreply.github.com>
* Machine list is now stored in SSmachines | Remove excessive use of global lists for specific machine types
* Resolve merge conflicts
* Modular adjustments
* destroy this double return on destroy
---------
Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
Co-authored-by: Giz <vinylspiders@gmail.com>
* Unit tests powernets to make sure the whole station is connected. (#70090)
* Unit tests powernets to make sure the whole station is connected.
* fixes cable tests for blueshift and raptor
* single cable misplacement
* hard map reset
* hec
* tramstation armory stray cable
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Paxilmaniac <paxilmaniac@gmail.com>
Co-authored-by: Tastyfish <crazychris32@gmail.com>
* large refactor of machine/power code to cut down on processing time and wasted lists (#60317)
original pr here: #59789 (Closed because he didn't think it was good enough)
came back to this because i realized that
all machines were area sensitive, meaning they had a list with at least a reference to themselves (assuming they arent in the contents of another movable which most arent) for the purposes of handling power differences when their area changes
pipes are machines
there are ~14k machines and ~6k pipes
i made this problem worse with a recent pr by making it a nested list
so i needed to track what machines needed power, and this pr had work already done that could be used for that purpose. now machines that have use_power == NO_POWER_USE do not have this extra memory overhead for no reason
currently every machine that uses power draws that amount from its area from a dynamic channel via auto_use_power() which is called every SSmachines fire(), then in apc/process() the area's dynamic power draw is reset and the power is used. with static power its not calculated then reset every loop, its just taken from the grid. so now machines handle updating their static power usage from their current area (this doesnt touch power machines that require a wire connection). in order to allow this, use_power, idle_power_usage, and active_power_usage have setters to track state correctly and update the static power usage on the machines current area and handle area sensitivity.
also goes through a lot of heavy abusers of SSmachine processing time and tries to make it faster. makes airalarm/process() into a signal handler for COMSIG_TURF_EXPOSE since air alarms only need to process for changes.
Why It's Good For The Game
SSmachines isnt the heaviest hitter in terms of total cpu and certainly not in terms of overtime, but its not a lightweight. it frequently takes > 50ms to complete a run and seems to be in the top 5 or so of subsystem costs looking at some round profilers
also gets rid of a few thousand lists since every pipe no longer has two useless lists each (and any other machines that dont use power)
Love ya kyler
Co-authored-by: Rohesie <rohesie@ gmail.com>
* large refactor of machine/power code to cut down on processing time and wasted lists
Co-authored-by: Kylerace <kylerlumpkin1@gmail.com>
Co-authored-by: Rohesie <rohesie@ gmail.com>
* The Great Radio Rework: NTNET Part 1 of many.
* Update airlock.dm
Co-authored-by: WarlockD <warlockd@gmail.com>
Co-authored-by: Gandalf2k15 <jzo123@hotmail.com>
* Process procs now properly utilize deltatime when implementing rates, timers and probabilities (#52981)
* Process procs now properly use deltatime when implementing rates, timers and probabilities
* Review fixes
* Geiger counters cleanup
Made hardsuit geiger code more similar to geiger counter code
Geiger counters are more responsive now
* Moved SS*_DT defines to subsystems.dm
* Rebase fix
* Redefined the SS*_DT defines to use the subsystem wait vars
* Implemented suggested changes by @AnturK
* Commented /datum/proc/process about the deltatime stuff
* Send delta_time as a process parameter instead of the defines
Also DTfied acid_processing
* Dtfied new acid component
* Process procs now properly utilize deltatime when implementing rates, timers and probabilities
Co-authored-by: Donkie <daniel.cf.hultgren@gmail.com>
Replaces like 70-80% of 0 and such, as a side effect cleaned up a bunch of returns
Edit: Most left out ones are in mecha which should be done in mecha refactor already
Oh my look how clean it is
Co-authored-by: TiviPlus <TiviPlus>
Co-authored-by: Couls <coul422@gmail.com>
Co-authored-by: TiviPlus <57223640+TiviPlus@users.noreply.github.com>
Co-authored-by: Couls <coul422@gmail.com>
If an item is qdeleted, it is not queued for processing and removed
from the processing list (if it's not already gone)
This will prevent machines getting processed when qdeleted (due to being
cached in the subsystem current run list)
* Add the system for managed global variables
* Travis ban old globals
* So you CAN inline proccall, that's neat
* Fix that
* master.dm
* Remove the hack procs
* Move InitGlobals to the proper spot
* configuration.dm
* Fix the missing pre-slash
* clockcult.dm
* This is probably for the best
* Doy
* Fix shit
* Rest of the DEFINES tree
* Fix
* Use global. for access
* Update find_references_in_globals
Always hated that proc
Whoever made it must've bee a r e a l idiot...
* __HELPERS tree
* Move global initialization to master.
Fix the declaration
* database.dm
* Dat newline
* I said DECLARATIVE order!
* Here's something you can chew on @Iamgoofball
* game_modes.dm
* Fix this
* genetics.dm
* flavor_misc.dm
* More stuff
* Do it mso's way. Keep the controllers as global
* Make master actually see it
* Fix
* Finish _globalvars/lists
* Finish the rest of the _globalvars tree
* This is weird
* Migrate the controllers
* SLOTH -> GLOB
* Lighting globals
* round_start_time -> ticker
* PAI card list -> pai SS
* record_id_num -> static
* Diseases list -> SSdisease
* More disease globals to the SS
* More disease stuff
* Emote list
* Better and better
* Bluh
* So much stuff
* Ahh
* Wires
* dview
* station_areas
* Teleportlocs
* blood_splatter_icons
* Stuff and such
* More stuff
* RAD IO
* More stuff and such
* Blob shit
* Changeling stuff
* Add "Balance" to changelogs
* Balance for changelog compiler + Auto Tagging
* Update the PR template
* hivemind_bank
* Bip
* sacrificed
* Good shit
* Better define
* More cult shit
* Devil shit
* Gang shit
* > borers
Fix shit
* Rename the define
* Nuke
* Objectives
* Sandbox
* Multiverse sword
* Announce systems
* Stuff and such
* TC con
* Airlock
* doppllllerrrrrr
* holopads
* Shut up byond you inconsistent fuck
* Sneaky fuck
* Burp
* Bip
* Fixnshit
* Port without regard
* askdlfjs;
* asdfjasoidojfi
* Protected globals and more
* SO MANY
* ajsimkvahsaoisd
* akfdsiaopwimfeoiwafaw
* gsdfigjosidjfgiosdg
* AHHHHHHHHHHHHHHHHHHHHHHH!!!!!
* facerolll
* ASDFASDFASDF
* Removes the unused parts of dmm_suite
* WIP
* Fix quote
* asdfjauwfnkjs
* afwlunhskjfda
* asfjlaiwuefhaf
* SO CLOSE
* wwwweeeeeewwwww
* agdgmoewranwg
* HOLY MOTHER OF FUCK AND THATS JUST HALF THE JOB?!?
* Fix syntax errors
* 100 errors
* Another 100
* So many...
* Ugh
* More shit
* kilme
* Stuuuuuufffff
* ajrgmrlshio;djfa;sdkl
* jkbhkhjbmjvjmh
* soi soi soi
* butt
* TODAY WE LEARNED THAT GLOBAL AND STATIC ARE THE EXACT SAME FUCKING THING
* lllllllllllllllllllllllllllllllllllllllllll
* afsdijfiawhnflnjhnwsdfs
* yugykihlugk,kj
* time to go
* STUFFF!!!
* AAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!!!!!!!!!!!!!!!!!!!!!
* ngoaijdjlfkamsdlkf
* Break time
* aufjsdklfalsjfi
* CONTROL KAY AND PRAY
* IT COMPILEELEELELAKLJFKLDAFJLKFDJLADKJHFLJKAJGAHIEJALDFJ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Goteem
* Fix testing mode
* This does not belong in this PR
* Convert it to a controller
* Eh, fuck this option
* Revert controllerization Ill do it some other time
* Fix
* Working controllerization
* FOR THE LOVE OF CHRIST PROTECT THE LOGS
* Protect admins and deadmins
* Use the inbuilt proc
Basically, they key difference between StonedMC and CarnMC is that when multiple ticks want to run at the same byond tick, we divvy up the tick between the subsystems, rather then allow one subsystem to hog it all.
The key difference between StonedMC and GoonPS is that we allow the subsystems to tell us how to divvy up the tick using flags and priority.
The new SS_ flags allows us to select behaviors that used to be piggybacked as side effects of dynamic wait or default but sometimes unneeded behavior.
Dynamic wait is 100% gone, lower priority and SS_BACKGROUND are better more refined ways of doing this when combined with MC_TICK_CHECK
I have by design never looked at the inners of goonPS, so this is all original code but I know it uses two loops because of comments by goon devs on reddit threads, that design didn't make sense before, but when I can tell a SS how much of a byond tick it is allowed to have, knowing how many need to run this tick is helpful I also know a bit more about how it works from piecing together comments in #vgstation.
Detailed list of changes:
Subsystems now have flags, allowing fine grain control over things like rather or not it processes, inits, rather it's wait is how long between runs (post run timing) or how long between starts, and rather or not late fires should cause the next fire to be earlier.
Mc now has two loops One loop handles queuing shit, one loop handles running shit.
MC now splits up tick allotment rather than first come first serve Subsystems can even request a bigger share using higher priorities. (It will even resume subsystems it paused if other subsystems hadn't used as much as it predicted they might need)
Default fps is now 20 This is related enough to the MC and it's a change that's really long since over due
All code oddities are most likely to be necessities to lower overhead on the mc since it runs every tick
This setup allows subsystems to pause themselves until next mc fire if they are about to go over a tick, and resume on the next mc tick
It also makes it so we prioritize running subsystems we skipped because there wasn't enough time in the current tick to run them based on their avg tick usage. (as well as subsystems paused mid way thru)
Adds a macro for adding this to non-mc procs. just drop it in the loop. There is a define version as well for if checks if you want to know if you just slept to avoid lag.
This is all inside #if DM_VERSION defines, so once i test that 509 still works to compile/test this should be good to merge
MC:
No longer tracks a subsystem's cpu usage. This was basically worthless and took up space on the stat panel
Can calculate wait down to a tenth of a decisecond to make it fps/world.ticklag agnostic
Now allows subsystems to have a dynamic wait, that is based on a ratio of how long that subsystem has been taking to process(cost). (This system allows for upper and lower bounds, and an changeable cost delta for each subsystem)
MC can now be told to init a zlevel
All Subsystems:
Stats panel now allows child subsystems to pass it a message to add to its stats entry. All subsystems have been moved over to this system - This should cut down on subsystems having to copy and paste the stats proc in order to add to it
All subsystems now properlly handle being given a zlevel in their init proc
Subsystem changes:
Air:
Added air to the dynamic wait subsystem. upper bound: 50, lower bound: 5, cost delta: 3 times process cost
Air now fires 4 times faster when it can do so without lagging things up
Pipenet has been merged into air
Atmos machinery now processes with process_atmos(), ticked by air, not machinery.
Hotspots (the fire object) are now object pooled
Pipenet:
Deleted, added to air
Machinery:
Moved all atmos calcualtions in all objects's process() to process_atmos().
Lighting:
Added Lighting to the dynamic wait subsystem. upper bound: 20, lower bound: 5, cost delta: 3 times process cost
Ticker:
Fixed ticker not updating the lobby panel when game start delayed
Fixed the game start timer updating rapidly from queued fires when game start delay is removed
Garbage/qdel:
qdel will now limit its process time to 2ds a fire.
qdel can now be given hints as a return to Destroy() as to what should be done with the object.
the options are:
queue: (default) this is the normal behavior.
letmelive: old default to non-null/zero. does nothing with the object
iwillgc: functionally the same as above, mainly to let people working with objects know that the object will not be queued for GC checking
harddel: this will queue the object to be deleted without storing a soft reference, mainly to save locate() processing time.
harddel_now: this will del() the object. To allow for a clean removal of every del() not in qdel
All objects have been updated to the new system, harddel and iwillgc was not added to any new objects.
Fixed some objects not GCing because they didn't properlly clear references in Destory()
Fixed some objects getting qdel'ed preventing other objects from getting GCed because they did not null their reference to that object.
Misc:
+Fixes unreported issue with initializing lighting on a specific zlevel
+Fixes two similar issues with moveElement and moveRange. Where fromIndex or toIndex could be adjusted incorrectly in certain conditions. Potentially causing bad-sorts, or out of bound errors.
+Rewrites listclearnulls(list/L) to no longer iterate through L.len elements for every null in the list (plus 1). i.e. went from L.len*(number_of_nulls+1) list-element reads (best-case), to L.len list-element reads (worst-case)
+New proc/getElementByVar(list/L, varname, value) which finds the first datum in a list, with a variable named varname, which equals value. You can also feed it atoms instead of lists due to the way the in operator functions.
+Fixes an unreported issue with Yota's list2text rewrite. Under certain conditions, the first element would not be converted into a string. Causing type-mismatch runtimes.
+New global map_ready variable. This is not fully implemented yet, but will be used to avoid duplicate calls to initialize() for map objects.
+All turfs now maintain references to all lights currently illuminating them. This will mean higher memory use unfortunately, due to the huge number of turfs. However, it will speed up updateAffectingLights significantly. I've used list husbandry to reduce baseline memory usage, so it shouldn't be any worse than some past atmos modifications memory-wise.
-Removed 'quadratic lighting', can add this back at some point. Sorry.
+modified the way lum() works slightly, to allow turfs to have overridden delta-lumen. i.e. space cannot be illuminated more than its default ambiance. This allowed removal of some iffy special-snowflake lighting areas implemented by somebody else.
+Lighting images in the dmi can now use arbitrary naming schemes. It is reliant on order now. This allows the dmi to be replaced by simply dropping in a new dmi.
-Removed all subtypes of /area/shuttle. Shuttles now create duplicate 'rooms' of /area/shuttle. (More on this later). This will conflict with most maps. Guide on how to fix to follow.
+All verbs/tools relating to world.tick_lag were refactored to use world.fps. However old config text for setting tick_lag will still work (it converts the value to fps for you)
+MC stats improved using smoothing. They now have their own tab so they dont get in the way when you're playing as an admin.
-removed the push_mob_back stuff due to conflicting changes. Sorry Giacom.
_OK, NOW THE ACTUAL INTERESTING STUFF_
Following systems moved over to subsystem datums:
air_master
garbage_manager
lighting_controller
process_mobs (aka Life())
nanomanager
power
sun
pipenets
AFK kick loops
shuttle_controller (aka emergency shuttle/pods), supply_shuttle and other shuttles
voting
bots
radio
diseases
events
jobs
objects
ticker
Subsystems hooks and variables should be commented fairly in-depth. If anything isn't particularly clear, please make an issue.
Many system-specific global variables have been refactored into
All tickers which previously used world.timeofday now use world.time
some subsystems can iterate before round start. this resolves the issue with votes not working pregame