## About The Pull Request
In my effort to make the /icons/ folder cleaner and more intuitive
instead of having to rely on recalling names of stuff and looking them
up in code to find them for poor sods such as myself, plus in spurt of
complusion to organize stuff, here goes. I've tracked all changes in
commit descriptions. A lot still to be done, but I know these waves go
over dozens of files making things slow, so went lighter on it.
Destroyed useless impostor files taking up space and cleaned a stray
pixel on my way.
## Why It's Good For The Game
Cleaner /icons/ file means saner spriters, less time spent. Stray pixels
and impostor files (ones which are copies of actually used ones
elsewhere) are not good.
## Changelog
🆑
image: Cleaned a single stray pixel in a single frame of a bite
telegraphing accidentaly found while re-organizing the files.
/🆑
## About The Pull Request
Tin. Another annoying spurious runtime that is caused by
create_and_destroy spawning weed nodes (which delete the weed at their
loc). It was doing this before the weed finished initializing sometimes.
Fixes https://github.com/NovaSector/NovaSector/issues/2494
Tested with 10 back to back CI runs, runtime did not occur.
## About The Pull Request
Fixes some grammar errors in some of the department wall signs, mostly
adding "the" to the sign descriptions and tweaking a few misplaced
capitals.
## Why It's Good For The Game
A minor grammar mistake has been eliminated. (Grammar is nice.)
## Changelog
🆑
spellcheck: A handful of grammar errors in some department signs has
been fixed.
/🆑
## About The Pull Request
At some point the examine line about what the resulting airlock will be
named got split off into a separate statement, but in the process some
things got crossed and it doubled up on the final half of the line.
Currently, an airlock might state:
> There is a small <i>paper</i> placard on the assembly labelled ",
written on it is 'Public Garden'".
So we cut out the ` labelled \"[doorname]\"` part and go back to just
having the `, written on it is '[created_name]'` part.
> There is a small <i>paper</i> placard on the assembly, written on it
is 'Public Garden'.
## Why It's Good For The Game
Comprehensible examine for airlock assemblies.
## Changelog
🆑
spellcheck: Examining a renamed airlock assembly no longer says it has a
paper placard that is "labelled with written on it is".
/🆑
## About The Pull Request
Changes all player-facing instances of "recieve" to the correct spelling
"receive". There are still a handful of instances in the code, but this
PR doesn't mess with those.
## Why It's Good For The Game
It's important to speel things correctly.
## Changelog
🆑
spellcheck: Correctly spells "received."
/🆑
## About The Pull Request
This PR fixes some balance and practicality issues with the spawner
component that has affected vent mining and the associated wave defense.
* The turf_peel() proc now checks to see if it's pulling no turf from
the inside or outside of it's peel, in which case it now has a default
case where it returns it's center turf instead.
* As a consequence of this, the center turf is where mobs will spawn if
an ore vent is unable to find any space where it can spawn any new
hostile mobs.
Upon testing this, it worked fairly well, but ultimately node drones
were capable of tanking enough hits for long enough that typically they
could still survive a small vent's onslaught. As a precaution, I've made
two additional changes.
* Node drones have had their maximum health dropped slightly, from 500
health to 300 health.
* As a secondary precaution, if a spawner using the turf peel method
cannot spawn correctly, it will send a signal, which ore vents are now
registered to. When called on an ore vent, it has new behavior to clear
the offending nearby turfs and create a pathway to allow nearby mobs to
get access to the vent.
* (**This is an explosion**.)
## Why It's Good For The Game
Fixes an unreported on the repo but repeatedly pinged issue regarding
ore vent waves where players could often wall off or blockoff an ore
vent in such a way that it allows vents to be functionally immortal by
quickly walling off the vent using sandstone doors. This should help to
prevent players cheesing the intended gameplay mechanic, as well as keep
up the challenge to arcmining wave defense without some additional
nuance.
I may have gone a little overboard with the health tweaks as well, but
considering that even with the explosions, I was able to survive the
repeated explosions on the vent, I think this should work quite well all
things considered. Still, open to feedback there.
## Changelog
🆑
balance: Ore vents, if blocked off from all four sides while being
defended, now cause a mild gas explosion, resulting in a mild dissuasive
explosion.
fix: NODE drones spawned from ore vent defense have lower maximum
health.
/🆑
## About The Pull Request
Turf rusting is now based on knowledge instead of RNG; toxic damage on
spells has been replaced with disgust; rust walkers are a bit easier to
summon and show up early in the tree.
Rust ascension spread has been massively increased and immunities while
on Rust have been updated.
## Why It's Good For The Game
This is a massive list of changes, but the tl:dr is Rust heretic design
is pretty barebones and dated in its current state. I'm going to try my
best to explain why that is and why it needs to change.
### RNG on rusting is bad
**Problem** : quite a lot of turfs cannot be rusted, and reinforced
turfs rusting is tied to RNG, the emergency shuttle floors are also
unrustable, making an ascended heretic not threatening at all to an
escaping crew.
**Solution**: Heretic rusting prowess is now tied to knowledge
progression; reinf wall rusting is no longer tied to RNG; the emergency
shuttle is now rustable if you have accrued enough knowledge.
**Explanation** : I've been adopting the code from a previous PR that
sadly didn't make the light of day.
Link: https://github.com/tgstation/tgstation/pull/65361
The goal is to have Heretic rusting be more consistent, so that if you
ascend the shuttle is no longer a safe refuge.
**Grasp Of Rust**: Basic floors and walls.
**Mark Of Rust**: Reinf floors and walls (takes 3 applications of rust
to fully destroy).
**Toxic Blade** Titanium and Plastitanium( still takes 3 applications of
rust to destroy).
**Ascension**: almost everything save for admin walls, glass, and
silver.
### A territorial antagonist with no tools to defend its turf
**Problem**: Rust heretic is forced into a territorial playstyle, but
it's heavily diminished by rusted turfs not having any negative effect
on the crew whatsoever, Toxic damage on plume and blade is also kind of
bad and has no synergy with the rest of the kit.
Lastly, while fitting to the theme of Rust; mark detonation destroying
clothes and items can end up being more harmful to the heretic, as
destroying a secoff's flashbang will result in you getting stunned and
killed.
**Solution**: Rusted floors are no longer safe for the crew; walking
over Rust will add a small buildup of disgust, silicons will receive
ticking damage, Toxic damage on Rust skills has been replaced with
disgust buildup and a chem purge effect to prevent the crew from
cheesing the debuff with sol dry.
**Explaination** "The goal behind this change is to prevent the crew to
just be able to walk willy nilly into an eldritchly decayed area without
repercussions, plus I feel like disgust is a fitting debuff for Rusties
for a number of reasons.
1) Lore wise, your goal is to turn the entire station into a garbage
dump.
2) It fits for fighting a territorial antagonist, it's not immediately
threatening on its own, but if you overstay your welcome, it has dire
consequences.
3) We don't really do much with disgust as a status effect, far as i
know, this'll be the first iteration of it being used for an antagonist
toolset.
4) It gives reason to the crew to act hostile towards the Heretic, as
you are essentially making their work area inhabitable.
I've also Slightly increased the healing on leeching walk and gave it
some minor temperature regulation (you won't be able to outtemp space
cold).
### Rust Walkers
**Problem**: Rust walkers might as well not exist in their current
state; they are one of the latest heretic unlocks, and the recipe for
summoning one is INSANE now that you cannot decapitate mobs anymore.
**Solution**: Rust walkers pop up a bit earlier in the tree; the ritual
to summon them has more reasonable reagents (wires, pools of vomit, iron
sheets) and they have increased health.
**Explanation**: : There is not a lot to add to this. without walkers,
Rust heretics are fairly slow at spreading rust, by making rust walkers
have reasonable summoning reagents, we ease that problem; lastly i've
slightly bumped their hp, as i felt 75 hp was a bit low.
### Underwhelming ascension
**Problem**: The spread rate from the ascension is downright ATROCIOUS
in its current state, i actually ran multiple tests on different maps,
on Metastation it can take up to 40 minutes for the rust to spread to
the entire station, considering an ascended heretic results in an
immediate shuttle call, it's unecceptable in its current form.
Solution: Rust spread is now a hybridization between old ascension and
Wizard tranformation ritual.
**Explanation**: The spread rate in its current form is painstakingly
slow and has a tendency to reach one corner of the map and compound on
itself, i've borrowed the code from the wizard final ritual
"transformation" and gave it my own spin so that given enough time it
will cover the station more or less evenly, it can now spread through
all z levels.
Video example: https://www.youtube.com/watch?v=jZ5zMrNM6Jw
I've also updated the immunities you gain on ascension to ignore
slowdown and stasis from Cryogelidia.
The whole point of rust ascension is to become immune to crowd control,
i've seen far too many ascended heretics die to a single bola or cryo
syringe, that's pretty lame so i fixed that.
Lastly, aggressive spread has had its radius reduced in exchange for the
spread being consistent now; cooldown is also halved when you ascend, to
better help the heretic go on the offensive.
## About The Pull Request
Does a audit on all uses of parse_zone, replacing most instances of it
with a new living-level proc that refers to the bodypart in that zone if
it exists.
In other cases, removes parse_zone entirely because the bodypart is
already confirmed to exist, so we just use plaintext_zone.
Also cleans up some single letter vars.
## Why It's Good For The Game
In the doc of ```plaintext_zone```, its said it ```Should be used for
parsing non-instantiated bodyparts```. 99% of the code ignores the
possibility of a bodypart existing, and so uses parse_zone when
plaintext_zone could be accessed instead.
## Changelog
🆑
code: Most instances of parse_zone now refer to the limb's
plaintext_zone var
/🆑
---------
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
## About The Pull Request
Fixes: https://github.com/tgstation/tgstation/issues/83229
I think this code was done this way by a little mistake, and a metal
sword should conduct electricity anyway (right?).

