## About The Pull Request
This PR adds the ability to install a B.O.R.I.S. in a circuit that
contains an MMI component. These circuits can then be remotely connected
to by an AI by clicking on them or anything they are inside of. To
indicate that a circuit allows remote AI connection, an indicator is
given to the circuit and anything containing it.
Additionally:
- Refactors the MMI component to use `item_interaction`, since it was
pertinent.
- You cannot insert an MMI/B.O.R.I.S. into a locked circuit.
- You can no longer hotswap MMIs/B.O.R.I.S.es - you must manually eject
the inserted one.
Let me know what changelog labels I should use for the hotswap removal
and the prevention of insertion into locked circuits.
## Why It's Good For The Game
If you can put an MMI or posibrain in a circuit, why not allow an AI to
use it using a B.O.R.I.S.?
## Changelog
🆑
add: B.O.R.I.S.es can be installed inside of integrated circuits with
MMI components, allowing an AI to remotely interface with them the same
way an MMI or posibrain could.
refactor: The MMI component now uses item interaction behavior for
inserting MMIs/B.O.R.I.S.es.
/🆑
---------
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
## About The Pull Request
someone forgot to actually subtype these items
## Why It's Good For The Game
i tried to go to the definition of eyepatches and got brought here. it
hasnt been an issue because of this being earlier in the load order.
## About The Pull Request
Fixes#92463
## Why It's Good For The Game
- Fixes an exploit to take loot out of the Virtual Domain via build a
shuttle.
- Explicitly prevents people taking items into the Virtual Domain.
## 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
- Closes#92210
1) Bit Forge can be deconstructed with a screwdriver & crowbar like a
normal machine
2) Adds examines & screentips for netpod, bitforge(icon for panel open
state added) & quantum server on how to deconstruct them. New icon state
for when bitforge has its panel open is shown below
<img width="210" height="103" alt="Screenshot (497)"
src="https://github.com/user-attachments/assets/bb44c78d-1f0e-468f-9a79-ebc5800edd09"
/>
3) Moved bitrunning machine designs into files that exist to hold that
type of code
## Changelog
🆑
code: moved designs & circuitboards for bitrunning into their correct
files
qol: adds examines & screentips for bitrunning netpod, bitforge & server
on how to deconstruct them
fix: bitforge can be deconstructed with a screwdriver & crowbar
/🆑
## About The Pull Request
<img width="378" height="199" alt="1eSxYbsh0e"
src="https://github.com/user-attachments/assets/e8a658ca-c1c4-48fe-bb51-c77c85a7f824"
/>
Noticed some hard dels here, does some light refactoring/code
improvement to ensure that doesn't happen.
Crates shouldn't really be owning a hard ref to the manifest in the
first place since they are detachable. Removes some code duplication in
favor of calling `tear_manifest()` which has the safety check to prevent
`forceMove()`ing a qdeleted manifest out of nullspace.
## Why It's Good For The Game
Less server hiccups.
## Changelog
Nothing players will notice besides less server hiccups.
## About The Pull Request
Simple enough. This domain used just plain ghost spawners from the
lavaland ruin previously.
Now, it has `temp_body = TRUE`, allowing ghosts to return to their
original body after leaving the domain
_Alongside this it has unique little descriptions to cement it as NPC
actors_
This also adds a new `antag` variable to virtual_domain spawners, which
decides if they get the hunt-bitrunners antag datum _(default True, in
this case False)_
<h5>I did notice a few bugs while testing this, namely that temp_body
doesn't always work? I'm not coder enough to hunt down why and fix it
though... the two cases I noticed will be made into a bug report.</h5>
## Why It's Good For The Game
It feels weird that there's this temp_body ghost spawner stuff for
bitdomains, but it's not used in **all** the bitdomains. They don't last
that long, making them permanently kill old bodies feels odd.
This also sets up an easy var for other bit ghostroles to use if they
aren't explicitly antags hunting bitrunners, and don't need an antag
datum.
<img width="853" height="449" alt="image"
src="https://github.com/user-attachments/assets/d5761ac1-25bd-4ee5-b281-14fe4392479e"
/>
## Changelog
🆑
qol: made the Beach Bar bitdomain ghostrole spawners keep your old body
revivable (as other bitdomain spawners do)
/🆑
## About The Pull Request
Implements https://hackmd.io/@tgstation/SkeUS7lSp , rewriting Dynamic
from the ground-up
- Dynamic configuration is now vastly streamlined, making it far far far
easier to understand and edit
- Threat is gone entirely; round chaos is now determined by dynamic
tiers
- There's 5 dynamic tiers, 0 to 4.
- 0 is a pure greenshift.
- Tiers are just picked via weight - "16% chance of getting a high chaos
round".
- Tiers have min pop ranges. "Tier 4 (high chaos) requires 25 pop to be
selected".
- Tier determines how much of every ruleset is picked. "Tier 4 (High
Chaos) will pick 3-4 roundstart[1], 1-2 light, 1-2 heavy, and 2-3
latejoins".
- The number of rulesets picked depends on how many people are in the
server - this is also configurable[2]. As an example, a tier that
demands "1-3" rulesets will not spawn 3 rulesets if population <= 40 and
will not spawn 2 rulesets if population <= 25.
- Tiers also determine time before light, heavy, and latejoin rulesets
are picked, as well as the cooldown range between spawns. More chaotic
tiers may send midrounds sooner or wait less time between sending them.
- On the ruleset side of things, "requirements", "scaling", and
"enemies" is gone.
- You can configure a ruleset's min pop and weight flat, or per tier.
- For example a ruleset like Obsession is weighted higher for tiers 1-2
and lower for tiers 3-4.
- Rather than scaling up, roundstart rulesets can just be selected
multiple times.
- Rulesets also have `min_antag_cap` and `max_antag_cap`.
`min_antag_cap` determines how many candidates are needed for it to run,
and `max_antag_cap` determines how many candidates are selected.
- Rulesets attempt to run every 2.5 minutes. [3]
- Light rulesets will ALWAYS be picked before heavy rulesets. [4]
- Light injection chance is no longer 100%, heavy injection chance
formula has been simplified.
- Chance simply scales based on number of dead players / total number
off players, with a flag 50% chance if no antags exist. [5]
[1] This does not guarantee you will actually GET 3-4 roundstart
rulesets. If a roundstart ruleset is picked, and it ends up being unable
to execute (such as "not enough candidates", that slot is effectively a
wash.) This might be revisited.
[2] Currently, this is a hard limit - below X pop, you WILL get a
quarter or a half of the rulesets. This might be revisited to just be
weighted - you are just MORE LIKELY to get a quarter or a half.
[3] Little worried about accidentally frontloading everything so we'll
see about this
[4] This may be revisited but in most contexts it seems sensible.
[5] This may also be revisited, I'm not 100% sure what the best / most
simple way to tackle midround chances is.
Other implementation details
- The process of making rulesets has been streamlined as well. Many
rulesets only amount to a definition and `assign_role`.
- Dynamic.json -> Dynamic.toml
- Dynamic event hijacked was ripped out entirely.
- Most midround antag random events are now dynamic rulesets. Fugitives,
Morphs, Slaughter Demons, etc.
- The 1 weight slaughter demon event is gone. RIP in peace.
- There is now a hidden midround event that simply adds +1 latejoin, +1
light, or +1 heavy ruleset.
- `mind.special_role` is dead. Minds have a lazylist of special roles
now but it's essentially only used for traitor panel.
- Revs refactored almost entirely. Revs can now exist without a dynamic
ruleset.
- Cult refactored a tiny bit.
- Antag datums cleaned up.
- Pre round setup is less centralized on Dynamic.
- Admins have a whole panel for interfacing with dynamic. It's pretty
slapdash I'm sure someone could make a nicer looking one.


