## About The Pull Request
Oh man, so this entire pr started because of two things:
1. A kinda hacky fix to #92123 that got closed a good while ago.
2. A borg I know mentioning you can't do custom say verbs over robotic
talk.
Which subsequently led me down this rabbit hole of say modes and custom
say verbs.
So! The most wide-reaching thing this does is merge the custom say
verb/radio emote logic that used to be specialcased in
`compose_message(...)` into `say_quote(...)`, renaming this to
`generate_messagepart(...)` with its new functionality. This means
things that don't use the exact same chain as living things talking
normally can still generate custom say verbs if given that message
modifier.
Then, we split up say modes into a "can we do this" and "try to do this"
check to reduce conflicts (like #92123), and forward more of our data to
the latter. This allows us to then edit the say modes to actually make
use of that data, and with the previous addition of
`generate_messagepart(...)` allow for custom say verbs to be used.
In doing this I realized the logging was kind of awkward and all over
the place, so we create the new logging helper `log_sayverb_talk(...)`
which handles selecting how we should log things based on the given
message modifiers.
For better or worse I forgot about this pr for a few weeks, so I don't
perfectly remember all the details, but those are the big key parts.
## Why It's Good For The Game
Fixes#92123.
I think custom say verbs are some of the best flavour we have for
talking over radio, and any situation benefits from that being possible.
It's great to be able to tap your microphone, and it's hilarious for an
AI to be able to emote beaming an image directly into the heads of their
borgs over robotic talk.
The rest is mostly cleanup.
Moves all the dna block handling onto singleton datums initialized
inside global lists, to make the handling dna less of a copy-paste mess
and make adding new blocks significantly easier. There is still some
work to be done in the copypaste department but ultimately that falls
under its own PR scope after the core refactor goes through. (Ill
probably do those but it will also be easier for everyone else as the
code is now significantly less of an eyesore)
Both features and identities have been tested through and through, and
seem to be working fine.
Also removed the reliance on weird hardcoded lookup tables for length,
and other similar things that just didn't make sense when I was passing
through DNA code. There's a lot more that fall out of scope for this
exact PR's goal however
I've been told the maintainers will love me for doing this
🆑
code: feature keys are no longer magical strings floating around the
codebase and use proper defines
refactor: DNA blocks are now handled with singleton datums.
/🆑
## About The Pull Request
The entire asset loading had multiple issues.
Firstly, we could hit a tick check after an asset was generated and
didn't remove the index, leading to the asset being generated twice.
Secondly, we had the issue that the icon forge batching uses UNTIL to
wait until generation finishes. This led to the situation that the
entire subsystem fire proc was paused outside of the internal tick check
pause.
## Why It's Good For The Game
Especially on larger sprite sheets or when there're many to be generated
this led to the situation that we looked up a rust job multiple times:
`[2025-08-08T18:42:11] Runtime in
code/modules/asset_cache/iconforge/batched_spritesheet.dm,200:
Spritesheet design UNKNOWN ERROR: NO SUCH JOB`
## Changelog
No player facing changes.
## About The Pull Request
**1. Code Improvements**
- Removed unused vars `coin`, `bill` & other stuff
- Removed duplicate definition of `on_deconstruction()`
- Autodoc for a lot of procs
- Merged smaller procs into larger ones to avoid scrolling in the code
editor & reduced overhead
- Split the vending machine file into several smaller files for easy
code management
**2. Qol**
- Implemented vending machine ads. They now display random stuff on the
UI
https://github.com/user-attachments/assets/9720ea60-f268-4ca2-940d-243e3d0ac75f
- More error messages for custom & normal vendors as to why an item
could not be loaded
- Custom vending machines can be deconstructed safely via crowbar
without any explosion only after unlinking your account from the machine
else you get the same explosion. Upon deconstruction all loaded items
are moved into its restock canister meaning the machine can be safely
moved with all its products just like a regular vending machine to a new
location
**3. Fixes**
- Fixes#81917. Any returned items in the vending machine now show up as
free in the UI & won't cost credits to buy them
- Fixes#87416. Custom & normal vendors now keep track of products
removed via `Exited()` so the UI gets always updated
- Fixes#83151. Items with different names & custom prices now show up
in unique rows
- Fixes#92170 Custom vendors now show the correct icon for inserted
items
- Closes#80010. From the above fix this situation is impossible so it's
safe to close this as a duplicate
- Closes#78016 same problem as above with `Exited()` duplicate
- Custom vendors can now actually be used by players who are not the
owner instead of locking down the UI
- Vending machines keep track of `max_amount` of stocked items by hand
as well & not just RPED
**4. Refactor**
- Separates custom vending machine code from normal vending machine
code. This prime Marely focus on the `vending_machine_input` list which
now only exists inside the custom vending machine
- Compressed the UI code for vending machine so both custom & normal
vending machines can send the same data instead of separating the 2.
Overall less code
- Moved attack chain from `attackby()` to `item_interaction()` for
loading items
## Changelog
🆑
code: cleaned up vending machine code
qol: vending machines now have more product slogans you never heard
before
qol: custom & normal vending machines now have more feedback on why an
item could not be loaded
qol: vending machines now display random ads on the UI
qol: custom vending machines can be deconstructed via crowbar safely
only after unlinking your account from the machine.
qol: upon deconstructing a custom vendor all its products are moved into
its refill canister & it will be restored when reconstructing the
machine elsewhere
fix: Returned items to the vending machine now show up as free in the UI
and won't be greyed out if you don't have credits to get them back
fix: items that leave the vending machine by any means will update the
UI in all cases
fix: loading items by hand to the vending machine now respects the
max_amount for that category
fix: custom vendors can now actually be used by players who are not the
owner thus enabling them to transfer credits to the owner during
purchases & basically they do their job again
fix: custom vendors now show the correct icon for inserted items
fix: Items with different names & custom prices now show up in unique
rows in custom vendors
refactor: separated custom & normal vending machine code. Reduced UI
code & improved attack chain
/🆑
---------
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
## About The Pull Request
This PR makes it so the displayed station time in-world moves more
slowly, at a rate of 2x normal time. It has no effect on the speed of
the game itself, only the time displayed on clocks.
Mostly for lore reasons, so players aren't playing a 36-hour shift in
setting every time they play the game. Just something minor that always
bothered me.
This does mean Night Shifts are longer, though.
Includes upstream TG PRs 92428 and 92469.
## Why It's Good For The Game
Makes time more accessible for players by slowing it down. Now you can
set meetings for specific times in-game and have a rough idea of when
that will be!
## Proof Of Testing
Should just work out of the box. Compiles with no errors.
<details>
<summary>Screenshots/Videos</summary>
</details>
## Changelog
🆑 LT3, ReturnToZender
add: The displayed station time has been slowed down, making time more
consistent for players.
/🆑
---------
Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
## About The Pull Request
As the code currently is, if any missing limb is selected, command is
locked. This PR adjusts the logic so that command is locked only if both
arms are missing.
## Why It's Good For The Game
Disabled captains and other heads of staff offer more character creation
and roleplay opportunities. This change removes such logic discrepancies
such as a paraplegic captain being fine bug a legless captain being
disallowed. Crew with one hand are still very capable and do not need to
be blocked from command roles.
## Proof Of Testing
Code compiles with 0 errors, 0 warnings. Tested locally and working as
expected.
<details>
<summary>Screenshots/Videos</summary>
</details>
## Changelog
🆑
balance: Heads of staff are free to be missing as many roundstart limbs
as they want, as long as they have at least one hand.
/🆑
## About The Pull Request
Changes human name to update whenever anything that could result in
their visible name changing occurs, such as changing IDs, equipping
gasmasks, picking potted plants, etc. Currently name updates occur every
``Life()`` tick and in a few "special" cases, which causes a lot of name
changes from sources such as equipment to not apply until the mob ticks,
and makes us waste a tiiiny bit of CPU time on name updates.
I've also slighly cleaned up human /Life() and made species'
``spec_life()`` not run when the mob is dead, as it was causing certain
unintended interactions, such as slimepeople regenerating blood while
dead.
## Why It's Good For The Game
Microoptimization, ensures that correct names are always used (in case
something could update their name but the mob hasn't ticked yet), plus
its just a cleaner implementation
(cherry picked from commit 87e1ef6f64)
# Conflicts:
# code/game/data_huds.dm
## About The Pull Request
Fixes the issue of usr pointing to admins by making Trigger pass down
clicker, as usr is fucky and can be passed down by other unrelated
procs. Fun.
Added the clicker arg to all usages of Trigger as well
Also changes isobserver check in antagonist ui_act code that prevents
observers from clicking UI's instead to check if the ui.user is
owner.current
## Why It's Good For The Game
Fixes admins giving heretic to people opening the heretic UI for the
admin instead
(cherry picked from commit 0bc42d6940)
## About The Pull Request
Changes human name to update whenever anything that could result in
their visible name changing occurs, such as changing IDs, equipping
gasmasks, picking potted plants, etc. Currently name updates occur every
``Life()`` tick and in a few "special" cases, which causes a lot of name
changes from sources such as equipment to not apply until the mob ticks,
and makes us waste a tiiiny bit of CPU time on name updates.
I've also slighly cleaned up human /Life() and made species'
``spec_life()`` not run when the mob is dead, as it was causing certain
unintended interactions, such as slimepeople regenerating blood while
dead.
## Why It's Good For The Game
Microoptimization, ensures that correct names are always used (in case
something could update their name but the mob hasn't ticked yet), plus
its just a cleaner implementation
## About The Pull Request
Fixes the issue of usr pointing to admins by making Trigger pass down
clicker, as usr is fucky and can be passed down by other unrelated
procs. Fun.
Added the clicker arg to all usages of Trigger as well
Also changes isobserver check in antagonist ui_act code that prevents
observers from clicking UI's instead to check if the ui.user is
owner.current
## Why It's Good For The Game
Fixes admins giving heretic to people opening the heretic UI for the
admin instead
## About The Pull Request
Sorta-config related, replaced magic numbers in station time code with
defines and fixed station time calculations.
Constant time was (incorrectly) adjusted by your timezone in actual
station time calculations despite us changing all time ops to UTC+0, and
realtime was adjusted by your timezone in the wrong direction (realtime
returns GMT, and station time itself deducted your timezone again). Also
fixed station_time_debug debug proc using seconds instead of deciseconds
(by converting it to defines)
I've also made realtime config change time dilation factor from 12 to 1,
as its intended to make station time reflect real time *in the server's
own timezone*, and 12x time dilation made it deviate from that extremely
quickly (this does not affect gameplay in any meaningful manner, station
time dilation only affects displayed clock time and not any in-game
events except nightshifts)
- Closes#92380
## Changelog
🆑
fix: Fixed constant and realtime station time being calculated
incorrectly
/🆑
---------
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
## About The Pull Request
Sorta-config related, replaced magic numbers in station time code with
defines and fixed station time calculations.
Constant time was (incorrectly) adjusted by your timezone in actual
station time calculations despite us changing all time ops to UTC+0, and
realtime was adjusted by your timezone in the wrong direction (realtime
returns GMT, and station time itself deducted your timezone again). Also
fixed station_time_debug debug proc using seconds instead of deciseconds
(by converting it to defines)
I've also made realtime config change time dilation factor from 12 to 1,
as its intended to make station time reflect real time *in the server's
own timezone*, and 12x time dilation made it deviate from that extremely
quickly (this does not affect gameplay in any meaningful manner, station
time dilation only affects displayed clock time and not any in-game
events except nightshifts)
- Closes#92380
## Changelog
🆑
fix: Fixed constant and realtime station time being calculated
incorrectly
/🆑
---------
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
## About The Pull Request
Includes #92346
Additionally, fixes a non-pattern define that would fling the silo
logging formatting off its spinwheel when it would recursively jsonify
the logs.
Adds an id_read_failure for disassembling ore silos logging all their
dropped materials.
## Why It's Good For The Game
Hotfixes for a PR
## Changelog
🆑 Bisar
fix: Ore silos should be able to be connected/disconnected/disassembled
without any issues now.
fix: The define for CENTCOM_SPECOPS was incorrectly formatted; it has
been fixed.
/🆑
## About The Pull Request
# More robust logging
## Ore silo logs have now been refactored in the UI to display:
- Number of sheets is now the relative unit when displaying a given log.
- Instead of `100 iron` being displayed when removing one sheet, it just
says `1 iron`
- Instead of `25 iron` being displayed when using a quarter sheet, it
just says `0.25 iron`
- All information from ID_DATA(log_user) now sent to tgui backend
- The items rendered to ore silo users are:
- Name on ID, job on ID
- If the ID's bank account (if one is registered) is one of the ore
silo's banned users
- If the user for a given entry was wearing a chameleon card, they will
always appear unbanned
- NOTE: The bank account ID # is (currently) not shown to players using
the ore silo.
- Full log information is rendered within a dropdown; the dropdown
one-liner shows
- Action (deposit, eject, item created)
- Amount (deposit/eject? amount of material used. item created? number
of items created.)
- Either name of material (if deposit/eject) or the name of items
crafted
- The name of the user who performed a given operation (if wearing an
unbanned ID) or ID_READ_FAILURE (if ore silo ID requirement has been
disabled and the person is not wearing an ID)
- As name, but instead, the job of the ID (or ID_READ_FAILURE)

# Access control improvements
## Single-user bans
- Anyone with QM access (not silicons) can now ban/unban a user from a
given log from using the ore silo
- Bans are associated to bank account IDs.
- Wearers of chameleon cards bypass any ban restrictions.
- Anyone with QM access on their worn card bypasses ban restrictions.
- Silicons bypass ban restrictions.
- QM access requirement is removed if the ore silo is emagged.
- Silicons can ban/unban people if the ore silo is emagged.
## Worn ID requirement
- Enabled at roundstart, can be disabled by anyone with QM access (not
silicons)
- If enabled, you must be wearing an ID with a bank account associated
to it to use ore silo materials.
- Wearers of chameleon cards bypass this restriction (so-called ID
requirement free thinkers wearing chameleon ID cards)
- QM access requirement to toggle removed if emagged.
- Silicons can toggle this on/off if the ore silo is emagged.
# Access control radio notifications
## Access control operations reported on the radio
- Any operations for access control are reported on radio channels.
- Currently, the policy is always the default.
- In the future, the ore silo UI will allow the quartermaster to modify
what operations are reported on what channels (petty QM broadcasting ban
reports on Common)
- Current default policy:
- Reported on COMMON channel:
- Anyone but the Captain attempts to ban someone with QM access from the
ore silo (nice try dumbass)
- Ore silo ID requirement toggling
- Reported on COMMAND channel:
- Common channel reports.
- Per-user banning/unbanning.
- Anyone without QM access attempts to ban/unban someone.
- Anyone without QM access attempts to toggle the restriction for ID.
- Silicons attempting to tamper with the ID requirement restriction
- Silicons attempting to tamper with the ban/unbanned user list
- A ban attempt failing because a given log entry had a user with no
bank ID.
- Reported on SECURITY channel:
- Common channel reports.
- Per-user banning/unbanning.
- Anyone without QM access tampering with the silo.
- Reported on SUPPLY channel:
- Command channel reports.
- Reporting to the radio is disabled if the ore silo is emagged.
## Modifications to the remote_materials component
- Strictly encompass the behavior for connecting/disconnecting ore silos
to material receptacles (RCDs, machines, etc) into procs on the
component, instead of handling it all over the place
## Why It's Good For The Game
Gives people with ore silo access more fine grained control over ore
silo use without having to resort to heavy-handed fabricator lockouts
Makes the logging on the ore silo more robust so we can make sure we
kill the right Roboticist for using all the materials
Offers an avenue for sidestepping all of this with a chameleon card or
emag if a given traitor (organic or otherwise) is particularly opposed
to DRM mats.
https://github.com/user-attachments/assets/effd2c63-509c-4d33-992f-837a0d62b935
## Changelog
🆑 Bisar
add: The ore silo has had a significant expansion to its logging
capabilities.
add: The ore silo now allows any ID with Quartermaster access (NOT
SILICONS!) to ban/unban specific users from the silo.
add: The ore silo now has a toggle (on by default) that a user of ore
silo materials has an ID with an associated bank account. This can be
toggled by anyone with Quartermaster access (NOT SILICONS!)
add: NanoTrasen discounts any reports that Syndicate contraband
(cryptographic sequencer, agent card) can be used to circumvent any
protocols instituted on the ore silo access control routines.
add: The ore silo now announces operations to ban/unban users and
enable/disable ID requirements on radio channels (check the Github for
actions reported to what channels.)
add: The tgui interface for ore silo log entries has been reworked.
refactor: The code for logging a given access to ore silo materials has
been significantly refactored.
qol: Ore silo log entries now display materials spent in terms of sheets
rather than the obfuscated absolute-units previously display (1 iron
ejected instead of -100 iron, 0.25 used in a craft instead of -25 iron)
/🆑
## About The Pull Request
I made and metek improved this regex for finding instances if(itterator)
in for loops because a downstream im working on does it an insane
amount. Im fairly certin all these instaces have no reason to be running
if checks here saying most of the for loops are typed so if it was null
or something it shouldnt be iterated on
`for\s*\(var(/\w+)*/(\w+) .*\n\s+if\(\2\)`
## Why It's Good For The Game
just kinda bad practice. Its way way way worse on the downstream tho
holy shit
<img width="1264" height="759" alt="image"
src="https://github.com/user-attachments/assets/1d0f152d-372d-49d4-a9fa-6d8e4d27a816"
/>
## Changelog
N/A
## About The Pull Request
Includes #92346
Additionally, fixes a non-pattern define that would fling the silo
logging formatting off its spinwheel when it would recursively jsonify
the logs.
Adds an id_read_failure for disassembling ore silos logging all their
dropped materials.
## Why It's Good For The Game
Hotfixes for a PR
## Changelog
🆑 Bisar
fix: Ore silos should be able to be connected/disconnected/disassembled
without any issues now.
fix: The define for CENTCOM_SPECOPS was incorrectly formatted; it has
been fixed.
/🆑
## About The Pull Request
# More robust logging
## Ore silo logs have now been refactored in the UI to display:
- Number of sheets is now the relative unit when displaying a given log.
- Instead of `100 iron` being displayed when removing one sheet, it just
says `1 iron`
- Instead of `25 iron` being displayed when using a quarter sheet, it
just says `0.25 iron`
- All information from ID_DATA(log_user) now sent to tgui backend
- The items rendered to ore silo users are:
- Name on ID, job on ID
- If the ID's bank account (if one is registered) is one of the ore
silo's banned users
- If the user for a given entry was wearing a chameleon card, they will
always appear unbanned
- NOTE: The bank account ID # is (currently) not shown to players using
the ore silo.
- Full log information is rendered within a dropdown; the dropdown
one-liner shows
- Action (deposit, eject, item created)
- Amount (deposit/eject? amount of material used. item created? number
of items created.)
- Either name of material (if deposit/eject) or the name of items
crafted
- The name of the user who performed a given operation (if wearing an
unbanned ID) or ID_READ_FAILURE (if ore silo ID requirement has been
disabled and the person is not wearing an ID)
- As name, but instead, the job of the ID (or ID_READ_FAILURE)

# Access control improvements
## Single-user bans
- Anyone with QM access (not silicons) can now ban/unban a user from a
given log from using the ore silo
- Bans are associated to bank account IDs.
- Wearers of chameleon cards bypass any ban restrictions.
- Anyone with QM access on their worn card bypasses ban restrictions.
- Silicons bypass ban restrictions.
- QM access requirement is removed if the ore silo is emagged.
- Silicons can ban/unban people if the ore silo is emagged.
## Worn ID requirement
- Enabled at roundstart, can be disabled by anyone with QM access (not
silicons)
- If enabled, you must be wearing an ID with a bank account associated
to it to use ore silo materials.
- Wearers of chameleon cards bypass this restriction (so-called ID
requirement free thinkers wearing chameleon ID cards)
- QM access requirement to toggle removed if emagged.
- Silicons can toggle this on/off if the ore silo is emagged.
# Access control radio notifications
## Access control operations reported on the radio
- Any operations for access control are reported on radio channels.
- Currently, the policy is always the default.
- In the future, the ore silo UI will allow the quartermaster to modify
what operations are reported on what channels (petty QM broadcasting ban
reports on Common)
- Current default policy:
- Reported on COMMON channel:
- Anyone but the Captain attempts to ban someone with QM access from the
ore silo (nice try dumbass)
- Ore silo ID requirement toggling
- Reported on COMMAND channel:
- Common channel reports.
- Per-user banning/unbanning.
- Anyone without QM access attempts to ban/unban someone.
- Anyone without QM access attempts to toggle the restriction for ID.
- Silicons attempting to tamper with the ID requirement restriction
- Silicons attempting to tamper with the ban/unbanned user list
- A ban attempt failing because a given log entry had a user with no
bank ID.
- Reported on SECURITY channel:
- Common channel reports.
- Per-user banning/unbanning.
- Anyone without QM access tampering with the silo.
- Reported on SUPPLY channel:
- Command channel reports.
- Reporting to the radio is disabled if the ore silo is emagged.
## Modifications to the remote_materials component
- Strictly encompass the behavior for connecting/disconnecting ore silos
to material receptacles (RCDs, machines, etc) into procs on the
component, instead of handling it all over the place
## Why It's Good For The Game
Gives people with ore silo access more fine grained control over ore
silo use without having to resort to heavy-handed fabricator lockouts
Makes the logging on the ore silo more robust so we can make sure we
kill the right Roboticist for using all the materials
Offers an avenue for sidestepping all of this with a chameleon card or
emag if a given traitor (organic or otherwise) is particularly opposed
to DRM mats.
https://github.com/user-attachments/assets/effd2c63-509c-4d33-992f-837a0d62b935
## Changelog
🆑 Bisar
add: The ore silo has had a significant expansion to its logging
capabilities.
add: The ore silo now allows any ID with Quartermaster access (NOT
SILICONS!) to ban/unban specific users from the silo.
add: The ore silo now has a toggle (on by default) that a user of ore
silo materials has an ID with an associated bank account. This can be
toggled by anyone with Quartermaster access (NOT SILICONS!)
add: NanoTrasen discounts any reports that Syndicate contraband
(cryptographic sequencer, agent card) can be used to circumvent any
protocols instituted on the ore silo access control routines.
add: The ore silo now announces operations to ban/unban users and
enable/disable ID requirements on radio channels (check the Github for
actions reported to what channels.)
add: The tgui interface for ore silo log entries has been reworked.
refactor: The code for logging a given access to ore silo materials has
been significantly refactored.
qol: Ore silo log entries now display materials spent in terms of sheets
rather than the obfuscated absolute-units previously display (1 iron
ejected instead of -100 iron, 0.25 used in a craft instead of -25 iron)
/🆑
## About The Pull Request
I made and metek improved this regex for finding instances if(itterator)
in for loops because a downstream im working on does it an insane
amount. Im fairly certin all these instaces have no reason to be running
if checks here saying most of the for loops are typed so if it was null
or something it shouldnt be iterated on
`for\s*\(var(/\w+)*/(\w+) .*\n\s+if\(\2\)`
## Why It's Good For The Game
just kinda bad practice. Its way way way worse on the downstream tho
holy shit
<img width="1264" height="759" alt="image"
src="https://github.com/user-attachments/assets/1d0f152d-372d-49d4-a9fa-6d8e4d27a816"
/>
## Changelog
N/A
## About The Pull Request
Fixes#92125
Very simple, when working without an instantiated datum we would read
from the config manually, but some places neglected to do that.
So I added a macro to help in the future.
## Changelog
🆑 Melbert
fix: Fixes some places where dynamic configs were not being read
correctly
/🆑
## About The Pull Request
Moves all the dna block handling onto singleton datums initialized
inside global lists, to make the handling dna less of a copy-paste mess
and make adding new blocks significantly easier. There is still some
work to be done in the copypaste department but ultimately that falls
under its own PR scope after the core refactor goes through. (Ill
probably do those but it will also be easier for everyone else as the
code is now significantly less of an eyesore)
Both features and identities have been tested through and through, and
seem to be working fine.
Also removed the reliance on weird hardcoded lookup tables for length,
and other similar things that just didn't make sense when I was passing
through DNA code. There's a lot more that fall out of scope for this
exact PR's goal however
## Why It's Good For The Game
I've been told the maintainers will love me for doing this
## Changelog
🆑
code: feature keys are no longer magical strings floating around the
codebase and use proper defines
refactor: DNA blocks are now handled with singleton datums.
/🆑
## About The Pull Request
Fixes#92125
Very simple, when working without an instantiated datum we would read
from the config manually, but some places neglected to do that.
So I added a macro to help in the future.
## Changelog
🆑 Melbert
fix: Fixes some places where dynamic configs were not being read
correctly
/🆑

This PR adds "platforms" to the game, a port of the window frames from
the Wallening branch but with no windows attached.
You can craft them with two stacks of many kinds of materials.
Functionally they're basically just tables for standing on and act as a
decorative tool allowing you to make raised areas like stages.
Largely as far as I can tell I _think_ these were sprited by @Krysonism
although it's a little hard to check if there's any that were done by
someone else.
You can walk directly from tables to platforms (and crates) and vice
versa. You can also tableslam people onto them.
This PR also comes with "steps" (AKA small stairs)
You can use steps to walk onto platforms (or tables, or crates) without
needing to do the climbing action first.

If you try to run through them the wrong way you will trip.
Right now they only come in "Iron" flavour. Maybe one day someone will
sprite some wooden ones, or other varieties.
Basically the intention is to use them to build a little stage or altar
or maze or something. They don't have a lot of non-decorative purpose.
Don't be alarmed by the touched files list. It's mostly sprites and
there's barely even any code in this PR. It's almost entirely elements
and boilerplate.
Mappers keep asking me to add these.
Salvages some sprites from the Wallening project which we can still use.
You can make a really really big multitile pizza.
🆑 Jacquerel, Smartkar, sprites by Kryson
add: Added "platforms", or "half-walls" which are a kind of decorative
block similar to tables which you can walk around on.
add: You can walk freely between tables, platforms, and crates that
happen to be near tables or platforms.
add: You can construct iron steps to traverse tables and platforms
without needing to climb on, but try not to trip over them.
/🆑
---------
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
## About The Pull Request
The game will now log when someone signs up or removes their candidacy
for ghost polls for roles.
This also fixes a runtime I experienced while testing it and running
pirates with no candidates signed up, IDK if it had any effect but it's
possible the runtime was causing the ship not to spawn.
## Why It's Good For The Game
Mostly just that I saw admins requesting this on several recent
occasions.
It's already possible to dig up some of this information through the
existing logs but it's a bit of a pain.
## Changelog
🆑
admin: Additional logging for when people sign up for ghost roles.
/🆑
## About The Pull Request

This PR adds "platforms" to the game, a port of the window frames from
the Wallening branch but with no windows attached.
You can craft them with two stacks of many kinds of materials.
Functionally they're basically just tables for standing on and act as a
decorative tool allowing you to make raised areas like stages.
Largely as far as I can tell I _think_ these were sprited by @Krysonism
although it's a little hard to check if there's any that were done by
someone else.
You can walk directly from tables to platforms (and crates) and vice
versa. You can also tableslam people onto them.
This PR also comes with "steps" (AKA small stairs)
You can use steps to walk onto platforms (or tables, or crates) without
needing to do the climbing action first.

If you try to run through them the wrong way you will trip.
Right now they only come in "Iron" flavour. Maybe one day someone will
sprite some wooden ones, or other varieties.
Basically the intention is to use them to build a little stage or altar
or maze or something. They don't have a lot of non-decorative purpose.
Don't be alarmed by the touched files list. It's mostly sprites and
there's barely even any code in this PR. It's almost entirely elements
and boilerplate.
## Why It's Good For The Game
Mappers keep asking me to add these.
Salvages some sprites from the Wallening project which we can still use.
You can make a really really big multitile pizza.
## Changelog
🆑 Jacquerel, Smartkar, sprites by Kryson
add: Added "platforms", or "half-walls" which are a kind of decorative
block similar to tables which you can walk around on.
add: You can walk freely between tables, platforms, and crates that
happen to be near tables or platforms.
add: You can construct iron steps to traverse tables and platforms
without needing to climb on, but try not to trip over them.
/🆑
---------
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
## About The Pull Request
The game will now log when someone signs up or removes their candidacy
for ghost polls for roles.
This also fixes a runtime I experienced while testing it and running
pirates with no candidates signed up, IDK if it had any effect but it's
possible the runtime was causing the ship not to spawn.
## Why It's Good For The Game
Mostly just that I saw admins requesting this on several recent
occasions.
It's already possible to dig up some of this information through the
existing logs but it's a bit of a pain.
## Changelog
🆑
admin: Additional logging for when people sign up for ghost roles.
/🆑
Reworks the Voidwalker into a basic mob, including a lot of the balance
and mechanics!
Old (left), new (right)

https://github.com/user-attachments/assets/22d6138f-11aa-4f7a-8600-2565e6578bcf
(little outdated)
https://youtu.be/cp1E3qPJGX4 (high res mirror)
**🟨Voidwalker mob changes🟨**
No longer a human species and no more void eater. Instead deals damage
by simple unarmed attacks.
Instead of dealing brute, the voidwalker does oxygen damage (4-5 hits to
knock out) with left-click, and slight brute on right click. Non-human
mobs automatically take brute damage instead of oxygen damage.
150 HP
33% burn armor
Yes it has hands, but it can only pick up and drop stuff
**🟨Window phase🟨**

Instead of needing to smash a window with the void eater, moving through
windows simply leaves them passable for 5 seconds. Makes kidnapping a
lot easier, but also makes it easier for people to chase you
People who used the voided skull also leave windows passable for a short
bit.
**🟩Cosmic Charge🟩**
Standard charge ability, but only lets you charge towards space and
works while dragging people
**🟩The Vomitwalker🟩**
People you kidnapped now occasionally do the nebula vomit, which
voidwalkers can use to dive from and into

Diving into it is very fast but also removes the nebula vomit. You can
also kidnap people into the vomit (this doesn't remove the vomit).
There is also a little UI for tracking this. Clicking it while in space
dive teleports you to the next nebula vomit, if there are any.

**🟨Voided people changes🟨**
Kidnapped people and people that used the cosmic skull are no longer
muted, but take 10% extra brute and occasionally leave behind glass
shards when taking a lot of damage.
Are no longer obliterated on a second encounter with voidwalkers.
Voidwalkers can't hurt people they've already voided (unless they really
want to), but instead just knock them out for 30s
Also the kidnapped do space vomit as I said earlier.
**🟩Sunwalker🟩**
Voidwalker variant made for pure murderbone. Has no camo and kindap
mechanics, but has a fiery charge, loads of damage and area igniting and
people ignition. It's admin, but I might change this later once I've had
some more time to think about it.

Other changes:
- Voidwindows no longer need to be space adjacent
- Unsettle works faster but can't be used in combat anymore
- Space camo now grants complete space invisibility
- Makes a lot of aspects easily moddable, so we can easily mod it into a
moistwalker in-game
- Taking a cosmic skull when you already used one gives you the old
voidwalker void eater arm. Additional uses just gives you more void
eater arms until you run out of hands
- I definitely forgot a lot more
- I made a cool voidwalker hud! It even has a unique space camo toggle
<details>
<summary>Lot of text</summary>
Voidwalker was basically a snowflaked toghether human species because I
didn't know how to sprite, but I was able to work with species and
visual effects. Then I realized I can just commission sprites!
This also let me just cut out a lot of the snowflake code, because it's
no longer a human so half the things I didn't want them to be able to
do, they just literally cannot do.
Voidwalkers were in a bit of strange spot with kidnapping? There was
essentially no incentive, other than "smash spaceman = funny". They also
had issues doing, anything? There's surprisingly little space on a space
station, especially maps such as tram. Making the voided victims have
nebula vomit gives the voidwalker a reason to WANT to kidnap, by giving
them a way to appear basically anywhere on the station. I don't think
it's too overpowered. Voided people don't vomit that much, it's easily
cleanable and diving into it removes them, so they're limited usability.
Replacing the brute damage with oxygen damage also kinda... just makes
sense? I seriously contemplated letting them do stamina damage for the
first iteration, but opted not to do it because stamina damage has so
many hooks attached. Oxygen damage doesn't! It's also just incredibly
thematic, let's them bypass most armor and makes them more suited to
non-letha kidnappings.
Space camo making them completely invisible was also long overdue. It
was literally just urging people to turn up their gamma and turn down
their parallax settings. I thought it was an interesting mechanic, but
it's just straight up unfair and doesn't belong in a multiplayer game.
They now more frequently leave behind little glass shards, leave
particles from nebula vomit they leave from and have more unique sound
effects, so attentive (and lucky) people can still deduce if an area is
safe-ish.
I removed being able to shatter voided people because the mechanic was
deeply misunderstood. It was intended to give them a means of removing
people if they kept incessently bothering the voidwalker, but people
went out of their way to use this to roundremove people they had already
voided. The 30s sleep conveys my intention a lot better, and fits better
now that the voidwalker benefits from having as many voided people
vomitting all over the place.
The cosmic charge gives them some much needed survivability. My
experiences (in observing voidwalkers, I can never get the roll ;_;) is
that they're constantly one mistake away from complete obliteration. The
cosmic charge let's them get out quick despite their slow movement speed
in gravity. It also makes them stronger when fighting in space.
They got 33% burn armor so it's a tiny bit harder to wipe them away in a
single laser salvo, while still giving people ample opportunity to fight
them off . Also they're like glass or something so it fits thematically.
I gave them hands because I thought it was cool, might be a mistake idk
</details>
🆑 Time-Green, INFRARED_BACON
add: Voidwalker has been throughly reworked! Now you are even less safe!
admin: Adds admin-only Sunwalker mob
fix: Unsettle doesnt work on yourself anymore
fix: Space camo doesnt stop bobbing anymore
fix: Voidwalker windows now recharge on kidnap
runtime: Fixes healthanalyzers runtiming when scanning mobs without
reagent holders
/🆑
## About The Pull Request
Fixes#91882
`RULESET_HIGH_IMPACT` is checked in `get_weight`, but by the time
`get_weight` is called for roundstart rulesets, no rulesets are
selected.
So we need to add logic in `pick_roundstart_rulesets`
Not super big fan of this fix - I think it'd be a lot cleaner if all the
rulesets recalculated their weights, but this is a needed temp fix.
## Changelog
🆑 Melbert
fix: Multiple high impact rulesets will no longer roll simultaneously
unless dynamic picks "high chaos"
/🆑
## About The Pull Request
Quirks only send their on_gain text when given midround, such as by an
admin
## Why It's Good For The Game
Spams the hell out of you for no reason - in very few contexts are these
messages important (randomized allergies come to mind), but there are
other avenues to figure out (such as dogtags)

## Changelog
🆑 Melbert
qol: Quirks spam you less on roundstart or latejoin
/🆑
## About The Pull Request
Ok there's a lot here, sorry bout that.
- Cleaned up the permissions panel backend pretty signficantly
- Added some extra security measures to said code, mostly proc call
checks
- Properly implemented filtering code jordie wrote years and years ago
for permissions logs
- Cleaned up the permissions ui generally, more bars, nicer lookin
stuff, etc
- Fixed the Management panel's relationship with combined roles, and
renamed it to Housekeeping. Its display is expanded too.
- Added tracking to rank datums on where exactly they came from
- Added a new tab to the permissions panel which allows the modification
and deletion of ranks
- Beefed up rank modification to try and avoid accidential temp rank
additions to the db
I'm doing my best to avoid perms escalation issues, tho they are always
possible right.
Also, got mad at some query cleanup handling, did a pass on it. this
isn't nearly all of em, but it's some.
## Why It's Good For The Game
I realized there is no way to, in game, cleanly edit/create ranks, and
that the way the existing system worked was quite opaque.
I'm trying to fix that here. It does mean potentially opening up DB rank
deletion/modification to bad actors, but frankly I am not overly worried
about that. Admin modification has always been a vulnerability so like.
Here's a video with my changes (mostly, it's lightly outdated)
https://file.house/XqME7KWKk0ULj4ZUkJ5reg==.mp4
## Changelog
🆑
refactor: Fucked with admin rank setup very slightly, please yell at me
if anything is wrong.
admin: Updated the permissions panel to be a good bit more user
friendly, added rank management support to it.
server: I've added code that gives the game modification/deletion perms
for the rank table, be made aware.
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
## About The Pull Request
inspired by https://github.com/tgstation/tgstation/pull/85407
we initialize a global assoc list in SSsounds named sfx_datum_by_key,
with k = SFX_KEY, v = ref to the singleton sound_effect datum, then we
can call return_sfx on the referenced datum to get an sfx
## Why It's Good For The Game
makes the code a bit easier to add onto and work with
## Changelog
🆑
refactor: refactored how sfx with multiple variants are coded, report
any issues with sounds not playing!
/🆑
## About The Pull Request
Implements ranked choice voting for storyteller and map vote
## Why It's Good For The Game
I can close the secret storyteller PR
## Changelog
🆑 LT3
qol: Ranked choice voting is now available for storyteller and map votes
/🆑
## About The Pull Request
Reworks the Voidwalker into a basic mob, including a lot of the balance
and mechanics!
Old (left), new (right)

https://github.com/user-attachments/assets/22d6138f-11aa-4f7a-8600-2565e6578bcf
(little outdated)
https://youtu.be/cp1E3qPJGX4 (high res mirror)
**🟨Voidwalker mob changes🟨**
No longer a human species and no more void eater. Instead deals damage
by simple unarmed attacks.
Instead of dealing brute, the voidwalker does oxygen damage (4-5 hits to
knock out) with left-click, and slight brute on right click. Non-human
mobs automatically take brute damage instead of oxygen damage.
150 HP
33% burn armor
Yes it has hands, but it can only pick up and drop stuff
**🟨Window phase🟨**

Instead of needing to smash a window with the void eater, moving through
windows simply leaves them passable for 5 seconds. Makes kidnapping a
lot easier, but also makes it easier for people to chase you
People who used the voided skull also leave windows passable for a short
bit.
**🟩Cosmic Charge🟩**
Standard charge ability, but only lets you charge towards space and
works while dragging people
**🟩The Vomitwalker🟩**
People you kidnapped now occasionally do the nebula vomit, which
voidwalkers can use to dive from and into

Diving into it is very fast but also removes the nebula vomit. You can
also kidnap people into the vomit (this doesn't remove the vomit).
There is also a little UI for tracking this. Clicking it while in space
dive teleports you to the next nebula vomit, if there are any.

**🟨Voided people changes🟨**
Kidnapped people and people that used the cosmic skull are no longer
muted, but take 10% extra brute and occasionally leave behind glass
shards when taking a lot of damage.
Are no longer obliterated on a second encounter with voidwalkers.
Voidwalkers can't hurt people they've already voided (unless they really
want to), but instead just knock them out for 30s
Also the kidnapped do space vomit as I said earlier.
**🟩Sunwalker🟩**
Voidwalker variant made for pure murderbone. Has no camo and kindap
mechanics, but has a fiery charge, loads of damage and area igniting and
people ignition. It's admin, but I might change this later once I've had
some more time to think about it.

Other changes:
- Voidwindows no longer need to be space adjacent
- Unsettle works faster but can't be used in combat anymore
- Space camo now grants complete space invisibility
- Makes a lot of aspects easily moddable, so we can easily mod it into a
moistwalker in-game
- Taking a cosmic skull when you already used one gives you the old
voidwalker void eater arm. Additional uses just gives you more void
eater arms until you run out of hands
- I definitely forgot a lot more
- I made a cool voidwalker hud! It even has a unique space camo toggle
## Why It's Good For The Game
<details>
<summary>Lot of text</summary>
Voidwalker was basically a snowflaked toghether human species because I
didn't know how to sprite, but I was able to work with species and
visual effects. Then I realized I can just commission sprites!
This also let me just cut out a lot of the snowflake code, because it's
no longer a human so half the things I didn't want them to be able to
do, they just literally cannot do.
Voidwalkers were in a bit of strange spot with kidnapping? There was
essentially no incentive, other than "smash spaceman = funny". They also
had issues doing, anything? There's surprisingly little space on a space
station, especially maps such as tram. Making the voided victims have
nebula vomit gives the voidwalker a reason to WANT to kidnap, by giving
them a way to appear basically anywhere on the station. I don't think
it's too overpowered. Voided people don't vomit that much, it's easily
cleanable and diving into it removes them, so they're limited usability.
Replacing the brute damage with oxygen damage also kinda... just makes
sense? I seriously contemplated letting them do stamina damage for the
first iteration, but opted not to do it because stamina damage has so
many hooks attached. Oxygen damage doesn't! It's also just incredibly
thematic, let's them bypass most armor and makes them more suited to
non-letha kidnappings.
Space camo making them completely invisible was also long overdue. It
was literally just urging people to turn up their gamma and turn down
their parallax settings. I thought it was an interesting mechanic, but
it's just straight up unfair and doesn't belong in a multiplayer game.
They now more frequently leave behind little glass shards, leave
particles from nebula vomit they leave from and have more unique sound
effects, so attentive (and lucky) people can still deduce if an area is
safe-ish.
I removed being able to shatter voided people because the mechanic was
deeply misunderstood. It was intended to give them a means of removing
people if they kept incessently bothering the voidwalker, but people
went out of their way to use this to roundremove people they had already
voided. The 30s sleep conveys my intention a lot better, and fits better
now that the voidwalker benefits from having as many voided people
vomitting all over the place.
The cosmic charge gives them some much needed survivability. My
experiences (in observing voidwalkers, I can never get the roll ;_;) is
that they're constantly one mistake away from complete obliteration. The
cosmic charge let's them get out quick despite their slow movement speed
in gravity. It also makes them stronger when fighting in space.
They got 33% burn armor so it's a tiny bit harder to wipe them away in a
single laser salvo, while still giving people ample opportunity to fight
them off . Also they're like glass or something so it fits thematically.
I gave them hands because I thought it was cool, might be a mistake idk
</details>
## Changelog
🆑 Time-Green, INFRARED_BACON
add: Voidwalker has been throughly reworked! Now you are even less safe!
admin: Adds admin-only Sunwalker mob
fix: Unsettle doesnt work on yourself anymore
fix: Space camo doesnt stop bobbing anymore
fix: Voidwalker windows now recharge on kidnap
runtime: Fixes healthanalyzers runtiming when scanning mobs without
reagent holders
/🆑
## About The Pull Request
Fixes#91882
`RULESET_HIGH_IMPACT` is checked in `get_weight`, but by the time
`get_weight` is called for roundstart rulesets, no rulesets are
selected.
So we need to add logic in `pick_roundstart_rulesets`
Not super big fan of this fix - I think it'd be a lot cleaner if all the
rulesets recalculated their weights, but this is a needed temp fix.
## Changelog
🆑 Melbert
fix: Multiple high impact rulesets will no longer roll simultaneously
unless dynamic picks "high chaos"
/🆑
## About The Pull Request
Quirks only send their on_gain text when given midround, such as by an
admin
## Why It's Good For The Game
Spams the hell out of you for no reason - in very few contexts are these
messages important (randomized allergies come to mind), but there are
other avenues to figure out (such as dogtags)

## Changelog
🆑 Melbert
qol: Quirks spam you less on roundstart or latejoin
/🆑
## About The Pull Request
Ok there's a lot here, sorry bout that.
- Cleaned up the permissions panel backend pretty signficantly
- Added some extra security measures to said code, mostly proc call
checks
- Properly implemented filtering code jordie wrote years and years ago
for permissions logs
- Cleaned up the permissions ui generally, more bars, nicer lookin
stuff, etc
- Fixed the Management panel's relationship with combined roles, and
renamed it to Housekeeping. Its display is expanded too.
- Added tracking to rank datums on where exactly they came from
- Added a new tab to the permissions panel which allows the modification
and deletion of ranks
- Beefed up rank modification to try and avoid accidential temp rank
additions to the db
I'm doing my best to avoid perms escalation issues, tho they are always
possible right.
Also, got mad at some query cleanup handling, did a pass on it. this
isn't nearly all of em, but it's some.
## Why It's Good For The Game
I realized there is no way to, in game, cleanly edit/create ranks, and
that the way the existing system worked was quite opaque.
I'm trying to fix that here. It does mean potentially opening up DB rank
deletion/modification to bad actors, but frankly I am not overly worried
about that. Admin modification has always been a vulnerability so like.
Here's a video with my changes (mostly, it's lightly outdated)
https://file.house/XqME7KWKk0ULj4ZUkJ5reg==.mp4
## Changelog
🆑
refactor: Fucked with admin rank setup very slightly, please yell at me
if anything is wrong.
admin: Updated the permissions panel to be a good bit more user
friendly, added rank management support to it.
server: I've added code that gives the game modification/deletion perms
for the rank table, be made aware.
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
## About The Pull Request
inspired by https://github.com/tgstation/tgstation/pull/85407
we initialize a global assoc list in SSsounds named sfx_datum_by_key,
with k = SFX_KEY, v = ref to the singleton sound_effect datum, then we
can call return_sfx on the referenced datum to get an sfx
## Why It's Good For The Game
makes the code a bit easier to add onto and work with
## Changelog
🆑
refactor: refactored how sfx with multiple variants are coded, report
any issues with sounds not playing!
/🆑
## About The Pull Request
1. Mail is now shipped every 2 SSeconomy ticks, rather than every
SSeconomy ticks. The amount of mail per round will not change.
2. Mail is not shipped during Red or Delta alert. Mail will still
continue to pile up for if the station returns to blue alert.
## Why It's Good For The Game
1. The time between cargo shipments is like five minutes. This means you
get mail practically every cargo shipment, if only a few pieces. I think
it's a bit spammy, so doubling time between shipments means you actually
get substantial shipments of mail and you don't have to pay attention to
mail constantly.
2. In the event of an emergency and the cargo shuttle has to fly back
and forth for emergency supplies (like guns for a blob), being blocked
because of mail is annoying. It's also reasonable from an in character
perspective that they would hold your mail until the emergency is
resolved.
## Changelog
🆑 Melbert
qol: Mail is now shipped every 10 minutes rather than every 5 minutes.
The amount of mail remains unchanged (so you get 1 crate with 6 mail
instead of 2 crates with 3 mail each).
qol: Mail is no longer shipped while the station is on red alert - mail
held will be sent if the station returns to blue alert.
/🆑
(cherry picked from commit 0675ddf6cb)