## Why It's Good For The Game
its a fix
## Changelog
🆑 Rengan
fix: Officers sabre and grilles now conducts electricity as it should.
/🆑
## About The Pull Request
https://github.com/tgstation/tgstation/assets/51863163/b0662ee7-8f67-42d3-95ca-31012556f4ee
This effect is purely visual, objects are still "instantly" put into or
out of the morgue itself. (Meaning you can't grab an object as it is
being shifted in or taken out, nor can you move off the tray while it is
sliding in or out.)
Also applies to crematoriums.
## Why It's Good For The Game
Adds a tiny bit of visual flair to help "sell" the effect that the tray
belongs to the morgue container, rather than just appearing and
disappearing.
## Changelog
🆑 Melbert
qol: Morgue trays (and the contents inside) are now animated on open and
close
/🆑
## About The Pull Request
This PR moves random name generation for species onto their languages.
What does this mean?
- For species with a predefined name list, such as Lizards and Moths,
nothing.
- For species without predefined name lists, such as Felinids, their
names will now be randomly generated from their language's syllables.


(In the prefs menu:)

Why?
- Well, we actually had some dead code that did this. All I did was fix
it up and re-enable it.
- Generates some pretty believable in-universe names for various
languages that are lacking name lists. Obviously defined lists would be
preferred, but until they are added, at least.
- Moves some stuff off of species, which is always nice.
- Also hopefully makes it a tad easier to work with name generation.
There's now a standard framework for getting a random name for a mob,
and for getting a random name based on a species.
Misc:
- Adds a generic `species_prototype` global, uses it in a lot of places
in prefs code.
- Makes `GLOB.species_list` init via the global defines
- Deletes Language SS
- Alphabetizes some instances of admin tooling using the list of all
species IDs
- Docs language stuff
- Deletes random_skin_tone, it does pretty much nothin
## Changelog
🆑 Melbert
refactor: Random Name Generation has been refactored. Report any
instances of people having weird (or "Unknown") names.
qol: Felinids, Slimepeople, Podpeople, and some other species without
defined namelists now automatically generate names based on their
primary language(s).
qol: More non-human names can be generated in codewords (and other misc.
areas) than just lizard names.
/🆑
This is just a revitalization of #80275.
## About The Pull Request
On the tin, basically demotes everything related to setting up and
storing these bulky lists generated from reading
`/datum/sprite_accessory` subtypes from living in a global space that
will instead be in a compartmentalized subsystem for accesses. Also a
lot of code modernization and micro-improvements (unquantifiable)
## Why It's Good For The Game
Same exact expected results, just accessed in a different way.

There's a few reasons why I want this to happen.
* The `GLOB` space is too clogged. There are at least a thousand
variables on `GLOB`, and it's extremely painful to access stuff on
production/local through view variables when you're debugging stuff like
this. It's also painful when there is stuff that _should_ live on `GLOB`
that you might want to see in VV/Debugger but are forced to either have
to scroll a mile to find what you want or wait a long while for it to
load. The less bulky lists we have of stored initialized datums, the
better.
* `make_datum_reference_lists()` is a consequence of wack stuff like
this where we're reliant on certain things being initialized in the
`GLOB` portion of world initialization _before_ subsystems/static
variables load - most of these datum lists in the aforementioned proc
doesn't _really_ need to be ready to go before `world.New()` for
example. We'll sadly have to abuse `PreInit()` for now, but it really is
something that has to be ready to go due the critical dependence that
stuff like Preferences has on it.
* We don't have to have the procs live in a global namespace either.
Instead of passing in `GLOB.XList` or `DSstorage.XList` every single
time, we can instead just move the proc setup on the subsystem and use
`XList` in a more native fashion.
* It's easier to find what you need. To me, it's a lot nicer to
ctrl+click the DS and go to the variables to find something I'm looking
for instead of having to scavenge around for any footprint/trace of the
global I want to look for. This is more trivial than the other two, but
that's something I like to think about when I go to bed.
I also had to refactor a bit of the code to accommodate the limitations
of the new DS system, but it should be a lot cleaner anyways.
## Changelog
Not relevant
---
Also nothing should have broken but it's a good thing we have screenshot
unit tests to prove me wrong.
## About The Pull Request
Lets you pick up wheelchairs while resting, and lets you place
wheelchairs on adjacent tiles, much like medical roller beds.
## Why It's Good For The Game
Makes life just a little bit easier. Barely being able to move is
already enough of a downside. I think allowing the little bit of extra
independence being able to pick up your own chair (without just finding
or making a basic chair first) offers is justifiable.
And being able to place the chair a tile away just saves needing to
pixel hunt or shuffle around to buckle yourself.
## Changelog
🆑 Fluffles
qol: you can pick up wheelchairs while on the ground
qol: you can place wheelchairs a tile away from you, like roller beds
/🆑
i noticed node drones were being hard deleted 60% of the time. its
because the ore vent wasnt cleaning up after them. also fixes some
runtimes if ur id card didnt have a registered account
fix hard deletes
## About The Pull Request
I was trying to fix a bug with ejecting from mechs as malf AI and the
more I looked the worse it seemed to get? So I'm putting in this PR with
the intent to refactor AI code to not be a Byzantine nightmare of new
objects referencing each other incompletely or with buggy behavior.
Finished PR for #82579 because I didn't want to clutter the comments
with commits of me trying to fix shit with git restore and revert
## Why It's Good For The Game
Fixes#81877Fixes#82524
Mech dominating now just works off (and integrates with) similar code
for APC shunting
The cores left behind by AIs shunting or controlling mechs now properly
reference the AI instead of only the other way around
Some of these refactors slightly change how malf works; I think most of
it was unintended behavior in the first place, let me know in review if
not
## Changelog
The code for AIs remoting out of their shell has been refactored.
🆑
fix: Mech domination now properly integrates with shunting.
fix: Combat upgraded AIs no longer get two buggy malf ability pickers if
they also become malfunctioning
refactor: Refactored most of the functionality around malf AI shunting,
mech control
/🆑
---------
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
## About The Pull Request
(short, slightly outdated video compilation of the pirates)
https://youtu.be/j9BNFzcUSjc
Adds the **MEDIEVAL WARMONGERS** pirate gang, these pirates are focused
on causing chaos directly on the station with the use of melee weaponry
and swarming tactics.
they are not very smart when it comes to using technology, so they crash
in the station in an attempt to dock.
the pirates spawn with the NOGUN trait as they have never used guns
before but have access to dashing and the unbreakable component(small
heal burst upon reaching crit).
Warlord spawns with a better version of hulk(isnt removed upon crit and
can still do stuff while critted) and gigantism mutation by default
because ~~Chad Maximus~~ the other pirates require someone to run to
when stuff like flashbangs, batons or lasers are present. The warlord
spawns with a boarding axe which is a better axe that is good at
destroying things and a meat hook. **there's a total of 5 pirates.**
the pirate shuttle has:
- thermite barrel and 3 large beakers
- single weak claymore
- 3 extra military spears
- 3 kite shields
- 3 heavy bolas
- 4 regular bolas
- a stack of wood
- 2 stacks of mourning poultice (15 uses each)
- one burn medkit
**shuttle was made by striders18, big thanks to him**