- Maybe some other things.
## Why It's Good For The Game
See readme for more info.
Will you see a massive change in how rounds play out? My hunch says
rounds will spawn less rulesets on average, but it's ultimately to how
it's configured
## Changelog
🆑 Melbert
refactor: Dynamic rewritten entirely, report any strange rounds
config: Dynamic config reworked, it's now a TOML file
refactor: Refactored antag roles somewhat, report any oddities
refactor: Refactored Revolution entirely, report any oddities
del: Deleted most midround events that spawn antags - they use dynamic
rulesets now
add: Dynamic rulesets can now be false alarms
add: Adds a random event that gives dynamic the ability to run another
ruleset later
admin: Adds a panel for messing around with dynamic
admin: Adds a panel for chance for every dynamic ruleset to be selected
admin: You can spawn revs without using dynamic now
fix: Nuke team leaders get their fun title back
/🆑
## About The Pull Request
Alleviates #91603
As in it does not fix it because i have not been able to reproduce it.
It now checks for invalid values and defaults to `amount`(which is 1)
during `Initialize()` and not null so we don't have to pass the number
`1` when creating a single sheet.
A stack trace is thrown for <= 0 sheet amounts so we can debug & fix
stuff
## Changelog
🆑
code: stacks error on invalid amounts, removed manual passing of number
`1` when creating a single stack in many cases
/🆑
## About The Pull Request
-# so help me space jesus if this doesn't compile despite working fine
on my local machine
Makes burdened chaplain and psyker pirates not blind, so that someone
playing them isnt assaulted by irregularly flashing monochromatic lights
on a black background. Instead the echolocation outlines will simply
pulse to highlight nearby objects regardless of lighting conditions or
other vision obscuring effects. adds support for if you want
psykerization to blind people or not.
keeps bitrunner psykers blind, since that's the point of the domain.
Just avoid those domains if you can't handle the effect, sorry.
## Why It's Good For The Game
A. It makes psyker an actual useful ability. I have personally seen, as
a ghost, psyker pirates fail to navigate out of their ship for a full
five minutes, and then die horribly because they are unable to actually
do anything because they're **Worse than blinded** since blindness has a
small radius of working vision.
B. In-game effects should not cause **real world eye pain and nausea**
thank you very much.
neat fact: blind seers only really work when the seer-ing makes up for
the blindness.
example of outline highlighting hidden underfloor objects (like that
satchel!) while user is not horribly blinded

## Changelog
🆑
fix: blind psykers are not blinded twice by two different sources, head
and brain.
qol: Psyker bounty hunters and chaplains are no longer blinded by
default, so as to reduce the amount of eye strain from the echolocation
effect. The echolocation virtual domains remain as they are.
/🆑
---------
Co-authored-by: ThrowawayUseless <notarealemail@emailservice.fake>
## About The Pull Request
Adds support for PVP bitrunning domains. If min/max candidates are set
above 0, the virtual domain will search for any ghost spawners inside
and cause a randomly-selected ghost that signed up via poll to spawn
there. If no ghosts are signed up the process is cancelled.
Also adds content for them:
An outfit wardrobe that lets you select one of several possible outfits,
once.

