## About The Pull Request
This adds a new **Black Hole** admin shuttle event while the escape
shuttle is in transit. The regular version spawns a small 1x1
singularity that falls through the ship. There is also a special
adminbus Kobayashi Maru version that spawns multiple black holes
rapidly.
## Why It's Good For The Game

Tell me this doesn't look fun?
## Changelog
🆑
add: Add admin blackhole shuttle event with a normal version and
suicidal version.
fix: Fix several shuttle event runtimes
/🆑
---------
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
## About The Pull Request
- "Long shift" can now be earned from sub 10 minute rounds rather than
sub 5 minute rounds
- Admin restarts no longer give out "Long shift"
## Why It's Good For The Game
I do not think this achievement can *possibly* be earned right now. Like
at all.
Nuke Ops and cult are the only antags that can possibly do it and it's
incredibly infeasible (requiring that they nuke the station or summon
Nar'sie in just 3 minutes!)
So I bumped up the timer to 10 minutes. This means that ops can get it
if they nuke the station in 8 minutes, cult can get it if they REALLY
speedrun, and revs can get it if they beeline the heads.
I checked the DB for stats on this achievement and it's only been earned
in 3 rounds across the last year - `208780` (admin restart due to a bug)
`192892` (admin restart due to a bug?) `186192` (admin restart).
So I also prevented admin forcing the round to end. (I don't know if it
catches admin reboots directly I'll have to check that.)
## Changelog
🆑 Melbert
balance: The "Long Shift" achievement is now feasibly obtainable, and
admins can no longer trigger it unknowingly
/🆑
## About The Pull Request
Removes all of the duplicate global lists for specific machine types
where the only thing they do is store all machines of that type.
Adds machine tracking to SSmachines in the form of a list for all
machines, and then an associative list for machines by their type.
Previously we have machines in multiple global lists, such as airlocks
being in GLOB.doors, GLOB.airlocks, GLOB.machines.
This makes that not a thing, and also means that iterating through
GLOB.machines looking for a specific type is no longer as expensive.
## About The Pull Request
New malf AI upgrade
Remote safety overrides: Mid-cost, Mid-supply. Allows the AI to remotely
emag things it can see and can access.
1. Very useful for psychological warfare (Emagging APCs to throw the
crew off their trail)
2. Logically makes sense - why, of all things, can the AI not emag
anything when it's fundumentally integrated with the station's
electronics?
3. Generally speaking can only access things that make sense for it to
access - it cannot emag ethereals, sadly
In order for this to work, emag_act now returns a boolean, designating
if the emag had any effect.
While I was in there, I also added args to every single emag_act I could
find and added far more feedback/converted a lot of things to balloon
alerts to allow the AI to see if its emag had any effect.
## Why It's Good For The Game
It just makes sense that the AI, the most electronically-sensitive
entity in the game, would be able to emag things. Plus, more options
given to malf that aren't strictly MURDER KILL MURDER are always a plus,
especially if they allow for fancier plays.
## Changelog
🆑
add: New malf ability: Remote safety overrides. Allows the AI to
remotely emag things it has access to.
code: emag_act() now returns a boolean designating it's success in
emagging
code: All instances of emag_act() now have the proper arguments
qol: Most usecases of emagging now have some kind of feedback, and
existing feedback has been sanity checked and converted to balloon
alerts.
/🆑
## About The Pull Request
Further continous organizing and cleaning the Icons folder. There are
still some minior nitpicks left to do, but I reached my daily sanity
expenses limit again, and the faster these get in the less issues for
both me and others later. Also cleans some mess I caused by my blindness
last PR.
## Why It's Good For The Game
Saner spriters = better sprites
## About The Pull Request
Machines that require a cable underneath it to operate like Tesla, SMES,
Emitter & Turbine now look for the `cable_layer` (red, yellow, blue
default being yellow) to operate on and not `machine_layer`(that var is
removed). `machine_layer` & `cable layer` served the same purpose so i
removed `machine_ layer` var and made it just look for the cable layer
to operate on to reduce redundancy.
The following machine's can have their cable layer changed with a
multitool when in the specified state
1. Emitter when it's not welded
2. Tesla Coil when it's not wrenched
3. SMES when it does not have a terminal attached
3.1 Terminal of the SMES cable layer can also be changed with Right
Click during installation
4. APC terminal cable layer can also be changed with Right Click during
installation
5. Turbine rotor when its panel is open

Here all 3 SMES were on 3 separate layers of cable but they were all
joined by a single multi z layer hub cable summing up all their
contribution's even though they were on different cable layers.
## Why It's Good For The Game
It makes sense that a machine should only look for what cable layer it
should operate on and adding another layer called machine layer was just
redundant. Also cable layers blue & red which could not be used by
machines are now usable
## Changelog
🆑
fix: cable layers 1 & 3 can now be used by machine's like emitters,
smes, tesla coil & turbine.
fix: terminals(smes & apc) can operate on different cable layers by
installing them with right click
/🆑
---------
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
Remove welder fuel usage from all actions except attacking and leaving
it on
most welder tasks require a minimum of 1u of fuel, some longer tasks
require a minimum of 2 or 3u welders now drain 1u every 5 seconds
they're active
## About The Pull Request
Prior to this PR welder fuel usage was random, a lot of tasks didn't use
any welder fuel and welders were basically near infinite so long as you
didn't use them for combat, it took 26 seconds of activity to drain 1u
of fuel, that means an emergency welder alone could run for 5 minutes
straight before needing a refuel
After this PR all welders will drain 1u every 5 seconds instead of every
26 seconds, but welding objects won't require extra fuel anymore, making
the fuel usage much more consistent.
resolves#55018
## Why It's Good For The Game
Actually makes fuel tanks useful and relevant without making it
obnoxious to do repetitive quick tasks like turn rods into plates,
there's actually a reason to upgrade off the emergency welder now since
it lasts 50 seconds rather than 5 minutes
## Changelog
🆑
qol: Welders now have a more consistent fuel usage
/🆑
## About The Pull Request
[A common problem with explosions is an overabundance of
sleeping](6499077a09)
In an attempt to solve this issue, let's not continue to sleep and do
work in door closing if the door is already deleted
(This is caused by firelocks activating due to other adjacent objects
deleting, triggering an atmos update, and closing the firelocks before
they get bombed. I don't have a elegant way of resolving that core
problem, so let's just minimize the impact)
[Nukes a stupid sleep loop in airlock
code](5b16360520)
When an airlock was depowered, it would enter a sleep loop, decrementing
its delay by 1 second every well, one second, so long as it had the
right wires flipped
This is very stupid
Instead, let's use signals off wire changes and a combo of timer and
remaining time var to do this with JUST a timer
Most of the changes here are just swapping over wires to a setter to
make signal registration work\
## Why It's Good For The Game
Less sleeping around explosions means less dropped ticks after a bomb
goes off. Good just in general
Also this excises dumb boomer code and adds some hooks for other devs to
use (we should use wires more man)
## About The Pull Request
Allows field generators to contain explosions. The fields will not let
the explosion propagate past them.
## Why It's Good For The Game
Allows people to contain the tesla for fun, or on station bomb testing
if they so desire.
## Changelog
🆑
balance: Field generators can parry explosions.
/🆑
## About The Pull Request
Resprites stock parts to bring them up to date, changes manipulators to
servo motors as I couldn't make manipulators work well at this scale.

(Power cells sold separately)
## Why It's Good For The Game
The old stock parts are dated, in some cased quite ugly, and in the case
of manipulators a ball of assorted pixels. Incidentally removed a couple
of single letter var names.
## Changelog
🆑
image: Stock parts have been resprited.
code: Manipulators have been renamed to servo motors, all related types
have been repathed to match.
/🆑
basically ex_act's implementation on basic mobs would call parent and
then react to it's value, this is presumably to do the first check about
space vine mutations and whatever. the problem is that the `/mob/living`
implementation would itself also call parent, and that would always
return null because `/atom/proc/ex_act` doesn't have a set return value.
So, this simply would _always_ early return, with ex_act presumably
*never* working on basic mobs for at least four months now.
I decided to then change up the return values for pretty much all
implementations of `ex_act()` since there was no rhyme or reason to
returning null/FALSE/TRUE, and documenting why it's like that.
Just to make sure I wasn't breaking anything doing this (at least on
base implementations), I wrote a unit test for all of the three major
physical types in game (objs, mobs, turfs) because i am a paranoid
fuckar. we should be good to go now though.
## Why It's Good For The Game
i noticed this because placing c4's on sargeant araneus wouldn't
actually damage it whatsoever. now it actually does the stated 30
damage, but araneus has like 250 health so it doesn't actually matter in
the long run. whatever at least it does the damn 30 now.
also adds a unit test for this specific case as well as a range of other
cases to ensure this stuff doesn't silently break in this way anymore
## About The Pull Request
Requires #74562 and #74556 be merged first.
Unit tests cult conversion and throws in a case for rev AOE flashes
## Changelog
Not necessary
---------
Co-authored-by: san7890 <the@san7890.com>
This tracks the seconds per tick of a subsystem, however note that it is
not completely accurate, as subsystems can be delayed, however it's
useful to have this number as a multiplier or ratio, so that if in
future someone changes the subsystem wait time code correctly adjusts
how fast it applies effects
regexes used
git grep --files-with-matches --name-only 'DT_PROB' | xargs -l sed -i
's/DT_PROB/SPT_PROB/g'
git grep --files-with-matches --name-only 'delta_time' | xargs -l sed -i
's/delta_time/seconds_per_tick/g'
The check queue is 5 minutes long because that's the longest a client
can hold onto a reference. Without clients, we can drastically decrease
the time we have to wait. This lowers the time down to 10 seconds
(though everything right now deletes in 5).
This will represent a 5 minute decrease in CI across the board, freeing
up runners.
Makes a few changes to stuff that was being held for more than 10
seconds.
- `VARSET_CALLBACK` now works through weakrefs, to allow for pAIs to
have their holochassis init timers.
- Nar'Sie cleans herself up in GLOB.cult_narsie if she's deleted.
- "Spooky portals" no longer hold onto a reference for 2 minutes.
- `poll_candidates` short circuits to an empty list if there are no
candidates, to avoid several 30 second+ long timers
Originally this was going to be a more clever hack from @MrStonedOne
about short circuiting if everything deletes before the wait, but we
realized that basically nothing actually holds onto references for that
long without clients, and that nothing really should anyway
## About The Pull Request
This sprite file had been a dumping ground for miscellaneous sprites for
the past decade. It's bloated and full of random kinds of icons and even
has a few unused ones. It's time to reorganize them into their own
separate dmi's based on theme.
## Why It's Good For The Game
Better organization and easier access when looking for stuff.
## Changelog
🆑
imageadd: Split all icons in weapons_and_items.dmi to their own
categories
imagedel: Removed some unused icons
/🆑
## About The Pull Request
<details>
<summary>Dark Matt-eor Image</summary>

</details>
> A barely visible blur in the cosmic darkness, like a ghostly shadow on
a moonless night. A piercing howl in the vacuum of space, as if it were
tearing the fabric of reality. A twisted halo of light around it,
bending and breaking the rays of distant suns. A shower of quantum
sparks, flickering and fading in its wake. A dark matter meteor (dark
matt-eor) is a wonder to witness, and to dread.
> A sudden impact, like a hammer blow to the heart of the station. A
violent tremor, shaking and shattering the metal walls and windows. A
deafening roar, as the air rushes out of the breached hull. A blinding
flash, as the dark matter meteor unleashes its hidden energy. A tiny
black hole, forming and growing in the center of the station. A
relentless pull, dragging everything towards the abyss. A dark matter
meteor is incredibly deadly.
Emagging too many meteor shields will summon a dark matt-eor. This comes
with several warnings, and after awhile, warns the station that someone
is trying to summon a dark matteor.
The dark matt-eor itself is not that damaging in its impact, but drops a
singularity in its final resting place.
## Why It's Good For The Game
It's a new way to terrorize a round as an antagonist. Before, emagging a
lot of meteor shields would basically make meteor showers the only event
that can run, which is cool, but since constant meteor waves are going
to destroy the station, let's also throw in the mother of all meteors!
This also adds warnings to spamming emagging meteor shields, which imo
needs it. The round ends when someone spams emagged meteor shields, and
since they're meteor shields nobody is going to reasonably check on
them.
## Changelog
🆑
add: The dark matt-eor
add: Summon a dark matt-eor final traitor objective
add: Dark matter singularity variant, which can't grow as big as a
regular singularity but hungers for blood
code: cleaned up/sorted meteor shield code, satellite control, and more
qol: added a lot of feedback to interacting with meteor shields
balance: emagging a lot of meteor shields warns the station, but
emagging enough of them summons a Dark Matt-eor.
/🆑
## About The Pull Request
Fixes#39775
The `TRAIT_INCAPACITATED` trait is intended to block you from acting but
does not inherently block actions. Actions only check for "conscious",
"has available hands", "immobile", or "lying down".
Most actions still _can't_ be used while incapacitated. This is because
most actions are spells, most spells have invocations, and you can't
talk while you are incapacitated. This is silly.
I have resolved this by adding a new flag which blocks actions while
incapacitated. This is somewhat redundant with "conscious" because most
sources of that also make you incapacitated but not _always_, you might
want the specificity.
I have tried to be discerning about where this flag is applied, it is
not in all cases (for instance you can still swallow implanted pills
while incapacitated and such), but it's not only possible but I can't
really avoid implementing this without it being a balance change in
_some_ cases,
Actions this effects are things such as:
Xenomorph Tail Sweep, Lesser Magic Missile (cult constucts), Heretic
Shadow Cloak, the Smoke spell in general, Conjuring (but not firing)
Infinite Guns, Mime spells
Times when these actions will no longer be available but were previously
are such times as when the mob is:
Stamina Crit, Stunned, Paralysis, and Time Stopped.
## Why It's Good For The Game
The incapacitated trait is applied by effects which should block acting
but still permits several actions which logically would be prevented.
This fortunately hasn't come up too often due to the high ratio of
actions with invocations, but it feels bad to stun someone and then have
them still able to perform an action they logically wouldn't be able to
take while stunned.
This is especially egregious in the case of Time Stop (the only way to
stun a lot of the mobs effected by this) but that's a rare pick on a
rare antagonist and would also rarely be used on these mobs, so a bit of
an edge case.
## Changelog
🆑
fix: Many spell-like abilities which could be stunned, paralysed, or
frozen in time now cannot be.
/🆑
## About The Pull Request
The linters in #73202 revealed to me that `heal_overall_damage` was
overridden wrong in `carbon` and left out an argument, meaning that
plausibly some places that didn't provide an argument for `stamina`
probably had an off-by-one error with args and wouldn't apply them
properly.
I fixed that in that PR because it was using it. Then I noticed that the
same problem exists in `take_overall_damage` so I am fixing that too.
I don't know if this was linked to any actual bugs, but it might cause
some. They'd be hard to spot because it'd be for stuff like "a
shadowperson with a prosthetic takes damage to their prosthetic if not
in darkness" and probably nobody would even get into that situation let
alone notice to report it.
## Why It's Good For The Game
We want arguments to do what they are supposed to do.
## Changelog
🆑
fix: Biotypes will be more consistently applied when taking damage, pod
and shadowperson prosthetic limbs won't be corroded due to light levels.
fix: Podperson and Wooden Golem prosthetic limbs won't be corroded by
having a hungry tummy.
/🆑
## About The Pull Request
Part of a prior PR that was closed (#72562). This version does not add
the check in CI.
## Why It's Good For The Game
The work is already done, so I figured why not.
## Changelog
N/A Nothing player facing
Co-authored-by: Jeremiah Snow <jlsnow301@pm.me>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
So i accidently reverted all my commits in #72511 when resolving a merge
conflict So ummm yeah fuck my bad anyway
## About The Pull Request
Finishes what was started in #71693 and completes the
[initiative](https://github.com/tgstation/dev-cycles-initiative/issues/1)
Except for `obj/item/stock_parts/cell` and its subtypes. All machines
now use `datum/stock_part` for its requested components & component
parts
Not sure if i caught every machine & stuff in the game so merge with
caution
## Changelog
🆑
code: datum stock part for every obj stock part
refactor: all machines & dependent experiments to use datum stock parts
/🆑
Necessary for #72292 to work effectively, and probably not very useful
out of that context. Split out of its own PR because this is long and
boring.
I want to make sure that we're catching actual mistakes there, and not
just experiencing side effects of how shitty the attack chain is.
## About The Pull Request
- Rewrites how action button icons are generated.
- Prior, generated an action button icon was fairly simplistic and
didn't allow for many changes. Someone recently added the option for
overlays to be generated over action buttons, but the framework was very
weak.
- Now, action button icon generation is split across multiple procs,
like atom icon updates.
- The background of action buttons are underlays
- The actual icon of the action button is the icon and icon state of the
action button movable
- The rim / border of the button is an overlay, layered overtop the
button.
- Allows observers to see what action buttons a mob has. They even
update in real time! And no, the observers cannot click on them.
## Why It's Good For The Game
- Runechat text of action buttons are no longer hidden behind the actual
icon. This was very ugly with cooldown actions, as the cooldown text was
hidden behind a lot of spell icons.
- Cuts down on a lot of icon duplication.
- Gives much finer control over action button icons
- Saves a bit of processing from generating full action button icons
when not necessary. Not implemented in many places, but is in some.


## Changelog
🆑 Melbert
add: Observers can now see what action buttons an observed mob has. No,
you can't click them. And no it doesn't show EVERY action.
refactor: Refactored how action button icons are generated. Some actions
will now use a colored border when active instead of just turning green.
Cooldown text will also appear on the top layer of actions too. If you
see any funky lookin' icons (namely their borders), let me know.
refactor: Bluespace Golem's teleport action is now a cooldown action.
fix: Construct actions go to the middle of the screen like expected.
/🆑
## About The Pull Request
Atomisation of #71421
This moves the attack function of "environment smash" flags which allow
simple mobs to attack walls into an element, so that we can put it on
other things later.
For some reason while working on carp I convinced myself that they had
"environment_smash" flags, which they do not, so this actually is not
relevant to carp in any way.
While implementing this I learned that the way wall smashing works is
stupid, because walls don't have health and so resultingly if a mob can
attack walls it deletes them in a single click. If we ever decide to
change this then it should be easier in an element than in three
different `attack_animal` reactions.
This is especially silly with the "wumborian fugu" item which allows any
mob it is used on to instantly delete reinforced walls, and also to
destroy tables if they click them like seven or eight times (because it
does not increase their object damage in any way).
## Why It's Good For The Game
Eventually someone will port a basic mob which does use this behaviour
(most of the mining ones for instance) and then this will be useful.
If we ever rebalance wall smashing to not instantly delete walls then
this will also be useful.
Admins can apply this to a mob to allow it to delete walls if they
wanted to do that for some reason, they probably shouldn't to be honest
at least until after we've done point two unless they trust the player
not to just use it to deconstruct the space station.
## Changelog
🆑
refactor: Moves wall smashing out of simple mob code and into an element
we can reuse for basic mobs later
/🆑
So i left over some basic `/whatever/proc/format` uses in the original
PR this fixes it.
Notable exceptions to the rule:
- Paths in add_verb/remove_verb, we need full path instead of a name
there to access verb metadata so we can't use proc ref macros there.
- regex.Replace, found out that it does not accept call by name. Instead
i added new REGEX_REPLACE_HANDLER so we can at least try to mark these.
There's still leftover global procs that do not use GLOBAL_PROC_REF but
they functionally equivalent so that's for later.
I don't see any reasonable way to grep for this. But if you got any
ideas please share.
## About The Pull Request
Hey there,
force_ending was a boolean (with inconsistent usage, flip-flopping
between using TRUE/FALSE and 1/0 variables), so let's just change it all
over to the macros and call it a good day.
I also updated documentation of the variables in that "code block" in
SSTicker while in the area because changing just one line made it look
ugly. Some of the documentation was no longer current to it's... current
use in code, so I updated those as well.
## Why It's Good For The Game
Pure code improvement, DMdocs are swell, and readability is kino.
## Changelog
Nothing here should affect players.
Makes the code compatible with 515.1594+
Few simple changes and one very painful one.
Let's start with the easy:
* puts call behind `LIBCALL` define, so call_ext is properly used in 515
* Adds `NAMEOF_STATIC(_,X)` macro for nameof in static definitions since
src is now invalid there.
* Fixes tgui and devserver. From 515 onward the tmp3333{procid} cache
directory is not appened to base path in browser controls so we don't
check for it in base js and put the dev server dummy window file in
actual directory not the byond root.
* Renames the few things that had /final/ in typepath to ultimate since
final is a new keyword
And the very painful change:
`.proc/whatever` format is no longer valid, so we're replacing it with
new nameof() function. All this wrapped in three new macros.
`PROC_REF(X)`,`TYPE_PROC_REF(TYPE,X)`,`GLOBAL_PROC_REF(X)`. Global is
not actually necessary but if we get nameof that does not allow globals
it would be nice validation.
This is pretty unwieldy but there's no real alternative.
If you notice anything weird in the commits let me know because majority
was done with regex replace.
@tgstation/commit-access Since the .proc/stuff is pretty big change.
Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
* Makes flags properly check themselves
Byond ref: https://www.byond.com/docs/ref/#/operator/&
Basically, flags should use & instead of ==
We can have more than 1 slot on any item, so it's preferred that we do this instead. Even if it doesn't immediately fix any problems, it's something that should be the standard anyways to prevent it from ever being a problem.
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Moves singulo and supermatter dmis into obj/engine, renamed from obj/tesla_engine
Moves Halloween, Christmas, and misc holiday items to obj/holiday
Moves lollipops to obj/food
Moves crates, closets, and storage to obj/storage
Moves assemblies to obj/assemblies
Renames decals.dmi to signs.dmi ...because they're signs and not decals
Moves statues, cutouts, instruments, art supplies, and crayons to obj/art
Moves balloons, plushes, toys, cards, dice, the hourglass, and TCG to obj/toys
Moves guns, swords, shields to obj/weapons
* Removes ComponentInitialize()
Completely removes ComponentInitialize() as a proc, which was called on every single atom in the game, twice in some instances (like new players), over something that can already be done with Initialize().
This is the second attempt at doing this, after the first attempt fell apart for some reason. This time it was way easier though, since storages are no longer a Component.
* update icon blocker added before calling parent
* Update code/game/machinery/porta_turret/portable_turret.dm
Co-authored-by: san7890 <the@san7890.com>
* adds a mapload while I'm here
* moves human mood
* Does some UNRELATED thing to the PR
Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com>
Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com>
About The Pull Request
Emitter status display on examine will now display the minimum and maximum firing delay depending in place of an inaccurate static speed.
Why It's Good For The Game
Fixes#68820
As the emitter shoots at a random speed (inexplicably, it seems to create more issues than it solves), saying it'll fire "one beam every x seconds" is inaccurate as it's subject to change.
About The Pull Request
replaces a ton of log_game with user.log_message so the log is added to individual and global logs.
adds a few logs for individual LOG_VICTIM, LOG_ATTACK etc logging.
adds logging for bluespace launchpad's tele coords being changed.
took the word "has" out of log_combat, as it's extra and just lengthens the log.
Why It's Good For The Admins
It's extremely laggy to open game.txt so an alternative is individual game logs
Changelog
cl
admin: A lot of game logs will now also be in individual game logs, for convenience in log diving.
admin: Added logging for bluespace launchpad x and y offset changes, which go to individual game logs.
admin: Attack logs will now be slightly shorter, one useless word was removed.
/cl
* [DRAFT] Reformats Access IDs for accessibility and futureproofing
* replaced all the old defines and IDs everywhere
* replaced ID integers with strings, cleaned up a couple tram helpers
* replaces req_access_txt with req_access and fixes a few of my mistakes
Co-authored-by: san7890 <the@san7890.com>
This PR refactors firestacks into two status effects: fire_stacks, which behave like normal firestacks you have right now, and wet_stacks, which are your negative fire stacks right now. This allows for custom fires with custom behaviors and icons to be made.
Some fire related is moved away from species(what the fuck was it even doing there) into these as well.
Oh and I fixed the bug where monkeys on fire had a human fire overlay, why wasn't this fixed already, it's like ancient.
Also changed some related proc names to be snake_case like everything should be.
This allows for custom fire types with custom behaviours, like freezing freon fire or radioactive tritium fire. Removing vars from living and moving them to status effects for modularity is also good.
Nothing to argue about since there's nothing player-facing
I'll do more in the future but I'll limit myself to this because I'm tired, bored, and don't want to make so many PRs touching the same things that I have to deal with conflicts each time one is merged.
Just as an example, screwdriver's gotta be done as well, does the exact same thing wrenches do, I believe.
Standardizes (and touches) each time default_unfasten_wrench is used.
Fixes tool logs, since it relies on tool acts to exist, I'm trying to move as many tool acts to its proper proc. Like a spiritual successor to the tool superpack PRs.
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
About The Pull Request
I noticed a lot of strange and un-intuitive behavior in action buttons, and got stung by the bloat bug. Damn it hug #58027
I'll do my best to explain what I've changed and why, might get a bit long.
If you want a better idea, read the commits. Most of em are pretty solid, if long.
Whelp. Here we go.
How do action buttons currently work
All action buttons are draggable, to any place on the screen. They're held in an actions list on the player's mob.
Their location in this list determines their position on the top of the screen. If one is dragged away from the top, its position in the list is "saved". This looks really bad.
If two buttons are dragged over each other, their positions swap. (inside the actions list too)
If a button is shift clicked, it is brought back to the position it started at.
If the action collapse button that you likely just mentally edit out is alt clicked, it resets the position of all action buttons on the screen.
If an action is ctrl clicked, it is "locked". This prevents any future position changes, and also enables a saving feature. With this saving feature, locked button positions persist between rounds. So your first o2 canister will always start where you saved it, etc.
Actions and buttons are a one to one link. While there is functionality to share action buttons between two players, this means showing the same object to both. So one player can move a button on another's screen. Horrendous.
This also makes code that modifies properties of the screen object itself very clunky.
Why is this bad
A: None knew pretty much any of this information. It is actually documented, just in a horribly formatted screen tip on the collapse button, you know the one we all mentally delete from the hud.
B: None of this is intuitive. Dragging buttons makes the hud look much worse, and you get no feedback that you even can drag them. Depressing
C: We use actions to make new options clear to the player. This means players can have a lot of action buttons on the hud. This gets cluttery
D: The collapse button is useless. It lets you clear your screen if someone like me fucks up and gives you 2000 actions, but outside of that it just hides all information from you. You never want to see none of your action buttons, just a filtered list of them.
E: On a technical level, they're quite messy, and not fully functionally complete. This is depressing.
What I've done
Assuming the above to be true, how do we fix them?
Well first I'm going to go over everything I changed, including links to major commits. I'll then describe the finished product, and why I made the decisions I did.
Oh and I've moved some of the more niche or technical discussion to dropdowns. Hopefully this makes finding the major functional changes easier
Adds helper procs for turning screen_loc strings into more manageable arrays. This doesn't fully support all of the screen_loc spec, but it's enough for what I'm doing. (f54865f)
Uses these helper procs to improve existing code (6273b93)
Fixes an issue with tooltip code itself. If you tried to hold down a mouse button while dragging onto a tooltip enabled object, it would silently fail. The js made assumptions about the order args came in, which broke when buttons were held down (e0e42f6)
Adds a signal linked to /client/Click(). Surprised we didn't have this before honestly (c491a4a)
Makes /client/MouseDrag() return parent. If we don't do this, any overrides of MouseDrag will never actually be called (2190b2a)
Refactors how action buttons work under the hood (53ccce2)
Basically, rather then generating one button per action, we generate one button per viewer
Starts to change button behavior, more cleanup
Changes the mouse cursor when an action button is dragged. Hopefully
this makes moving things feel less like an accident, and makes you doing
it more clear
Removes the moved and locked vars. This will be more relevant later, but
for now:
Moved exists as a sort of budget "We've been dragged" variable. We can
handle this more cleanly, and the movable type doesn't care about it
Locked is a very old variable that is also not something that the
movable type "owns". It's more an action button thing that's been moved
down.
It exists so an action can be locked in place, and in that locking, be
treated as a "saved location"
(21e20fc)
Because I've nuked move, we don't need to directly set our button's
position. We can use the default_button_position var instead. This is
quite handy.
Please ignore position_action, I will explain that later
(83e265e)
Removes the buttons locked pref
It was another obscure part of action buttons, basically do buttons
start "locked" or not. See previous discussion of locked
(b58b1bd)
Major rework starts here
Alright. Sorry for this, this is where me not commiting regularly starts
to suck. I'll do my best though.
Rather then figuring out an action button's position via a combination
of the moved and ordered vars, we use a separate location var to store
one of a few defines. This makes life later much easier.
Adds tooltip support for dragging action buttons. The way the tooltip
just froze in place when dragging really bugged me, and lead to some
nasty visual artifacts.
This is a bit messy because the drag procs are horrible, but it's
workable
Dropping a button on another button will no longer swap their positions
Behavior instead depends on the target button.
If it's a part of a group (A concept I will explain later) the dragged
button is simply inserted before it in the group's list.
If it's floating on the general hud, we instead position the dragged
button to its right. There's extra logic here to ensure buttons will
never overflow the screen, but I'll get into that later.
Alright. That's most of the refactoring. Time for the larger behavior
changes.
Adds a button palette. This is a separate dropdown that renders
underneath buttons.
image
The idea is to allow for a conceptual separation between "important"
buttons and the ones that end up cluttering the screen.
You can click on the dropdown to open it, then any later clicks that
don't involve actions in some way will autoclose it.
My goal is to come up with an alternative for the action button that
just acted as a way to hide all buttons on screen. Not convinced it saw
much use.
As a side effect of removing that, I've moved its tooltip stuff to the
palette. I've properly formatted it, so hopefully it's easier to read
then the jumble that we used to have.
(You can alt click the palette button to reset all button positions)
Oh and the palette can scroll, since as you'll see later it has a
limited size.
image
Moving on from that, I've added what amounts to action landing buttons.
These allow buttons to rejoin groups, or be positioned at the end of a
line of buttons.
image
They've got a 32x32 hitbox, and only show up when dragging. Hopefully
this makes the system more clear just by dragging an action.
Oh and I've changed how button position updating works. The old system
of calling update_action_buttons on mob every time an action button
changes position is gone, mostly because I've setup more robust
grouping. Will discuss when I get to huds
(0d1e93f)
Adds the backbone behind action button position changes (94133bd)
Moves hud defines to the global folder, safer this way (7260117)
Adds color changing to the palette button, giving some heads up for buttons being inserted into the palette automatically
image
image
Ensures a landing button is always shown, even if it needs to break the
max row rule
Makes palettes auto contract if they have no buttons inside them
Prevents palettes from being opened if they have no buttons inside them
(f9417f3)
How it looks
2022-02-26.02-30-10.mp4
Why It's Good For The Game
Players have more control over the clutter on their screen.
Buttons are available, but not in the way,
Since any player move of a button saves it, any lack of clarity in the way buttons work will be forced out by buttons not just resetting when a new game starts.
We don't overlap any existing screen elements, unless the upper button list gets really long.
The code is much less crummy (I think, may have made it worse it's hard for me to judge my own work)
If it ends up not being as usable as I'd like, I'll rip out the existing changes and just implement the qol and backend stuff. I think it's worth doing though.
Changelog
cl
add: Expanded heavily on action buttons
add: Adds an action button dropdown that sits just under the normal list in the top left. You can drag new buttons onto it to insert them. Click on it to show its contents, do what you want to do, then click again anywhere to contract it. Alt click it to reset all button positions
add: Action buttons will now remember their position between rounds. So if you really like your flashlight right next to your player for some reason, we support that now
add: When you start to drag an action button, docking ports will appear in places that it can be inserted into. (Outside of just floating somewhere on your screen of course)
del: Removed action button locking, and the associated preference. I'm reasonably sure literally none uses this, but if you do hit me up
qol: Dragging an action button will now give you an outline of its size around your cursor
fix: You can no longer cause the screen to expand by putting an action button on the edge of widescreen, and then resizing to standard.
refactor: Refactors action and button code significantly. lots of little things.
/cl
This adds some new defines and flags for the rotation component that lets us remove lots of c/p code chunks. I also added documentation to all the rotation defines that currently exist and in other spots that had weird behavior.
New rotation flags:
ROTATION_GHOSTS_ALLOWED - checks if ghosts are able to manipulate objects in config and lets them rotate the object
ROTATION_IGNORE_ANCHORED - this skips checking if an object is anchored (which normally prevents us from rotating) Used mainly for chairs.
ROTATION_NO_FLIPPING - this removes the flip verb from possible right click rotation options. Used for pipes that have custom flipping verbs instead
ROTATION_NEEDS_ROOM - this checks if an object needs to have an empty spot available in target direction. Used for windows and railings.
Objects can now be rotated in the direction based on which LMB or RMB you click with when you ALT click it. LMB is counter clockwise. RMB is clockwise. Before some objects could only be rotated clockwise. Now any object that inherits the rotation component can be rotated in either direction.
There was also a bug with wheelchairs that existed from when they were ported over from another codebase. The rotation logic was broken and never allowed anyone to rotate them. This has been fixed.
Rotation for IV_drips was enabled however Alt Click was being used for another proc and rotation was ignored because of this. I removed the rotation component due to this since I didn't want to change the hotkeys for IV drips since those have an actual effect on gameplay interactions while rotation does not.
Fingerprints are no longer added when something gets rotated. Only a few objects had this enabled but I believe this interaction was very spammy and unnecessary. I can readd this as a flag if needed but for now it's removed.
Alert balloons have replaced a lot of rotation to_chat() messages for the same reason as fingerprints. Rotating objects has almost no effect on gameplay and will only clutter a player's message log.
The hotkeys for pipe interactions had to be redone since Alt clicking was already being used in some situations. For regular pipes: Right clicking now changes the pipe layer. Alt clicking rotates the pipe. For Trinary pipes: Right clicking now flips the pipe device. Alt clicking rotates the device.
ComponentInitialize() is a deprecated function and the AddComponent proc was moved to Initialize for several objects.
Adds a basic bucketing system to move loops.
This should hopefully save a lot of cpu time, and allow for more load while gaining better smoothness.
The idea is very similar to SStimer, but my implementation is much more simple, since I have to worry less about long delays and redundant buckets.
Insertion needs to be cheaper too, since I'm making a system that by design holds a lot of looping things
It comes with some minor tradeoffs, we can't have constant rechecking of loops if a move "fails", not that we really want that anyway
We also lose direct control over the timer var, but I think that's better, don't want people manipulating that directly
Not that it even really worked very well back when we did have it
Removes the sleep from singularity code
Rather then using sleep to store the state of our iteration, we instead queue the iteration in a list.
We then use a custom singulo processing subsystem to call our "digest" proc several times per full eat, with the hope of staying on top of
our queue
This rarely happens because the queue is too large, god why is a sm powered singulo 24x24 tiles.
I've also A: cached our dist checks, and B: Added dist checks to prevent attempting to pull things out of range
This might look a bit worse, but it saves a lot of work
Oh right and I made the singulo unable to eat while it still has tiles to digest. The hope is to prevent
overwork and list explosion.
Hopefully this will prevent singulo server stoppage, though I've seen some other worrying things in testing.
You can click on things through cameras. This is one of the major appeals of BRPEDs. If you try to shoot at things while using a camera console to aim you will shoot at the angle between the camera you are looking through and the thing you are aiming at. This makes you aim at the thing you are aiming at from the perspective of yourself instead of the camera you are using.
While it would be funny to watch a sniper gun down their own team aiming through a camera bug and shooting in the opposite direction they think they I'd prefer if it actually worked.