things added:
- the new pirate gang
- a gamberson jumpsuit
- crude armor (good melee and wound protection but lacks on the rest)
- warlord armor (extreme protection at the cost of slowdown)
- a shortsword(bootleg claymore with 30 block chance and goes on belt
instead of back)
- military spear (better at throwing, better wounding, deals blunt
wounds instead of sharp)
- axe with better damage and demolition mod for the warlord
- a var to specify the name of the landing zone destination for the
assaultpod
- an assault pod targeting device item for the medieval shuttle
- a thermite barrel
- kite shields
- new hulk variant that doesnt go away when crit and has tenacity
## Why It's Good For The Game
I always liked the chaotic nature of the russian bounty hunters that
would come from their extra numbers and lack of tools. i thought
something of a similar idea on pirates would be good, a very direct and
scary militia rushing in with sword and faith would create some awesome
scenarios
## Changelog
🆑
add: New heavy weight pirates, medieval warmongers
add: Adds military spear, shortsword, boarding axe, kite shields
add: Adds warlord and crude armor
add: Adds medieval shuttle (made by striders18)
/🆑
---------
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
## About The Pull Request
Subsystems currently come in two different flavors:
1. Systems that process at intervals with the master controller
2. Global data containers that do not fire
And I think they should be split up...
This moves 4 non firing, non init subsytems -> datasystem
## Why It's Good For The Game
Clarity in code
## About The Pull Request
### Changes Fitness skill to Athletics skill; Removes the sprite growth
as the only meaningful reward
Basically just a rebranding so that it is more broad in its concept. It
isn't just about peak physique. It's about how you can apply it too.
Reaching Legendary rewards you with the Golden Gloves.
### Boxing Overhaul
I started it in this pr here
https://github.com/tgstation/tgstation/pull/80635
But this is a more significant overhaul of boxing from the ground up.
Namely, it now is majorly influenced by the Athletics skill, and also
more thoroughly aligns with conventional punching in its current state.
However, a major component of this is that boxing's breadth of mechanics
is only relevant when used against another boxer. Non-boxer targets are
only ever going to get smacked by a stamina punch, as it is currently
(and more or less the same values too). Additionally, boxers cannot
punch someone who is either unconscious or in stamina crit, so it can't
be used to maintain stamcrit.
- Boxing now has a One-Two Punch mechanic. Swapping between the left and
right mouse buttons to punch and maintaining this causes every second
punch to do more damage (to boxers). Breaking this chain by punching
with the same button twice will cause you to lose damage (against
boxers).
- Boxing now can have crits occur below 50 stamina damage (against
boxers). However, to knock someone out clean, the target must be
staggered from a previous crit first. (Or I guess be staggered at all,
maybe their shoelaces were tied or something). Crit probabilities are
determined by adding your Athletics probability skill bonuses to your
unarmed effectiveness, and then reduced by the targets own Athletics
skill bonuses. It is hard for two athletes to knock each other out in
one blow. It is trivial for a legendary boxer to knock out a novice in a
single punch. Cybernetically enhanced boxers are dangerously effective
at boxing.
- Boxers can block other boxers by using throw mode, but the chances of
doing so is based on Athletics skill bonuses. A successful block causes
the attacker to take stamina damage (as does the blocker, but less so).
- Participating in boxing increases the Athletics skill. Your gains are
probably slower than normal training, but you at least get some reward
for doing so. Only relevant if your opponent is a boxer. Get a sparring
partner!
### Evil Boxing (Admin Only)
So this is all well and good, but what if you're a scoundrel with no
care for the other person in this equation? Well, that's where Evil
Boxing comes in. Evil Boxing has absolutely no restrictions at all, and
can freely use its boxing abilities against anyone. Even non-boxers. You
can even grab people! Wow, what a scumbag. I bet you even king hit
people. Thankfully, only an admin can make you into an Evil Boxer.
### Strength and Stimmed Mutations now benefit Exercising and Boxing
(against boxers)
Both mutations have a flimsy increase to instability of 5 because of how
incredibly particular the bonus is.
Strength now reduces the amount of stamina damage inflicted via
exercising by half. Strength also adds a +2 damage bonus on boxing
punches while boxing against boxers (this doesn't influence normal
unarmed attacks whatsoever, or boxing against nonboxers). Obviously,
evil boxers just get this benefit against everyone because they're
knaves.
Stimmed increases the duration of the exercised status effect by one
factor. (That is, if you have no other modifiers, it will double the
duration on its own)
## Why It's Good For The Game
@Jacquerel was racking their brain trying to come up with an alternative
to the skill rewards of Fitness. At the moment, sprite growth is not
only a really bad bonus (it does literally nothing but make you big, and
thus is actually a detriment due to how intrusive sprite size is with
interaction, and plays weird with other sprite changing effects), but
isn't really all that interesting for all the effort put in.
Problem is, how do you make Fitness meaningful without making it a
powergame mechanic? Simple! You make it applicable to a really niche,
self-contained but still utilized game mechanic that is engaging to
participate in and makes you meaningfully very good in it. AND scratches
that power scaling itch that many players have.
Boxing is reasonably self-contained as is, but pretty bland due to how
old it is. While maintaining that self-contained nature, I hoped to
expand the interactivity of boxing a little bit by giving it a small
mini-game in of itself. And also introduce ways to simulate the idea of
boxing a bit better.
The idea of being an Evil Boxer is funny. For every Rocky, there is a
[Insert Rocky Villain Here that isn't Creed]. But in this case, it's
probably some Syndicate douchebag looking to punch clowns into a coma
and inspire the mime to take up shadowboxing in revenge.
## Changelog
🆑
add: Replaces Fitness with Athletics; same skill, but now more
specifically applicable to boxing.
add: Athletics does not increase sprite size.
balance: Overhauls Boxing to add a lot more depth to the interactions.
Only applicable to other boxers, however. You can still punch the snot
out of non-boxers though. But only up to stamcrit or unconsciousness. No
hitting someone who can't fight back!
balance: Adds Evil Boxing, which is the evil and fucked up version of
boxing that you kill people with and are allowed to flout the sacred
rules of boxing as you please. Everyone is a victim!
/🆑
## About The Pull Request
Scanning ore vents will now tag them on GPS so you can find them easily
when you are prepared (and remove them when they are tapped). Also adds
special pinpointer to help with finding unscanned vents in a first
place. And adds missing uranium overlays for scanned vents. Because why
not.
<details>


</details>
## Why It's Good For The Game
While looking at mineral density to find vents is somewhat fun and
entertaining, having some sort of upgrade to make finding them easier
adds a bit of a progression. Also re-finding already scanned vents can
be a bit annoying. You need to fill your backpacks with GPSs and tag
them manually. It is also inconsistent with geysers that are added to
positioning after you scan them. And with tendrils, which are always
visible.
## Changelog
🆑
add: added ventpointer that points toward nearby ore vents and can be
bought with mining points
balance: scanned ore vents can now be found with GPS
fix: fixed ore vents missing overlay icon for uranium
/🆑
## About The Pull Request
Allows you to alt-click a bunch of items while resting.
Fixes#82788
## Why It's Good For The Game
Some of these, such as storage, are bugfixes. You shouldn't need to be
standing up to configure a spray can, or change the direction of your
bedsheet
Others are just sensible changes.
## Changelog
🆑 Melbert
fix: You can open bags with alt click while resting again
qol: Many items which previously required you to stand to alt-click now
don't, such as bedsheets and spray cans
/🆑
## About The Pull Request
Deathmatch is severely lacking in HIGH IMPACT MAGIC LARPING. So I added
a big ass wizard arena. The arena itself is based off the wizard den.
Loadouts:
**Wizard:** Standard all-rounder. Got magic missile, jaunt, and
forcewall. Regular gear.
**Pyromancer:** Fire guy. Red robes, fireball, smoke.
**Electromancer:** Zappy guy. Lightning and tesla shock.
**Necromancer:** Is a skeleton. Has Scream for Me and blink.
**LARPer:** Straight from Station & Spessmen. Fake robes and can only
throw lightning and repulse.
**Chuunibyou:** Classic animage. Got chuuni buff and magic cards.
**Battlemage:** Melee fighter. Got some armor and a big hammer with
instant summons.
**Apprentice:** Underpowered until they find a mystery box. Got charge.
**Gunmancer:** Who needs magic when you have guns? Starts with an m1911,
lesser gun summons, and knock.
**Monkeymancer:** Is a monkey. Can summon monkeys and gorillas. Has a
banana.
**Chaosmancer:** Jumbled robes. Starts with a chaos rod. Can rod form
and summon traps for high chaos.
**Funnymancer:** It's just a clown with a banana staff.
The map itself is a pretty standard arena with a long sightline in the
middle. Each participant spawns in their own room complete with a magic
item box. The very southern portion of the ship has a standard mystery
gun box. Soon after the round starts, a hostile gelatinous cube in the
center of the map will break out and attack whoever it sees. Inside its
enclosure is a free death wand. Map has been tested to make sure
deathmatch participants can't escape the deathmatch.
## Why It's Good For The Game
Deathmatch provides a unique opportunity for people to play with
mechanics they will not often get to use. Allowing people to play wizard
for a few minutes shouldn't cause too much harm aside from admin logging
from explosions, which hopefully a fix is in the pipeline for.
## Changelog
:cl:Motho
add: Added wizard-themed deathmatch map.
add: Added mystery wand box.
/🆑
## About The Pull Request
I have received feedback that after the prior changes in #81971, the
gulag is still a little bit too subject to RNG.
The main culprit (as in my previous PR) is Iron being kind of cheap and
the fact that unlike the old Gulag you no longer have any way of
headhunting more valuable materials (everything appears as boulders on
your ore scanner).
My solution to this is wider than the last one of tweaking point values,
but also much simpler:
Just make every boulder you mine be worth the same amount of points
regardless of what is inside of it.
On the average test I made I could comfortably mine about 40-45 boulders
in ten minutes.
We'll make some adjustments to that rather than leaving 40 as the target
number;
Most players upon being teleported to the gulag are going to spend a few
minutes whining and bemoaning their fate instead of getting straight to
work. I had the benefit of being able to make sure my run started as
soon as a storm ended so I wouldn't need any kind of midpoint break. I
was also always the only person playing on my local instance, there
hadn't been any other pesky prisoners before me who had already mined
out all the nearest available deposits. And of course, let us not
forget, I am an MLG master league ss13 player who was surely performing
well above average.
So we'll round that down to: Each boulder is worth 33 points, meaning
you need to collect 31 boulders to complete a 1000 point (roughly ten
minute) sentence.
How do I ensure that every boulder is worth the same amount of points?
Well it's pretty easy.
One boulder = one material sheet. One material sheet = 33 points.
Simple.
"Now Jacquerel", I hear you not saying because you don't want me to know
about this thing you would prefer to do instead of hitting rocks
outside; "if I simply smash all of the tables and microwaves and botany
trays and bed in the gulag I can easily get like 65 sheets of Iron,
which is almost enough to buy the freedom for two entire people!"
Unfortunately I knew you were going to try and do that and the prisoner
point machine will only give you points for material sheets which have
been printed from the material smelter (well, any material smelter
actually but you should probably use the one in the gulag). You'll be
able to tell because if you examine a valid material sheet it will
mention a little maker's mark on it, which is absent in the beat-up iron
that you get from smashing furniture to bits.
Also glass is worth 0 points. Don't waste time digging up that shit.
As glass has had all of its point value removed, I have added a "work
pit" to the gulag to compensate. You can pull boulders out of this
indefinitely via effort, however it also stamcrits you every time.
It's not very fun to do this, but that's because I would prefer you to
go find the rocks out in the field instead. This is a last resort.
You can do this if there's no boulders left to mine or if you really
really really hate mining and would rather very slowly click on one tile
repeatedly to get your boulders instead.
As a tiny bonus doing this gives workout experience.
This isn't a totally ideal solution but I think it'll do for now.
## Why It's Good For The Game
What we want out of the gulag is:
- Something where officers can vaguely approximate an expected sentence
duration.
- A task that requires players to actually be spending that time doing
something to get out of here.
- Produces at least some amount of useful materials.
In I think roughly that order.
I hope this change accomplishes all three of these in a way that is
somewhat predictable rather than throwing darts at a board.
## Changelog
🆑
balance: Gulag mining has been rebalanced so that every boulder is worth
the same amount of points to mine for a prisoner regardless of what it
contains, and should be more consistent.
add: A vent which boulders can be hauled out of by hand has been added
to the gulag which you can use if there's nothing left to mine. It is
very slow, but at least it gives you a workout...
/🆑
## About The Pull Request
Rewrites how alt click works.
Based heavily on #82625. What a cool concept, it flows nicely with
#82533.
Fixes#81242
(tm bugs fixed)
Fixes#82668
<details><summary>More info for devs</summary>
Handy regex used for alt click s&r:
`AltClick\((.*).*\)(\n\t.*\.\.\(\))?`
`click_alt($1)` (yes I am aware this only copies the first arg. there
are no other args!)
### Obj reskins
No reason for obj reskin to check on every single alt click for every
object. It applies to only a few items.
- Moved to obj/item
- Made into signal
- Added screentips
### Ventcrawling
Every single atmospherics machine checked for ventcrawling capability on
alt click despite only 3 objects needing that functionality. This has
been moved down to those individual items.
</details>
## Why It's Good For The Game
For players:
- Alt clicking should work more logically, not causing double actions
like eject disk and open item window
- Added context menus for reskinnable items
- Removed adjacency restriction on loot panel
For devs:
- Makes alt click interactions easier to work with, no more click chain
nonsense and redundant guard clauses.
- OOP hell reduced
- Pascal Case reduced
- Glorious snake case
## Changelog
🆑
add: The lootpanel now works at range.
add: Screentips for reskinnable items.
fix: Alt click interactions have been refactored, which may lead to
unintentional changes to gameplay. Report any issues, please.
/🆑
## About The Pull Request
So if a closet/crate has the `NO_DEBRIS_AFTER_DECONSTRUCTION` set on it
and if someone/something is still inside, then after deconstruction they
get deleted rather than getting dumped out first.
Could cause potential hard delete of mobs & stuff. We don't want to deal
with that
## Changelog
🆑
fix: closets & crates will dump all contents out first before deleting
itself regardless of `NO_DEBRIS_AFTER_DECONSTRUCTION` thus not for e.g.
hard deleting mobs inside it
/🆑
## About The Pull Request
Issue brought some missed hidden actions to my attention.
I left cogbars in for _breaking_ handcuffs because resisting is sort of
a gray area. On one hand, you don't want someone to see you doing it; on
the other, there is a visible warning that you started doing it. So,
meet in the the middle, breaking handcuffs is still visible while
resisting isn't.
## Why It's Good For The Game
Closes#82583
Cogbars are not intended to ruin stealth
## Changelog
🆑
fix: Deviants buffed: Rogue shoelacing, pickpocketing and restraint
resisting no longer give cogbar icons.
/🆑
## About The Pull Request
Fixes the following input stalling exploits (maybe missed some):
- Changing GPS tag
- Setting teleporter destination
- Request Console Reply
- Various AI law board interactions
- Note, I used `is_holding` but technically this means these fail with
telekinesis. I can swap them to `can_perform_action(...)`, which allows
TK, but I noticed some places explicitly deny TK interactions with Ai
law boards. Not sure which is preferred.
- Borg Rename Board
- Plumbing Machines and Ducts
- APCs and SMES terminal placements
- Stargazers Telepathy
- Go Go Gadget Hat
## Changelog
🆑 Melbert
fix: You can't change the GPS tag of something unless you can actually
use the GPS
fix: You can't set the teleporter to a location unless you can actually
use the teleporter
fix: You can't reply to request console requests unless you can actually
use the console
fix: You can't update AI lawboards unless you're actually holding them
fix: You can't update a borg rename board unless you're actually holding
it
fix: You can't mess with plumbing machines unless you can actually use
them
fix: You can't recolor / relayer ducts unless you're actually holding
them
fix: You can't magically wire APCs and SMESs unless you're right by them
fix: You can't use Stargazer Telepathy on people who you can't see
fix: You can't configure the Inspector Hat unless you can actually use
it
/🆑
## About The Pull Request
1. Renames `NO_DECONSTRUCTION` -> `NO_DEBRIS_AFTER_DECONSTRUCTION`. As
the name suggests when the object is deconstructed it won't drop any
items/debris. After my last refactor for this flag it now serves a new
purpose so its name has been changed to match that
2. Fixes objects that are now using `NO_DECONSTRUCTION` incorrectly.
Some of these changes include
- Removing the flag in objects where there are no means to deconstruct
them (e.g. jukebox, hydroponics soil, flora etc)
- Replacing the flags old purpose by overriding its tool procs so that
it regains its old behaviour(e.g. You once again cannot deconstruct ctf
reinforced tables, survival pods, indestructible windows etc)
## Changelog
🆑
code: renamed `NO_DECONSTRUCTION` to `NO_DEBRIS_AFTER_DECONSTRUCTION` so
its name matches its intended purpose
fix: fixes some items that incorrectly used `NO_DECONSTRUCTION` prior to
its refactor, meaning makes some objects non deconstructable again
/🆑
## About The Pull Request
Edited: updated changelog, read comments for changes in implementation
details
So previously, tables would let you use a wrench to fully deconstruct
them, or a screwdriver to take off only their top.
This, however, broke in two different ways in #82280, when their
deconstruction logic got changed.
First off, deconstructed tables would only drop the materials for their
top and not their frame.
For this, the primary culprit seems to be on line 307:
c34d56a45b/code/game/objects/structures/tables_racks.dm (L300-L307)
Where `new framestack(target_turf, framestackamount)` accidentally got
an extra indent, and ended up in the less common half of the if-else
chain.
Just moving this outside of the if-else chain again fixes it.
Secondly, tables had their own special deconstruction logic, which got
'standardized'.
Issue. This was special to accommodate for having two different
deconstruction logics: full or top only.
With `deconstruct(...)` no longer being overridable, I feel it's awkward
to attempt to proxy that information to the new `atom_deconstruct(...)`
So we introduce a new method, `deconstruct_top`, for the screwdriver to
use, which handles deconstructing only the top.
```dm
/obj/structure/table/proc/deconstruct_top()
var/obj/table_frame = new frame(loc)
if(obj_flags & NO_DECONSTRUCTION)
table_frame.obj_flags |= NO_DECONSTRUCTION
else // Mimic deconstruction logic, only drop our materials without NO_DECONSTRUCTION
var/turf/target_turf = get_turf(src)
drop_top_mats(target_turf)
qdel(src)
```
Mimicking the `NO_DECONSTRUCTION` logic of normal deconstruction, and
copying over the flag onto its frames if need be.
This fixes screwdriver deconstruction.
## Why It's Good For The Game
Fixes#82503.
We can now deconstruct the table top separately again, AND get the right
materials back too.
## Changelog
🆑 00-Steven, SyncIt21
fix: Wrench table deconstruction gives the right materials again.
fix: Screwdriver table deconstruction only deconstructs the top again.
/🆑
## About The Pull Request
I've seen a few cases in the past where LateInitialize is done cause of
the init return value being set to do so for no real reason, I thought I
should try to avoid that by ensuring LateInitialize isn't ever called
without overriding.
This fixes a ton of machine's LateInitialize not calling parent
(mechpad, door buttons, message monitor, a lot of tram machines,
abductor console, holodeck computer & disposal bin), avoiding having to
set itself up to be connected to power. If they were intended to not
connect to power, they should be using ``NO_POWER_USE`` instead.
Also removes a ton of returns to LateInit when it's already getting it
from parent regardless (many cases of that in machine code).
## Why It's Good For The Game
I think this is better for coding standard reasons as well as just
making sure we're not calling this proc on things that does absolutely
nothing with them. A machine not using power can be seen evidently not
using power with ``NO_POWER_USE``, not so much if it's LateInitialize
not calling parent.
## Changelog
🆑
fix: Mech pads, door buttons, message monitors, tram machines, abductor
consoles & holodeck computers now use power.
/🆑
## About The Pull Request
Fixes#81052Fixes#58008
Setting weight class of items is now done via `update_weight_class`.
I updated as many occurrences of manually setting `w_class` as I could
find but I may have missed some. Let me know if you know of any I
missed.
This is done to allow datums to react to an item having its weight class
changed.
Humans and atom storage are two such datums which now react to having an
item in its contents change weight class, to allow it to expel items
that grow to a weight class beyond what is normally allowed.
## Changelog
🆑 Melbert
fix: You can't fit items which are normally too large for a storage by
fitting it in the storage when it is small, then growing it to a larger
size.
/🆑
## About The Pull Request
Remakes Battle Arcade from just about the ground up, with exceptions
taken for emagged stuff since I didn't really want to touch its
behavior.
The Battle Arcade now has stages that players can go through, unlocking
a stage by beating 2 enemies and the boss of the previous one, but this
must all be done in a row. You can choose to take a break between each
battle and there's a good chance you'll sleep just fine but there's also
a chance it can go wrong either through an ambush or robbery.
The Inn lets you restore everything for 15 gold and you can buy a sword
and armor, each level you unlock is a new sword and armor pair you can
buy that's better than the last, it's 30 gold each but scales up as you
progress through levels. They are really worth getting so it's best to
try to not lose your money early in.
The battle system is nearly the same as how it was before but I removed
the poor combo system that plagued the old arcade as one big knowledge
lock, now it's more just turn based. The game is built on permadeath so
dying means you restart from the beginning, but if you are going to lose
you can try to escape instead which costs you half of your gold.
Getting to higher levels increases the difficulty of enemies but also
increases the gaming exp rewards which could make this a better way to
get exp if you can get good at it.
Gaming EXP is used to increase chances of counterattacking but doesn't
give any extra health to the player.
I also removed the exploit of being able to screwdriver arcade cabinets
because people would do that if they thought they were on the verge of
losing to bypass the effects of loss. I instead replaced it with a new
interaction that the Curator's display case key can be used to reset
arcade cabinets (there's several keys on the chain so it made sense to
me), which I added solely because I thought Curators would be the type
of person to have run an actual arcade.
This is some gameplay
https://github.com/tgstation/tgstation/assets/53777086/499083f5-75cc-43b5-b457-017a012beede
As a misc sidenote, I also split up the arcade file just like how Orion
Trail was before, just for neat code organization.
The Inn keeper is straight up just a photo of my localhost dude, he's
not a player reference or anything it's not my actual character.
I also have no idea how well balanced this is cause I suck at it lol.
## Why It's Good For The Game
Battle Arcade is one of 3 last machines in my hackmd here to turn into
TGUI https://hackmd.io/XLt5MoRvRxuhFbwtk4VAUA?view
I've always thought the current version of battle arcade is quite lame
and lacks any progression, like Orion Trail I thought that since I was
moving this to TGUI, it would also be a perfect opportunity to revamp it
and try to improve on where it failed before, especially since the
alternative (NTOS Arcade) is also lame as hell and is even lamer than
HTML battle arcade (spam mana, then spam health, then just spam attack,
rinse and repeat).
This will hopefully be more entertaining and give players sense that
they are getting through a series of tasks rather than doing one same
one again and again.
## Changelog
🆑 JohnFulpWillard, Zeek the Rat
add: Battle Arcade has been completely overhauled in a new progression
system, this time using TGUI.
add: The Curator's keys can now reset arcade cabinets.
balance: You now need to be literate to play arcade games, except for
Mediborg's Amputation Adventure.
fix: You can no longer screwdriver emagged arcade consoles. Accept your
fate.
fix: Silicons can no longer play Mediborg's Amputation Adventure.
/🆑
---------
Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
## About The Pull Request
- Gloves and Shoes are now referred to in "pairs" rather than as "some".
- Meaning you now see "That's a pair of gloves" rather than "That's some
gloves"
- Makes it a tad easier to edit portions of an atom's examine text.
- Gives reinforced windows a more proper description.
- (I was examining random things to test and noticed its current
description was INCREDIBLY out of place)
- Fixes an extra space in bloody hand examination.

## Why It's Good For The Game
It's the little things that you tend to notice.
When referring to shoes, you _generally_ will say "a pair of shoes"
rather than "some shoes". It's just a tad more proper.
## Changelog
🆑 Melbert
spellcheck: Shoes and Gloves are now referred to as "a pair of" rather
than "some".
spellcheck: Reinforced Window's description is less out of place.
spellcheck: Fixed an empty space in examining a human's bloody hands.
code: It's a tad easier to exit an atom's examine text now.
/🆑
## About The Pull Request
Using these search regexes:
Ending in 0:
`addtimer\((.*),\s?(\d{1,3})0\b\)`
replacement:
`addtimer($1, $2 SECONDS)`
Two digit ending in odd:
`addtimer\((.*), (\d)([1-9])\)$`
replacement:
`addtimer($1, $2.$3 SECONDS)`
Single digit ending odd:
`addtimer\((.*), ([1-9])\)$`
replacement:
`addtimer($1, 0.$2 SECONDS)`
## Why It's Good For The Game
Code readability
---------
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
## About The Pull Request
Using these search regexes:
Number ending in 0:
`do_after\((\w+), (\d+)0,`
Replace:
`do_after($1, $2 SECONDS,`
Single digit number:
`do_after\((\w+), [1-9],`
replace:
`do_after($1, 0.$2 SECONDS,`
Double:
`do_after\((\w+), (\d)([1-9]),`
Replace:
`do_after($1, $2.$3 SECONDS,`
## Why It's Good For The Game
Code readability
## About The Pull Request
When it comes to deconstructing an object we have `proc/deconstruct()` &
`NO_DECONSTRUCT`
Lets talk about the flag first.
**Problems with `NO_DECONSTRUCTION`**
I know what the comment says on what it should do
b5593bc693/code/__DEFINES/obj_flags.dm (L18)
But everywhere people have decided to give their own meaning/definition
to this flag. Here are some examples on how this flag is used
**1. Make the object just disappear(not drop anything) when
deconstructed**
This is by far the largest use case everywhere. If an object is
deconstructed(either via tools or smashed apart) then if it has this
flag it should not drop any of its contents but just disappear. You have
seen this code pattern used everywhere
b5593bc693/code/game/machinery/constructable_frame.dm (L26-L31)
This behaviour is then leveraged by 2 important components.
When an object is frozen, if it is deconstructed it should just
disappear without leaving any traces behind
b5593bc693/code/datums/elements/frozen.dm (L66-L67)
By hologram objects. Obviously if you destroy an hologram nothing real
should drop out
b5593bc693/code/modules/holodeck/computer.dm (L301-L304)
And there are other use cases as well but we won't go into them as they
aren't as significant as these.
**2. To stop an object from being wrenched ??**
Yeah this one is weird. Like why? I understand in some instances (chair,
table, rack etc) a wrench can be used to deconstruct a object so using
the flag there to stop it from happening makes sense but why can't we
even anchor an object just because of this flag?
b5593bc693/code/game/objects/objs.dm (L368-L369)
This is one of those instances where somebody just decided this
behaviour for their own convenience just like the above example with no
explanation as to why
**3. To stop using tools to deconstruct the object**
This was the original intent of the flag but it is enforced in few
places far & between. One example is when deconstructing the a machine
via crowbar.
b5593bc693/code/game/machinery/_machinery.dm (L811)
But machines are a special dual use case for this flag. Because if you
look at its deconstruct proc the flag also prevents the machine from
spawning a frame.
b5593bc693/code/game/machinery/_machinery.dm (L820-L822)
How can 1 flag serve 2 purposes within the same type?
**4. Simply forget to check for this flag altogether**
Yup if you find this flag not doing its job for some objects don't be
surprised. People & sometimes even maintainers just forget that it even
exists
b5593bc693/code/game/objects/items/piggy_bank.dm (L66-L67)
**Solution**
These are the main examples i found. As you can see the same flag can
perform 2 different functions within the same type and do something else
in a different object & in some instances don't even work cause people
just forget, etc.
In order to bring consistency to this flag we need to move it to the
atom level where it means the same thing everywhere. Where in the atom
you may ask? .Well, I'll just post what MrMelbert said in
https://github.com/tgstation/tgstation/pull/81656#discussion_r1503086862
> ...Ideally the .deconstruct call would handle NO_DECONSTRUCTION
handling as it wants,
Yup that's the ideal case now. This flag is checked directly in
`deconstruct()`. Now like i said we want to give a universal definition
to this flag and as you have seen from my examples it is used in 3 cases
1) Make an object disappear(doesn't dropping anything) when
deconstructed
2) Stop it from being wrenched
3) Stop it from being deconstructed via tools
We can't enforce points 2 & 3 inside `deconstruct()` which leaves us
with only case 1) i.e. make the object disappear. And that's what i have
done. Therefore after more than a decade or since this flag got
introduced `NO_DECONSTRUCT` now has a new definition as of 2024
_"Make an object disappear(don't dropping anything) when deconstructed
either via tools or forcefully smashed apart"_
Now i very well understand this will open up bugs in places where cases
2 & 3 are required but its worth it. In fact they could even be qol
changes for all we know so who knows it might even benefit us but for
now we need to give a universal definition to this flag to bring some
consistency & that's what this PR does.
**Problem with deconstruct()**
This proc actually sends out a signal which is currently used by the
material container but could be used by other objects later on.
3e84c3e6da/code/game/objects/obj_defense.dm (L160)
So objects that override this proc should call its parent. Sadly that
isn't the case in many instances like such
3e84c3e6da/code/game/machinery/deployable.dm (L20-L23)
Instead of `return ..()` which would delete the object & send the signal
it deletes the object directly thus the signal never gets sent.
**Solution**
Make this proc non overridable. For objects to add their own custom
deconstruction behaviour a new proc has been introduced
`atom_deconstruct()` Subtypes should now override this proc to handle
object deconstruction.
If objects have certain important stuff inside them (like mobs in
machines for example) they want to drop by handling `NO_DECONSTRUCT`
flag in a more carefully customized way they can do this by overriding
`handle_deconstruct()` which by default delegates to
`atom_deconstruct()` if the `NO_DECONSTRUCT` flag is absent. This proc
will allow you to handle the flag in a more customized way if you ever
need to.
## Why It's Good For The Game
1) I'm goanna post the full comment from MrMelbert
https://github.com/tgstation/tgstation/pull/81656#discussion_r1503086862
> ...Ideally the .deconstruct call would handle NO_DECONSTRUCTION
handling as it wants, but there's a shocking lack of consistency around
NO_DECONSTRUCTION, where some objects treat it as "allow deconstruction,
but make it drop no parts" and others simply "disallow deconstruction at
all"
This PR now makes `NO_DECONSTRUCTION` handled by `deconstruct()` & gives
this flag the consistency it deserves. Not to mention as shown in case 4
there are objects that simply forgot to check for this flag. Now it
applies for those missing instances as well.
2) No more copying pasting the most overused code pattern in this code
base history `if(obj_flags & NO_DECONSTRUCTION)`. Just makes code
cleaner everywhere
3) All objects now send the `COMSIG_OBJ_DECONSTRUCT` signal on object
deconstruction which is now available for use should you need it
## Changelog
🆑
refactor: refactors how objects are deconstructed in relation to the
`NO_DECONSTRUCTION` flag. Certain objects & machinery may display
different tool interactions & behaviours when destroyed/deconstructed.
Report these changes if you feel like they are bugs
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
## About The Pull Request
Makes the Captain's Spare safe actually secure from being smashed open
now that it's been removed from a wall. Damage Deflection of 30 has been
added to it.
## Why It's Good For The Game
Because the Captain's Safe was moved off of the wall it's now vulnerable
to direct attack and projectiles way, way more than before and now
there's a lot of avenues to inflict AP damage, which is directly
subtracted from the armor value before application of damage. I've added
a damage deflection of 30 to make it
## Changelog
🆑
balance: Makes the Captain's Spare safe actually secure from being
smashed open now that it's been removed from a wall. Damage Deflection
of 30 has been added to it.
/🆑
## About The Pull Request
I misjudged `item_interaction` as being a non-combat mode only proc.
593f1eaee3/code/game/atom/atom_tool_acts.dm (L2-L12)
Which today I realized, well, it clearly isn't. With my changes, racks
don't let you beat them with an object even though you're in combat
mode.
Anyhow, this pr just makes it so it doesn't continue to the item placing
part when in combat mode.
## Why It's Good For The Game
Fixes an issue I caused, not letting you attack racks with objects.
## Changelog
🆑
fix: You can actually hit racks with objects when in combat mode again.
Importantly, painting them with spraycans like that works again.
/🆑
---------
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
## About The Pull Request
Removes the camera assembly structure middleman between the camera
wallframe and camera machine. All its behavior has been instead moved to
the camera, and I've tried to keep as much of the behavior the same as
before.
This also fixes the issue that camera assemblies had where, upon the
construction being finished, it would move itself into the newly
finished camera machine, therefore taking itself off a wall, therefore
deconstructing itself. This resulted in 2 piece of iron being in each
camera machine (except roundstart ones), and because camera machines
rely on the assembly inside of them for upgrades and such, upgrading
didn't work at all.
I've also made camera nets use defines (not in map) so it's easier to
find a list of them all, and tried to add autodoc comments to nearly
every var in camera code.
## Why It's Good For The Game
Removes copy paste and spaghetti code between structure and machine
camera, thus making it easier to work around with.
Closes https://github.com/tgstation/tgstation/issues/79019
## Changelog
🆑
fix: Cameras built in-round can be upgraded again.
fix: Deconstructing cameras now more consistently return to you the
upgrades inside of the camera.
fix: RD's telescreen can now properly see Ordnance cameras again.
fix: [Deltastation] Library art gallery no longer has an invisible
camera.
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
## About The Pull Request
### Alternate title: "Label Hoarding PR"
You ever just want to add sounds to a thing and then end up just
refactoring half of the damn thing?
Yeah.
Anyhow.
So in rough chronological order!
### Putting items in racks actually plays the sounds
Picking things up from racks plays their pickup sound, but putting them
on them doesn't. Just dropping it or putting it on tables does make the
right sounds. This seems to be because of a `silent` parameter in
`transferItemToLoc` that's set by tables but not racks.
```dm
(/code/game/objects/structures/tables_racks.dm, line 273)
if(user.transferItemToLoc(I, drop_location(), silent = FALSE))
(/code/game/objects/structures/tables_racks.dm, line 867)
if(user.transferItemToLoc(W, drop_location()))
```
Adding this makes it work just fine.
```dm
(/code/game/objects/structures/tables_racks.dm, line 867)
if(user.transferItemToLoc(W, drop_location(), silent = FALSE))
```
### Attackby single letter parameters, 1 instead of TRUE
Then, I noticed `attackby` just returns `1` to mean true after calling
`transferItemToLoc`, when we just have the more readable `TRUE`.
Similarly it uses a single letter parameter `W`, which on its own is
already unreadable, but is also mismatched with the parent proc using
`attacking_item`.
```dm
(/code/game/objects/structures/tables_racks.dm, line 859-868)
/obj/structure/rack/attackby(obj/item/W, mob/living/user, params)
var/list/modifiers = params2list(params)
if (W.tool_behaviour == TOOL_WRENCH && !(obj_flags & NO_DECONSTRUCTION) && LAZYACCESS(modifiers, RIGHT_CLICK))
W.play_tool_sound(src)
deconstruct(TRUE)
return
if(user.combat_mode)
return ..()
if(user.transferItemToLoc(W, drop_location()))
return 1
(/code/_onclick/item_attack.dm, line 133-136)
/atom/proc/attackby(obj/item/attacking_item, mob/user, params)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACKBY, attacking_item, user, params) & COMPONENT_NO_AFTERATTACK)
return TRUE
return FALSE
```
So we change it `1` to `TRUE` and `W` to `attacking_item` to make it
more readable!
### Don't let them try to put Abstract items
While looking over the table code, though, I also noticed it has a check
for the `ABSTRACT` item flag when placing items. Having tested this, we
add this too for consistency and to avoid awkward situations down the
line.
```dm
(/code/game/objects/structures/tables_racks.dm, line 272-273)
if(!user.combat_mode && !(I.item_flags & ABSTRACT))
if(user.transferItemToLoc(I, drop_location(), silent = FALSE))
(/code/game/objects/structures/tables_racks.dm, line 859-868)
/obj/structure/rack/attackby(obj/item/attacking_item mob/living/user, params)
var/list/modifiers = params2list(params)
if (attacking_item.tool_behaviour == TOOL_WRENCH && !(obj_flags & NO_DECONSTRUCTION) && LAZYACCESS(modifiers, RIGHT_CLICK))
attacking_item.play_tool_sound(src)
deconstruct(TRUE)
return
if(user.combat_mode || attacking_item.item_flags & ABSTRACT)
return ..()
if(user.transferItemToLoc(W, drop_location()))
return TRUE
```
### Split off rack structure attackby wrenching into wrench_act procs
But that's still kind of bad! But wait, we have procs for wrenching
actions, so it should really be in there.
So we move this to its own proc.
```dm
(/code/game/objects/structures/tables_racks.dm, line 850-855)
/obj/structure/rack/wrench_act_secondary(mob/living/user, obj/item/tool)
if(obj_flags & NO_DECONSTRUCTION)
return FALSE
tool.play_tool_sound(src)
deconstruct(TRUE)
return ITEM_INTERACT_SUCCESS
(/code/game/objects/structures/tables_racks.dm, line 857-861)
/obj/structure/rack/attackby(obj/item/attacking_item mob/living/user, params)
if(user.combat_mode || attacking_item.item_flags & ABSTRACT)
return ..()
if(user.transferItemToLoc(W, drop_location()))
return TRUE
```
### Split off rack item attackby wrenching into wrench_act procs,
include sounds
But the _item_ can also be deconstructed, and sure enough, it does the
same thing.
```dm
(/code/game/objects/structures/tables_racks.dm, line 920-925)
/obj/item/rack_parts/attackby(obj/item/W, mob/user, params)
if (W.tool_behaviour == TOOL_WRENCH)
new /obj/item/stack/sheet/iron(user.loc)
qdel(src)
else
. = ..()
```
So we give this the same treatment, and include a `deconstruct` method
rather than just having it be separate. We also play the tool sound for
consistency with deconstructing the rack structure.
```dm
(/code/game/objects/structures/tables_racks.dm, line 948-953)
/obj/item/rack_parts/wrench_act(mob/living/user, obj/item/tool)
if(obj_flags & NO_DECONSTRUCTION)
return FALSE
tool.play_tool_sound(src)
deconstruct(TRUE)
return ITEM_INTERACT_SUCCESS
(/code/game/objects/structures/tables_racks.dm, line 955-958)
/obj/item/rack_parts/deconstruct(disassembled = TRUE)
if(!(obj_flags & NO_DECONSTRUCTION))
new /obj/item/stack/sheet/iron(drop_location())
return ..()
```
Note: this makes it so it only deconstructs rack items on left click. I
think that's perfectly fine.
### Ancient code removal
Now we get to the fun part! Ancient code.
When removing the single letter parameters from `attackby` previously, I
thought I might as well remove other such instances while we're at it.
This gets us to `MouseDrop_T`.
```dm
(/code/game/objects/structures/tables_racks.dm, line 850-857)
/obj/structure/rack/MouseDrop_T(obj/O, mob/user)
. = ..()
if ((!( isitem(O) ) || user.get_active_held_item() != O))
return
if(!user.dropItemToGround(O))
return
if(O.loc != src.loc)
step(O, get_dir(O, src))
```
What the fuck?
Right so, this lets us click-drag-drop an item onto the rack, but only
for our active item. And it just drops it and steps it in the right
direction.
So we just, we just kill it. We just kill it.
You can just click on the rack to do functionally the exact same thing,
so we just kill it.
It's blocking us from dumping storage item contents, so just.
We Just Kill It.
We Just Fucking Kill It.
### Combat mode kicking
Anyhow! With that out of the way, we move to the finishing touches:
usage context and kicking!
While writing up context I was reminded that currently clicking on a
rack with an empty hand would just, kick it, regardless of combat mode.
```dm
(/code/game/objects/structures/tables_racks.dm, line 873-882)
/obj/structure/rack/attack_hand(mob/living/user, list/modifiers)
. = ..()
if(.)
return
if(user.body_position == LYING_DOWN || user.usable_legs < 2)
return
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src, ATTACK_EFFECT_KICK)
user.visible_message(span_danger("[user] kicks [src]."), null, null, COMBAT_MESSAGE_RANGE)
take_damage(rand(4,8), BRUTE, MELEE, 1)
```
This is awkward, misclick a few times and you've kicked it back into
item form.
So we make it only kick it while in combat mode to avoid this.
```dm
(/code/game/objects/structures/tables_racks.dm, line 880-889)
/obj/structure/rack/attack_hand(mob/living/user, list/modifiers)
(...)
if(!user.combat_mode || user.body_position == LYING_DOWN || user.usable_legs < 2)
return
(...)
```
### Usage context
Then finally! Usage context!
This part's easy, just copying over the logic from tables and making it
show deconstruct context for the rack structure and item and
construction context for the item.
```dm
(/code/game/objects/structures/tables_racks.dm, line 840-851)
/obj/structure/rack/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
. = ..()
if(isnull(held_item))
return NONE
if(!(obj_flags & NO_DECONSTRUCTION))
if(held_item.tool_behaviour == TOOL_WRENCH)
context[SCREENTIP_CONTEXT_RMB] = "Deconstruct"
. = CONTEXTUAL_SCREENTIP_SET
return . || NONE
(/code/game/objects/structures/tables_racks.dm, line 931-946)
/obj/item/rack_parts/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
. = ..()
if(isnull(held_item))
return NONE
if(held_item == src)
context[SCREENTIP_CONTEXT_LMB] = "Construct Rack"
. = CONTEXTUAL_SCREENTIP_SET
if(!(obj_flags & NO_DECONSTRUCTION))
if(held_item.tool_behaviour == TOOL_WRENCH)
context[SCREENTIP_CONTEXT_LMB] = "Deconstruct"
. = CONTEXTUAL_SCREENTIP_SET
return . || NONE
```
And then don't forget to register said context.
```dm
(/code/game/objects/structures/tables_racks.dm, line 834-838)
/obj/structure/rack/Initialize(mapload)
. = ..()
AddElement(/datum/element/climbable)
AddElement(/datum/element/elevation, pixel_shift = 12)
register_context()
(/code/game/objects/structures/tables_racks.dm, line 927-929)
/obj/item/rack_parts/Initialize(mapload)
. = ..()
register_context()
```
And that's all!
Now please remind me not to be _this_ comprehensive again.
Not for something that's less than thirty lines, at least.
Thanks.
## Why It's Good For The Game
Doing this in chronological order.
First off, it's wonky that putting say a toolbox on a table or the
ground makes sound but putting it in a rack is perfectly silent,
especially when taking it from the rack isn't. This makes it consistent
with tables.
Returning TRUE is more readable than returning 1. Single letter
parameters are awful for readability, _especially_ when inconsistent
with the parent parameters. This resolves those.
It shouldn't let you attempt to place items tagged with `ABSTRACT`, as
you shouldn't be able to place those. This makes it consistent with
tables.
We have procs for wrench actions, better to use those than implementing
your own wrench checks in `attackby`. This makes it do so.
It's just nice to have a deconstruction sound, so this makes
deconstructing the item also play the sound of the used tool.
The ancient rack code we're removing is entirely just a more awkward way
of doing what we can already do without it, it only let you drag your
active item onto them, _but you can just click_. It was awkwardly
implemented, and blocked anything from doing its own click-drag onto
surface thing like say storage dumping contents.
Usage context is just nice to have. This adds context for deconstructing
to the rack structure and for deconstructing and constructing to the
rack item.
## Changelog
🆑
refactor: Touched most of the code for racks. It should function almost
entirely the same save for what's noted here, please report any issues.
code: Wrenching moved to wrenching procs. Side-effect, rack items are
only deconstructed on left-click
sound: Items that have sounds make them when placed on racks, much like
when placed on tables.
sound: Rack items now make a sound upon deconstructing them.
fix: Racks no longer let you attempt to place abstract items like the
slap hand or water tank spray nozzles on them.
qol: Clicking on a rack no longer kicks the shit out of it if you don't
actually have combat mode on.
qol: Racks and rack items have hover tooltip usage context.
del: Killed ancient rack code for dragging your active item onto a rack.
Just click it does the same thing. This allows you to actually dump
items onto racks, though currently disorderly.
/🆑
## About The Pull Request
The gold and silver crates desc now accurately reflects NT corporate
greed
## Why It's Good For The Game
More lore correct crate
## Changelog
🆑
qol: Gold and silver crates now accurately reflects NT's greed
/🆑
## About The Pull Request
Wooden crates are now deconstructed with a crowbar. Cardboard crates are
now deconstructed with wirecutters. The context tips for deconstruction
are determined by the required tool now.
## Why It's Good For The Game
It doesn't make sense to deconstruct those crate types with a welder,
they would just burn. The logic for different cutting tool types was
already in there, and mentioned in a comment, but the variable was not
assigned to the sub types; I also changed the context tip to use that
instead of checking the held item for welder behavior.
## Changelog
🆑
add: Crowbars/wirecutters now deconstruct wooden/cardboard crates/boxes
/🆑
## About The Pull Request
Refactors a lot of the unused defines.
## Why It's Good For The Game
Refactors a lot of the unused defines.
## Changelog
Nothing player facing
---------
Co-authored-by: san7890 <the@san7890.com>
## About The Pull Request
Turns the varedited fluff item into its own item so it no longer has a
varedited icon & icon state.
## Why It's Good For The Game
We're varediting this fluff item 17 times on current tg master and it's
pretty bad. Varediting icon/icon state in maps should be discouraged and
hopefully banned later, it's not hard to make a subtype of an item so we
should be able to expect mappers to do that rather than this.
## Changelog
Nothing player-facing.
## About The Pull Request
Okay, so, turns out smoke machines, cigarettes, vapes and all sorts of
things intentionally unmix your mixes.
Why? For chaotic effects. Well sadly it just deletes chems from mixes
and makes them completely useless.
It also tends to have very little effect on deathmixes and moreso just
gimps you ability to use them for healing.
This is pretty bad, especially for machines like the smoke machine that
are specifically intended for chemists.
This PR entirely removes all uses of remove_any as well as the proc
itself from the game. It's just bad.
## Why It's Good For The Game
As it turns out, the game intentionally gimping your chem mixes just to
fuck with you is bad.
Especially when it's both obscure and not really all that fun for
gameplay.
## Changelog
🆑
balance: Smoke Machines, Showers, Vapes, etc will no longer arbitrarily
delete a random amount of the chems they are processing
/🆑