Not confident in my code, it's been in the works (as part of a
now-canned library heretic domain thing) for over a year
## Why It's Good For The Game
PvP domains are an underexplored concept. The beach domain is cloying
and overly simple. This adds support for newer and cooler domains as
long as there are ghosts for them.
## Changelog
🆑
code: Adds support for PVP Bitrunning Domains
/🆑
## About The Pull Request
This replaces the hardcoded atmos strings for these turfs with the
actual icebox atmos defines.
## Why It's Good For The Game
Hardcoding values is bad.
## About The Pull Request
Revival of https://github.com/tgstation/tgstation/pull/86482, which is
even more doable now that we have rustg iconforge generation.
What this PR does:
- Sets up every single GAGS icon in the game to have their own preview
icon autogenerated during compile. This is configurable to not run
during live. The icons are created in `icons/map_icons/..`
- This also has the side effect of providing accurate GAGS icons for
things like the loadout menu. No more having to create your own
previews.

<details><summary>Mappers rejoice!</summary>


</details>
<details><summary>Uses iconforge so it does not take up much time during
init</summary>

</details>
---
### Copied from https://github.com/tgstation/tgstation/pull/86482 as
this still applies:
Note for Spriters:
After you've assigned the correct values to vars, you must run the game
through init on your local machine and commit the changes to the map
icon dmi files. Unit tests should catch all cases of forgetting to
assign the correct vars, or not running through init.
Note for Server Operators:
In order to not generate these icons on live I've added a new config
entry which should be disabled on live called GENERATE_ASSETS_IN_INIT in
the config.txt
## Why It's Good For The Game
No more error icons in SDMM and loadout.
## Changelog
🆑
refactor: preview icons for greyscale items are now automatically
generated, meaning you can see GAGS as they actually appear ingame while
mapping or viewing the loadout menu.
/🆑
---------
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
## About The Pull Request
Melee attack chain now has a list passed along with it,
`attack_modifiers`, which you can stick force modifiers to change the
resulting attack
This is basically a soft implementation of damage packets until a more
definitive pr, but one that only applies to item attack chain, and not
unarmed attacks.
This change was done to facilitate a baton refactor - batons no longer
hack together their own attack chain, and are now integrated straight
into the real attack chain. This refactor itself was done because batons
don't send any attack signals, which has been annoying in the past (for
swing combat).
## Changelog
🆑 Melbert
refactor: Batons have been refactored again. Baton stuns now properly
count as an attack, when before it was a nothing. Report any oddities,
particularly in regards to harmbatonning vs normal batonning.
refactor: The method of adjusting item damage mid-attack has been
refactored - some affected items include the Nullblade and knives.
Report any strange happenings with damage numbers.
refactor: A few objects have been moved to the new interaction chain -
records consoles, mawed crucible, alien weeds and space vines, hedges,
restaurant portals, and some mobs - to name a few.
fix: Spears only deal bonus damage against secure lockers, not all
closet types (including crates)
/🆑
## About The Pull Request
- Address
https://github.com/tgstation/tgstation/pull/90476#discussion_r2051701283.
Makes pill bottle code cleaner
- Datumized some more storage values(monkey guncase toolbox & crafter
toolbox) making their init slightly faster
- Moved all standard storage subtypes(bags, boxes, lockboxes etc) that
is scattered across various files & folders in the codebase into their
respective files under `code/game/objects/item/storage` folder.
This means for e.g. if you want to see all boxes in the game you can
find them in `code/game/objects/item/storage/boxes` folder & don't have
to go looking for hidden subtypes in various module files or folders
where they were hidden away.
Makes looking for stuff & modifying these storages much saner & easier
## Changelog
🆑
code: organized storage subtypes under the same files & folders
/🆑
---------
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
## About The Pull Request
This prevents the Grassland Hunt VDOM from auto-completing when the
domain is shut down.
This is because the target mobs are "killed" as the map unloads, and
those kills would count towards the domain's win condition. Now, mobs
just qdel wholesale when the domain unloads. No death, no funeral.
This ALSO happened because, on the Grassland Hunt domain, the crate
point beacon was located directly over the delivery zone. This means
that, as the map unloaded, it would dust (kill) the target mobs until
the crate spawned in the safehouse (basically the last area to unload),
"winning" the domain as it unloads. Now, the beacon has been moved to
directly outside the safehouse.
I wasn't sure how to handle this so I went with both solutions at the
same time.
## Why It's Good For The Game
Bitrunning isn't a lot of work, but starting and stopping the domain is
a bit too easy to warrant a reward.
## Changelog
🆑 Rhials
fix: The grassland hunt domain no longer auto-completes just by closing
the domain.
/🆑
## About The Pull Request
People can now pet held mothroaches and pugs if they want to, or use
items on them, hopefully without causing many issues. After all, it only
took about a couple dozen lines of code to make...
...Oh, did the 527 files changed or the 850~ lines added/removed perhaps
catch your eye? Made you wonder if I accidentally pushed the wrong
branch? or skewed something up big time? Well, nuh uh. I just happen to
be fed up with the melee attack chain still using stringized params
instead of an array/list. It was frankly revolting to see how I'd have
had to otherwise call `list2params` for what I'm trying to accomplish
here, and make this PR another tessera to the immense stupidity of our
attack chain procs calling `params2list` over and over and over instead
of just using that one call instance from `ClickOn` as an argument. It's
2025, honey, wake up!
I also tried to replace some of those single letter vars/args but there
are just way too many of them.
## Why It's Good For The Game
Improving old code. And I want to be able to pet mobroaches while
holding them too.
## Changelog
🆑
qol: You can now interact with held mobs in more ways beside wearing
them.
/🆑
## About The Pull Request
Reverts the storage initialization refactor and all subsequent related
PRs.
The original PR is below our standards both for code quality and
testing, and is majorly flawed at its core. This has been discussed with
other maintainers and headcoder(s?) over on discord. A lot of changes
from the PR could be brought over later, but in its current state it
should not have been merged.
- Closes#90322
- Closes#90313
- Closes#90315
- Closes#90320
- Closes#90312
- Closes#90344
## Why It's Good For The Game
This PR causes a series of major issues which cannot be resolved without
either completely rewriting a lot of the original PR, or bad code.
Not matching our standards is grounds for not merging a PR, and the fact
that a PR should not have been merged is a reason for a revert.
## Changelog
🆑
fix: Fixed a series of storage-related bugs caused by a refactor PR.
/🆑
## About The Pull Request
Blacklists dumpster, hide, random toys, contraband and random medical
equipment crates from the cargo_crate_sanity unit test. These crates are
innately random, and while we have to be aware of potentially having
their average be over their price, we cannot (sanely) test for that
(without spawning a thousand crates, and even then we're affected by
random). The whole point of these crates is gambling on their value.
Closes#90328Closes#90314Closes#90298Closes#90253Closes#90216Closes#90181Closes#90178
## Changelog
Not player facing
## About The Pull Request
this fixes a bunch of code incorrectly calling qdel directly on a list,
and adds a stack trace to qdel if someone does pass a list to it
## Why It's Good For The Game
because I'm pretty sure qdel ends up calling fucking `del()` as `/list`
is not a `/datum`
## Changelog
No user-facing changes.
## About The Pull Request
MODsuits now calculate their slowdown by querying modules by sending a
signal on themselves instead of having modules try and keep up with
control unit's speed updates (which broke in a fabulous fashion after
MODsuits were allowed to deploy by piece)
Also added a separate trait to prevent objects from being speed
potion-ed to combat stabilized red crossbreed issues, and removed a
duplicate list helper (40 lines down in the same file lol)
Closes#89979Closes#90036
## Changelog
🆑
fix: MODsuits should now be affected by stabilized red crossbreeds
fix: MODsuit slowdowns should no longer behave weirdly with ash
accretion/magboots/armor booster modules.
refactor: Refactored MODsuit slowdown calculations to be query-based
instead of modules directly modifying part speed values.
/🆑
## About The Pull Request
A Huge chunk of changes just comes from moving existing storage code
into new files & seperating `atom_storage` code into its own subtype
under the already existing `storage/subtypes` folder.
With that the changes in this PR can be organized into 3 categories.
**1. Refactors how `/obj/item/storage/PopulateContents()` initializes
storages**
- Fixes#88747 and every other storage item that has a similar variant
of this problem
The problem with `PopulateContents()` is that it allows you to create
atoms directly inside the storage via `new(src)` thus bypassing all the
access restrictions enforced by `/datum/storage/can_insert()` resulting
in storages holding stuff they shouldn't be able to hold.
Now how this proc works has been changed. It must now only return a list
of items(each item in the list can either be a typepath or a solid atom
or a mix of them in any order) that should be inserted into the storage.
Each item is then passed into `can_insert()` to check if it can fit in
the storage.
If your list contains solid atoms they must be first moved
to/Initialized in nullspace so `can_insert()` won't count it as already
inserted. `can_insert()` has now also been refactored to throw stack
traces but explaining exactly why the item could not fit in the storage
thus giving you more debugging details to fix your stuff.
A large majority of changes is refactoring `PopulateContents()` to
return a list instead of simply creating the item in place so simple 1
line changes & with that we have fixed all broken storages(medical
toolbox. electrical toolbox, cruisader armor boxes & many more) that
hold more items they can handle
**2. Organizes initialization of `atom_storage` for storage subtypes.**
All subtypes of `/obj/item/storage` should(not enforced) create their
own `/datum/storage/` subtype under the folder `storage/subtypes` if the
default values are not sufficient. This is the 2nd change done across
all existing storages
Not only does this bring code cleanliness & organization (separating
storage code from item code like how `/datum/wire` code is separated
into its own sub folder) but it also makes storage initialization
slightly faster (because you are not modifying default values after
`atom_storage` is initialized but you are directly setting the default
value in place).
You now cannot & should not modify `atom_storage` values inside
`PopulateContents()`. This will make that proc as pure as possible so
less side effects. Of course this principle is not enforced and you can
still modify the storage value after `Initialize()` but this should not
be encouraged in the future
**3. Adds support for automatic storage computations**
Most people don't understand how `atom_storage` values work. The comment
here clearly states that
55bbfef0da/code/game/objects/items/storage/toolbox.dm (L327-L329)
Because of that the linked issue occurs not just for medical toolbox but
for a lot of other items as well.
Which is why if you do not know what you doing, `PopulateContents()` now
comes with a new storage parameter i.e. `/datum/storage_config`
This datum allows you to compute storage values that will perfectly fit
with the initial contents of your storage. It allows you to do stuff
like computing `max_slots`, `max_item_weight`, `max_total_weight` etc
based on your storage initial contents so that all the contents can fit
perfectly leaving no space for excess.
## Changelog
🆑
fix: storages are no longer initialized with items that can't be put
back in after taking them out
refactor: storage initialization has been refactored. Please report bugs
on github
/🆑
## About The Pull Request
Noticed that bitrunning virtual spawners were runtiming if the server
was already emagged. Basically, the guardrail component is added
(virtual_entity), then immediately deleted because it's emagged, leading
to a race condition in `JoinParent()` where parent is null. I still want
to keep this "valid, but delete me" state for components, so I made
`COMPONENT_REDUNDANT` (thx @LemonInTheDark).
I can't say for certain because I couldn't repro, but this /probably/
fixes#89992
## Why It's Good For The Game
Fixes a runtime
Allows devs to add components that execute an arbitrary amount of logic
while still qdeling themselves due to some in-game incompatibility issue
## Changelog
N/A
## About The Pull Request
Refactors martial arts off the mind. Don't worry the martial arts you
learn still transfer with mindswap
Instead, they are just tracked on a list on the mob, and they also
independently track the datum that created them
This fixes a lot of jank with martial arts, like say, having your krav
maga gloves transfer across slime clones or something...
But it also opens an opportunity: As we track all martial arts
available, I added a verb (ic tab) that lets you swap between the ones
you know

(Some don't let you swap like that one brain trauma)
## Why It's Good For The Game
Aforementioned fixes a lot of jank
Recently martial arts have just been up and disappearing and this was
entirely spurred on by that bug
Probably fixes#84710 (haven't checked)
Probably fixes#89247
Probably fixes#89948
Probably fixes#90067
## Changelog
🆑 Melbert
refactor: Refactored martial arts, if you notice any oddities like
managing to know two martial arts at once or having your powers
disappear, report it!
add: If you know multiple martial arts, such as krav maga from gloves
and cqc from a book, you can now swap between them at will via a button
in the IC tab!
/🆑
---------
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
## About The Pull Request
- All mentions of "express" have been renamed to "autodelivery"
- Autodelivering goods now comes with transit time. Mining console gets
30 seconds, the chef console gets 2 minutes
- Golem ordering remains the same as before. Forced autodelivery skips
any kind of transit time.
## Why It's Good For The Game
So this has been in the game for awhile, and I think it's a positive
element. But I think I messed up with the balance between the two
choices, because it's clearly far better to autodeliver and eat the
cost. I could change every other factor, and the only relevant one would
be the fact that express delivery instantly gives you what you want,
while the other option doesn't.
This change is meant to replicate the time you'd have to wait for cargo.
It may remain quicker than regular orders, but any amount of delay on
getting what you ordered is going to make the other delay (that comes
with discounts, and kickbacks, etc) more appealing to the orderee.
Ideally, if cargo is active, it should be a no-brainer to run a regular
order instead of express. Not sure if this does that without testing,
but it brings us closer.
I decided to make the delay far less for the mining console, mostly
because of distance to cargo and the cooldown also already mostly
removed.
## Changelog
🆑
balance: The cargo console now has a delay to express orders (renamed to
autodelivery)
/🆑
## About The Pull Request
I was kinda shocked that we didn't have something for this considering
that it's an unspoken rule of cargo to check that a crate does not sell
back for more than it's price and that the one comment saying to do so
has been doing some heavy lifting for the last 12 years.
I'm a novice when it comes to unit testing specifically so hopefully the
smoothing out that needs to be done should be fairly quick.
*Edit (2/22/25):*
The following changes were also made in order to allow for this unit
test to work smoothly:
Exports now have a market define added to them, as the purpose of this
unit test is to test exports that occur on the station, bought from
supply and then sold back to supply. As such, these market defines
exclude exports specific to pirates (since the cargo shuttle cannot sell
living mobs back, preventing you from making 10k per parrot crate.).
I've also added the `abstract` variable to some export datums, to
signify that a given export is either variable, or not meant to be
compared against the value of it's own container, such as with gas
canister's base export value as their export datums are generated
dynamically. (The subtypes are not abstract, however.)
The verb, `/mob/living/verb/tally_physical_credits()` has been changed
to `/mob/living/proc/tally_physical_credits()`, because that's my B and
does effect some economy back end but it's a one line fix so I just
absent-mindedly fixed it here instead of atomizing it out. I can
one-line it otherwise.
Mulebots now no longer runtime on spawn as they set their own to their
own `get_turf` as opposed to pulling their `loc`.
A few supply packs have had their prices bumped up slightly to actually
pass the test itself:
* `/datum/supply_pack/misc/candles_bulk`
* `/datum/supply_pack/security/armor`
* `/datum/supply_pack/security/helmets`
* `/datum/supply_pack/security/baton`
## Why It's Good For The Game
Prevents future infinite credit bugs that could have been missed by
simply checking the sale value in game.
## Changelog
🆑
fix: To prevent infinite sales issues, security helmets, armors, and
batons packs now all cost 600 credits, up from 400.
fix: Candle packs now cost 400 credits, up from 300, and candles now
sell for 12.25 cr each.
/🆑
---------
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
## About The Pull Request
Currently patches are a subtype of pills, and while they have the
``dissolveable`` var set to FALSE, barely anything checks it (because
people don't expect patches to be pills in disguise) so we end up
patches being dissolveable and implantable, which is far from ideal.
Both have been moved into an ``/obj/item/reagent_containers/applicator``
class, which handles their common logic and helps handling cases where
either one fits. As for gameplay changes:
* Pills no longer dissolve instantly, instead adding their contents to
your stomach after 3 seconds (by default). You can increase the timer by
dropping sugar onto them to thicken their coating, 1s per 1u applied, up
to a full minute. Coating can also be dissolved with water, similarly
-1s per 1u applied. Pills with no coating will work like before.
* Patches now only take half as long to apply (1.5s), but also slowly
trickle in their reagents instead of instantly applying all of them.
This is done via embedding so you could theoretically (if you get lucky)
stick a ranged patch at someone, although they are rather quick to rip
off. The implementation and idea itself are separate, but the idea for
having a visual display has been taken from
https://github.com/Monkestation/Monkestation2.0/pull/2558.

* In order to support the new pill mechanics, stomachs have received
contents. Pills and items that you accidentally swallow now go into your
stomach instead of your chest cavity, and may damage it if they're
sharp, requiring having them surgically cut out (cut the stomach open
with a scalpel, then cauterize it to mend the incision). Or maybe you
can get a bacchus's blessing, or a geneticist hulk to gut punch you,
that may also work. Alien devour ability also uses this system now. If
you get a critical slashing wound on your chest contents of your cut
apart stomach (if a surgeon forgot to mend it, or if you ate too much
glass shard for breakfast) may fall out. However, spacemen with the
strong stomach trait can eat as much glass cereal as they want.
Pill duration can also be chosen in ChemMaster when you have a pill
selected, 0 to 30 seconds.

## Why It's Good For The Game
Patches and pills are extremely similar in their implemenation, former
being a worse version of sprays and pills, with only change being that
pills cannot be applied through helmets while patches and sprays ignore
both. This change makes them useful for separate cases, and allows
reenactment of some classic... movie, scenes, with the pill change. As
for stomach contents, this was probably the sanest way of implementing
pill handling, and everything else (item swallowing and cutting stomachs
open to remove a cyanide pill someone ate before it dissolves) kind of
snowballed from there. I pray to whatever gods that are out there that
this won't have some extremely absurd and cursed interactions (it
probably will).
## Changelog
🆑
add: Instead of dissolving instantly, pills now activate after 4
seconds. This timer can be increased by using a dropper filled with
sugar on them, 1s added per 1u dropped.
add: Patches now stick to you and slowly bleed their reagents, instead
of being strictly inferior to both pills and sprays.
add: Items that you accidentally swallow now go into your stomach
contents.
refactor: Patches are no longer considered pills by the game
refactor: All stomachs now have contents, instead of it being exclusive
to aliens. You can cut open a stomach to empty it with a scalpel, and
mend an existing incision with a cautery.
/🆑
## About The Pull Request
Converts `/datum/player_details` into `/datum/persistent_client`.
Persistent Clients persist across connections. The only time a mob's
persistent client will change is if the ckey it's bound to logs into a
different mob, or the mob is deleted (duh).
Also adds PossessByPlayer() so that transfering mob control is cleaner
and makes more immediate sense if you don't know byond-fu.
## Why It's Good For The Game
Clients are an abstract representation of a connection that can be
dropped at almost any moment so putting things that should be stable to
access at any time onto an undying object is ideal. This allows for
future expansions like abstracting away client.screen and managing
everything cleanly.
## About The Pull Request
I standardized stuff in AASs code, and all current reference to it. Also
added interactions for bounty cubes, weather reports and request
consoles, all of it can be changed from AASs UI.
Also it's easier now to add new config entries for AAS to proceed, and
it's now downstream friendly.
## Why It's Good For The Game
Well, because kind of order in code and because it's funny to make
custom messages for... Almost everything?
BTW any entry can be blocked from ingame changes, by default you can't
change Broken Arrival shuttle and Security Officer arrival
announcements, how it was before. But may be we should allow it - it's
an open question.
## Changelog
🆑
add: Many things now handles via AAS: Bounty Cubes, Request Consoles,
Brig Cells, Vending Machines and Orion Trails alerts, Weather Reports,
Cargo Order Console
code: Now anyone can make their own entry for AAS
refactor: AAS internals, also cleanup
/🆑
## About The Pull Request
There are a couple of cases where ghost roles that give the temporary
body component prevent you from returning to the round when they really
shouldn't. The particular cases are:
- You entered a temporary body while you had no body, but could be
recovered via means such as podcloning
- You enter a temporary body, and while in that body, your original body
is permanently removed while your mind could be recovered via means such
as podcloning
- Basketball
This PR addresses those cases by allowing the temporary body component
to operate with a null `old_body`, and allowing the temporary body
component to be given to ghosts whose minds don't have bodies.
## Why It's Good For The Game
Erroneous DNRs caused by code oversights are probably very undesirable
to the playerbase.
## Changelog
🆑
fix: Joining a minigame or taking certain ghost roles, while you have a
mind without a body, will no longer DNR you, just in case you can be
resurrected by some means.
fix: If your old body is permanently destroyed while you are playing a
minigame or as certain ghost roles, you will still return to your
character's original mind, just in case you can be resurrected by some
means.
fix: The basketball minigame now gives its players and referee temporary
bodies.
/🆑
## About The Pull Request
Where I forget about a pr for 5 months.
This started because there was a pr that made it so skills transfer
between the real and the digital, and so I thought it'd be really funny
if I could train boxing in virtual reality... but there's no easy way to
get boxing gloves or anything like it in the virtual world...
So! I decided to make a disk for it, but then thought about fishing and
gaming and-
Anyhow it all went downhill from there and here we are now: Gimmick
Disks. (And a refactor of disk loading)
This implements a new type of bitrunning disk that instead of a single
item or ability, grants a full set of thematic items/abilities!
Unhelpfully cosplay as a wizard! Game inside your game! Down a digital
protein shake and box some simplemobs!
As the name "Gimmick" implies, these are primarily intended to help
shake up the sometimes stale bitrunner gameplay.
By letting you invoke, if you so desire, what to me is the most
enjoyable gaming experience: doing stupid shit with your buddies.
To facilitate the new type of disk I had to refactor disk loading, as it
was hardcoded to the item types.
Instead, we make disk loading send a signal to the bitrunner, and
register for this when held in their inventory.
This allows us to do things like making the lead acid battery give you
shock touch when held, without needing to make an explicit typecheck or
iterate over every item in the bitrunner's nested contents to see if
they have a loadable item.
## Why It's Good For The Game
I think it'd be really funny if you could train your boxing in the
digital realm.
As said above, I feel the bitrunner gameplay can get stale sometimes,
and this is how I hope to help people shake it up for themselves
sometimes. By giving them more stupid shit to do.
Doing stupid extended bits with other people is one of the things I
enjoy most out of ss13, and this is there to let the bitrunners do
exactly that with each other.
And sometimes you just have to roleplay as Gamers™️ entering virtual
reality to fight the virtual syndicate in bad cosplay while roleplaying
as a wizard smoking his magic weed, an overly edgy rogue, and the healer
desperately trying to keep them from exploding into a million pieces.
## Changelog
🆑
refactor: Bitrunning item/ability loading has been refactored. Please
report any issues.
add: Added Bitrunning gimmick loadout disks. These disks contain full
sets of equipment for all your digital cosplay needs, each including
questionably helpful equipment. Currently includes Sports (Boxer,
Skater, Archer, Fisher, Gamer) and Dungeon Crawling (Alchemist, Rogue,
Healer, Wizard).
add: Taking a lead acid battery into the netpod with you now gives your
bit avatar shock touch.
/🆑
## About The Pull Request
Adds a new area flag, LOCAL_TELEPORT.
This flag allows teleports ONLY in the same area that the teleport is
used. This allows for short range hijinks without enabling long range
exploits, and thus it's given to DMs and domains.
Changed almost all area_flags & NO_TELEPORT checks to use
check_teleport() (as now areas may use local_teleport instead, and this
lets them check for multiple things instead)
Thus I re-added Void Phase to the heretic scribe in DM and shuffled some
stuff around
(realizing now i neglected to doublecheck if blade breaking tps you to
station. need to check just in case)
## Why It's Good For The Game
It sucks you can't use teleporting abilities in temporary areas, so this
is a good way to allow this to still happen without opening the way for
gamebreaking exploits.
## Changelog
🆑
code: Adds a new area flag, LOCAL_TELEPORT, given to virtual domains and
deathmatch arenas.
code: Re-added Void Phase to Heretic Scribes in Deathmatch's Ragnarok
map.
/🆑
## About The Pull Request
Since #87866 PostTransfer now has it's parent set to nil, and instead
has a `datum/new_parent` argument supplied to it.
Why does the ***post*** transfer proc not have it's parent set yet? Not
sure, but some procs (and the documentation) haven't been adjusted yet
and this PR fixes that
also:
fixes#88156fixes#88325
## Why It's Good For The Game
Fix man good...
## Changelog
🆑
fix: /datum/component/PostTransfer() procs that didn't have their
new_parent arguments have now been fixed
fix: This means that turning into a Domain gondola shouldn't RR people
anymore
/🆑
## About The Pull Request
- Fixes#76827
This removes gravity from the following areas:
- Solars
- Nearstation
- Space
- Ordnance bomb testing
##### Note - Asteroid areas (Tram) or planet areas (Ice) are not
affected.
<details>
<summary>Examples of outside gravity turfs</summary>

</details>
Now stepping on floor plating in those areas will result in mobs
drifting. (like they do inside the station when gravity is offline)
Stepping on or near catwalks, lattices, or walls stills controls your
movement. Also refactored a little bit of the `has_gravity` code to use
defines instead of `TRUE/FALSE`.
## Why It's Good For The Game
Consistency. Mag boots are highly recommended when performing EVA.
## Changelog
🆑
fix: Fix gravity for areas in space near station (solars, nearspace,
bomb testing, etc.)
/🆑
## About The Pull Request
`boldannounce` is NOT for use ICly it's only for OOC stuff. `bolddanger`
is identical it just doesn't carry the same baggage
## Changelog
🆑 Melbert
fix: Stuff like the SM exploding will no longer output to your OOC tab
/🆑
## About The Pull Request
Replaces the mini-UZI beach battle domain reward with a ballistic
chameleon gun.
Also added a separate possible reward for an uzi bitrunning disk.
## About The Pull Request
clickable alerts glow (regex: /atom/movable/screen/alert/.*/Click)
## Why It's Good For The Game
people are much more likely to look at the chat or anywhere else than
the status effect (really, its usually never worth reading 99% of them
so they end up ignored)
## Changelog
🆑
qol: alerts that do stuff when clicked glow gold
/🆑
---------
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
## About The Pull Request
Fixes issues with var typing and proc arguments, discovered using
OpenDream's WIP TypeMaker feature (using improvements I haven't PR'd
upstream yet).
## Why It's Good For The Game
Codebase maintenance.
## About The Pull Request
So currently there's this incredibly incredibly niche records bug with
bitrunning.
Where if a generated bitrunner avatar has the exact same name as anyone
currently on the records, when it applies the hacker alias it then
proceeds to update the records to match.
This seems to be because it uses
`avatar.fully_replace_character_name(avatar.real_name, alias)`, which as
an old name is given then calls `replace_records_name(avatar.real_name,
alias)`, which proceeds to override the first record named
`avatar.real_name` with `alias`.
It also potentially screws with people's objectives for anyone with that
name.
As the documentation for this proc says:
7b9d4d0f94/code/modules/mob/mob.dm (L1123-L1125)
we instead just call it without supplying an `oldname`, such that it
doesn't try to update the records nor objectives.
This fixes our issues.
However, this _theoretically_ would've also updated our net avatar's ID!
But in practice, it never actually did so, as it would have required the
ID to already have been set to the `oldname` previously.
To make it actually update the ID, we instead just manually update the
avatar's ID after setting the alias.
## Why It's Good For The Game
Fixes jank.
It's nicer to have the IDs use the actual names rather than being
generic.
## Changelog
🆑
fix: A bitrunner avatar spawning with the exact same name as a name
currently on the records no longer updates that record to match when the
hacker alias gets applied.
qol: Net avatar ID cards use the net avatar's name instead of being
generic.
/🆑
## About The Pull Request
fixes https://github.com/tgstation/tgstation/issues/87419
When the avatar is qdel'd, the player returns to original body
## Why It's Good For The Game
Less bugs good
## Changelog
🆑
fix: Bitrunning: falling into chasms and other ways of destroying your
virtual body instead of killing it, WILL now return you to your body
/🆑
## About The Pull Request
This PR kills the abstract internal and external typepaths for organs,
now replaced by an EXTERNAL_ORGAN flag to distinguish the two kinds.
This PR also fixes fox ears (from #87162, no tail is added) and
mushpeople's caps (they should be red, the screenshot is a tad
outdated).
And yes, you can now use a hair dye spray to recolor body parts like
most tails, podpeople hair, mushpeople caps and cat ears. The process
can be reversed by using the spray again.
## Why It's Good For The Game
Time-Green put some effort during the last few months to untie functions
and mechanics from external/internal organ pathing. Now, all that this
pathing is good for are a few typechecks, easily replaceable with
bitflags.
Also podpeople and mushpeople need a way to recolor their "hair". This
kind of applies to fish tails from the fish infusion, which colors can't
be selected right now. The rest is just there if you ever want to
recolor your lizard tail for some reason.
Proof of testing btw (screenshot taken before mushpeople cap fix, right
side has dyed body parts, moth can't be dyed, they're already fabolous):

## Changelog
🆑
code: Removed internal/external pathing from organs in favor of a bit
flag. Hopefully this shouldn't break anything about organs.
fix: Fixed invisible fox ears.
fix: Fixed mushpeople caps not being colored red by default.
add: You can now dye most tails, podpeople hair, mushpeople caps etc.
with a hair dye spray.
/🆑
## About The Pull Request
On a downstream, we have an antagonist, that is a less competent
wizards. This antagonist's preview outfit has a beer bottle in their
hand, which has caused runtimes, as the bottle did not have any reagents
instantiated, and it tried check its length for sloshing. After putting
in a check for the `initial` argument of `on_equip`, I have noticed that
the problem goes deeper: the various procs that handle putting something
in your hand do not pass along if the items is put in your hand as a
preview or not. This PR adds a new optional var to these procs, ensuring
that unwanted behaviour during previews won't trigger.
I also swapped `visualsOnly` to snake case, as it looked inconsistent
with the rest of the code style.
## Why It's Good For The Game
Making the argument that ensures avoiding side effects during previews
work with all kinds of items is good.
## Changelog
🆑
fix: if an outfit puts a reagent container in the preview dummy's hand,
it will not try to slosh
code: outfits putting items in your hand will respect the visual_only
argument
/🆑
## About The Pull Request
We have the HIDEBELT flag but it isn't used anywhere and in fact is not
functional, so I added code to examine to enable it. I also threw the
flag onto a bunch of stuff -- primarily big billowy things, or stuff
like trenchcoats. This would include hiding guns, toolbelts, plant bags,
things of that nature. If you steal the Captain's saber and throw a
bedsheet on your head, you've pulled off the perfect crime.
## Why It's Good For The Game
Adds another way to be sneaky and immensely suspicious, increasing
paranoia when some guy wearing a big shapeless suit walks into the room.

## Changelog
🆑 Bisar
add: Clothing can now hide what you're wearing on your belt.
/🆑