# Disclaimer: No Goon code was referenced or used in the making of this
PR
## About The Pull Request
[Design Document (Read this for more
information)](https://hackmd.io/@L9JPMsZhRO2wI25rNI6GYg/rkYKM9Yc6)
This PR adds Spies as a new roundstart antagonist type, inspired by
Spy-Thiefs from Goonstation.
Spies are tasked with stealing various objects around the station, from
insulated gloves to the black box, from the clown's left leg to the
bridge's communications console.
For every item stolen, the Spy is rewarded with a random item from the
Syndicate Uplink, plus some items uniquely available to the Spy. Stolen
items are then shipped off and sold on the Black Market Uplink, allowing
the crew - or maybe some other evil-doers - to get their hands on them.

More ideas for theft items and bounties are welcome.
## Why It's Good For The Game
See the design document for more information.
In short: Adds a solo antagonist which has less impact than your
Traitors and Heretics, but more impact than Paradox Clones and Thieves.
In other words: On the same tier as old traitors.
Seeks to embrace the sandbox aspect of antagonists more by having no
precise greentext objective, and instead some suggestions for chaos you
can embark in. Have fun with it!
## Changelog
🆑 Melbert
add: Spies may now roam the halls of Space Station 13. Watch your
belongings closely.
/🆑
## About The Pull Request
Allows polls to hide the voting statistics, both while the poll is
running and when it completes, so that people vote in isolation of
knowing what other people are voting for.
It looks like this:


This functionality is also available for custom votes triggered by
admins, if they want it.
## Why It's Good For The Game
Put simply, if likely to be controversially, sometimes people get upset
that an event with a 5% chance of happening occurs 5% of the time. Now
they really won't know what the chance was, only that it was picked by a
weighted choice.
Lack of knowledge about what other people are currently voting for
should also curb "meme votes" where people pile onto something they see
other people voting for, your vote in a poll with hidden stats can only
be influenced by your own opinion because you can't see what the crowd
is doing in order to join their bandwagon.
## Changelog
🆑
add: Displaying the voting statistics is now optional on a per-poll
basis, and is disabled for map voting.
/🆑
## About The Pull Request
This PR adds a !!!FUN!!! bomb payload to the blackmarket, which, upon
detonation, transmutates all terrain in a range like the dimensional
anomaly would. You can also select the dimensional theme to use by using
it in your hand.
I believe however, this thing should cost a fuckton to get and only show
up occasionally. 8k to 10k was my original idea, but I think that's
perhaps not high enough given its flagrant potential. Perhaps I should
also make it so the more dangerous themes yield a shorter range than
others. Suggestions are welcome.
Screenshot of what happens when you don't set the theme:

This PR also turns dimension themes into singletons so we access them
more easily. Nothing to write home about.
## Why It's Good For The Game
The black market could always use some extra thingy or two anyway, and
this thing could either be a source of emergent gameplay, or a recipe
for a disaster. Perhaps second to the Big Slappy for how funny it could
be.
## Changelog
🆑
add: Added a multi-dimensional bomb payload to the black market. It's
very expensive.
/🆑
## About The Pull Request
(Roundstart) Curators now get a 22.5% cut on credits spent on painting
patronages (divided by the number of curators). The service department
also gets another, 12.5% cut.
This PR also adds zoom in/out buttons to the painting canvas UI. So you
don't have to stare at a blob of such enormous squares while the UI is
open, which is only good when drawing.
Screenshot copypaste in paint:
## Why It's Good For The Game
The painting feature is mostly an end in itself, which is totally fine.
I've put quite a few quality-of-life changes into it through the years,
and I still want to kick in some stuff. However, I think the curator
should actually benefit from them in a more "mechanical" way.
Furthermore, I personally prefer them over the random written crap that
players make.
Also, as I said above, the canvas UI can feel a tad too big at times.
## About The Pull Request
Big changes:
- Participation is Valentines day requires consent, as consent is
important.
- When the event triggers, all valid players are automatically signed up
to get a random date. However if you're uninterested, you can opt out of
getting a date.
- This uses the same system as ghost role polling, so it's a
non-obstrusive screen alert + chat box entry.
- AIs are now given a zeroth law to protect their date.
- This does not override existing zeroth laws (for malf ais).
- This zeroth is law is worded in a way such that they are not
effectively malf AIs. Their other laws still apply, but not for
situations pertaining to their date.
- Cyborgs are desynced from AIs and are given similar zeroth laws to
protect their date.

Small changes:
- Valentines cards are now paper. Meaning you can write on them, stamp
them, or yes, burn them.
- Third wheeling is more codified than before. Third wheels get their
own antag datum type.
- The antag panel listing in roundend takes up significantly less room
for each date. Additionally, dates are now paired up with each other.
- Adds implementations for getting pronouns from mind datums.

## Why It's Good For The Game
It's 2024 and our Valentines day is sooo 2012.
I'm a big fan of Valentines Day, personally - it gives me the
opportunity to mess around with another player that I probably would not
otherwise mess around with, getting into shenanigans I would not
otherwise.
But as the years have gone by it's gotten pretty lackluster. Some people
like it as much as I do, but others ditch it entirely and ignore the
objectives.
And if you get paired with someone ignoring it, well, now you're out of
luck!
This is something I'm aiming to rectify by making it opt-in when it
triggers rather than forced. All the people participating will be
guaranteed to get someone who cares about the event as much, which makes
it more fun.
As for the silicon changes, there's been lots of confusion around
silicons and their dates, so I thought I'd fix it here as well.
Also, better late than never?
## Changelog
🆑 Melbert
add: Valentines Day now polls all players for candidates when it
triggers rather than forcing all players to be a Valentine. Consent is
important.
add: Valentine silicons now gain special laws pertaining to their date.
qol: Valentines Cards are now paper, so you can write on them, stamp
them, or burn them.
qol: Valentine's roundend report no longer takes up a massive amount of
space and also no longer sound so, so weird.
/🆑
## About The Pull Request
**1. Qol**
- Adds screen tips & examines for screwdriver & crowbar acts on BRM,
Refinery & Smelter
- Adds examines to display number of boulders stored inside a refinery &
maximum number of boulders it can hold. Right click screentip to remove
boulders
- Adds examines to display maximum number of boulders than can be
teleported by a BRM & screentips for interacting with wires
- More audio & visual feedback for refinery processing. If a boulder
requires multiple steps you will get a balloon alert saying "crushing"
for refineries & "smelting" for smelters along with a sound per process
tick(which is every 2 seconds so no need for cooldown) giving you a
better idea of what's happening in the pipeline
- BRM now will display all lights when the "Automatic boulder retrieval"
is on & turn off the lights when disabled along with examines giving you
a visual indicator of its state
**2. Code Improvements**
- Splits types of boulders into its own file `boulder_types.dm` for easy
maintainability
- Moves beacon for refinery machines into its own file
`boulder_processing/beacon.dm` for easy maintainability
- Moves the cooldown for processing a boulder `processing_cooldown` into
the refinery machine itself. Since 100's of boulders can be created per
round this var can take up memory quickly so by moving them into the
refinery machine it gives us some savings
- Compressed & merged procs such as `create_mineral_contents()` ,
`flavour_boulder()` etc with the vent code. These procs were only used
by the vent 1 time & by merging the code we removed if conditions to
check if a parent vent was passed or not(since now that's always the
case). Helped in removing boilder plate code
**3. Fixes**
- **Fixes vents always spawning "Small size boulders" & not medium, nor
large boulders.**
Once a vent generates a boulder it calls `flavour_boulder()`
084f56938c/code/game/objects/structures/lavaland/ore_vent.dm (L385)
however this proc also accepts 2 more params `size` which would always
default to `BOULDER_SIZE_SMALL` and `is_artifact` which is simply unused
in the proc
fb83617ff9/code/modules/mining/boulder_processing/boulder.dm (L219)
Therefore vents would always generate small boulders giving us no
varity. Now the boulder size is set depending on the vent size &
durability for each boulder is set to a random value between 2 & the
boulder max size giving us the flavour we actually wanted
- **Fixes "Expanded Gulag boulders" using "normal gulag material list"
when setting its custom materials.**
If you look at the `add_gulag_minerals()` proc it always picks from the
`gulag_minerals` list & accepts no params
fb83617ff9/code/modules/mining/boulder_processing/boulder.dm (L235-L236)
So when we try to pass params to this proc which in reality doesn't
accept any we were wasting our time doing this
fb83617ff9/code/modules/mining/boulder_processing/boulder.dm (L274)
And for our case `expanded_gulag_minerals` list was simply unused
because our proc doesn't care about it and it went back to just using
`gulag_minerals` list thus ignoring our list
fb83617ff9/code/modules/mining/boulder_processing/boulder.dm (L282)
As i said in the "Code Improvement` section when i moved boulder types
into it's own unique file this was fixed & now expanded gulag boulders
actually has a chance to spawn with bluespace crystals inside them
- **Fixes manual tapping of ore vents by hand not using a cooldown**
`produce_boulder()` accepts a cooldown var for when you need to manually
tap the vent by hand.
e8b5b52d54/code/game/objects/structures/lavaland/ore_vent.dm (L374)
This var was always set to FALSE because we never passed `TRUE` into it.
Not once here
e8b5b52d54/code/game/objects/structures/lavaland/ore_vent.dm (L124)
Nor here
e8b5b52d54/code/game/objects/structures/lavaland/ore_vent.dm (L131)
Now we just pass `TRUE` so tapping these vents by hand have a cooldown
- **Fixes BRM off icon state never being used**
When the room ran out of power it would still look on. Now we use that
state correctly
- **Fixes Automatic Boulder Retrieval by the BRM not actually being
automatic**
You must have noticed that once you do "Right click" and wait for all
the boulders it can teleport (determined by `boulder_processing_max`) to
be teleported it stops permanently after that. Even if more boulders get
generated it won't do anything, You have to again "Right click" &
retoggle automatic boulder retrieval on again, thus forcing someone to
stand there & monitor the BRM
Now once you set Automatic Boulder Retrieval on you can leave & forget.
It will teleport boulders as & when available thus enabling automation
properly.
- **Fixes boulders ejected from refineries via right click from getting
teleported back into the machines loc**
Fixes
https://github.com/tgstation/tgstation/pull/78524#issuecomment-1911666995.
The problem is refinery machines & the BRM keep track of all the
boulders that entered into it via the `boulders_contained` list.
Now we directly check `contents` for boulders so we don't have to
maintain 2 seperate lists to keep track of boulders. It also now uses
`processed_by` var of boulders to ensure refinerries don't retake in the
same boulder it just processed. Not sure where exactly the problem got
fixed but implementing these 2 measures fixed it regardless.
- **Fixes boulders with 0 durability[a.k.a steps] from getting ejected
out**
Fixes
https://github.com/tgstation/tgstation/pull/78524#issuecomment-1914551952.
So inside `process()` we constantly decrease the durability of the
boulder till it becomes 0.
0a496f180c/code/modules/mining/boulder_processing/_boulder_processing.dm (L159)
When it reaches 0 it calls `breakdown_boulder()`
0a496f180c/code/modules/mining/boulder_processing/_boulder_processing.dm (L164-L165)
This proc has a chance to reject the boulder if it could not process any
materials
0a496f180c/code/modules/mining/boulder_processing/_boulder_processing.dm (L219-L222)
**"Without resetting its durability"** over here
0a496f180c/code/modules/mining/boulder_processing/_boulder_processing.dm (L241)
So it ends up rejecting a "0" or worse -1 durability boulder. Now we set
the durability in `remove_boulder()` so regardless of what circumstances
the boulder is ejected it always gets a positive durability
- **Fixes BRM & Refinery from rapidly spitting out boulders in their loc
which causes lag in the long terms**
Fixes#81404. Basically even if there is 1 boulder sitting at a BRM's
loc or an refineries loc. Operations are haulted i.e. the BRM will not
teleport any more boulders & the refinery will keep their already
processed boulders inside till their locs are cleared from boulders.
This prevents large number of boulders from pilling up in long rounds
- **[Priority : High] Fixes refineries incorrectly removing materials
from processed boulders**
Fixes#81109. This bug is quite serious because it can't literarily
affect any random item with custom materials in game. This one line of
code over here can break the entire material economy as we know it
0a496f180c/code/modules/mining/boulder_processing/_boulder_processing.dm (L217)
**"DONT DO THIS"**. The `custom_materials` list is a **"read only"**
list & if you ever want to change it call the `set_custom_materials()`
proc with your new values but do not edit this list manually as it is
done here.
All lists related to materials are cached by the `SSmaterials`
subsystem. List values are cached & shared across multiple objects so
when you edit those values like here, you might end up effecting an
item/multiple items in some random corner of the map that shares this
list.
This also causes boulders with empty list of materials to get spawned at
random so yeah again plzz don't do this
**4. Refactors**
- Repathes `obj/machinery/boulder_processing/brm` -> just
`obj/machinery/brm`.
Even though semantically it looks nice that the brm is a subtype of
`obj/machinery/boulder_processing` from a code & operation perspective
they have 0 similarities.
1) The BRM does not accept boulders feed into it from a conveyer belt
unlike a refinery but instead picks boulders from `SSore` subsystem &
put it on the conveyer belt. This means procs for accepting boulders
such `CanAllowThrough()`, `breakdown_boulder()`, `accept_boulder()` etc
have no use in the BRM. Their just code clutter at this point
2) The BRM overrides `process()` & does not call its parent proc making
that code wasted
3) It has no use for silo materials & mining points making those vars go
to waste
With so much wasted code its better to just let go off all of it & just
make it a basic instance of `obj/machinery` making maintainence easy
- BRM now teleports boulders in a batch (batch size determined by
`boulders_processing_max` max value from upgraded parts is 7) with a
boulder appearing every 1.5 seconds rather than spawning all at once.
After a batch is processed it has a cooldown of 3 seconds before
repeating the process if automatic boulder retrieval is on. This stops
the conveyer belt from getting crowded with boulders and makes the
refining process more efficient.
With this BRM wires are removed because only it had only 1 wire
responsible for toggling boulder retrieval but now since this process is
automatic, we have true control over the timing of boulders spawned &
don't want to leave it in the hands of players
## Changelog
🆑
qol: adds examines & screentips for crowbar, screwdriver acts to BRM &
refinery machines
qol: adds examines about the number of boulders stored & processed to
BRM & refinery machines
qol: BRM now has its lights turn on/off depending on wether automatic
boulder retrieval is on/off for visual clarity along with examines
qol: refinery machines now display ballon alerts & plays sounds more
frequently when processing boulders for better feedback
fix: vents now spawn boulders of all sizes & not just small ones
fix: expanded gulag boulders now have correct materials in them.
fix: manual tapping of vents now has a cooldown applied as intended.
fix: BRM has its light turned off when area power goes off
fix: boulders ejected from refineries by hand no longer teleport all
over the place occasionally.
fix: refineries no longer eject boulders with 0 durability
fix: Boulders & refineries no longer pile up on top of BRM's &
refineries in long rounds. Their locs have to be clear of boulders
before they spit out more boulders to prevent a large pile of boulders
from causing lag
fix: sheets ejected from lathes no longer get rejected when inserted
back which could happen at random, no more boulders with empty materials
code: splits boulder types into its own file along with other items
code: merges & autodocs procs, vars related to boulders
refactor: repaths BRM to a simpler subtype
refactor: BRM now spawns boulders in batches(batch size can be increased
with upgraded parts) with a boulder appearing every second. After a
batch is processed a 3 second cooldown is applied to stop the conveyer
belt from clogging up, With this BRM wires are removed as there is no
need for timers to be attached to wires which intefers without our batch
processing timings.
/🆑
---------
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
## About The Pull Request
We'd finish a set of atom creation, then try and smooth those atoms The
problem is they might try and smooth with an uninitialized neighbor,
which wouldn't have its smoothing vars parsed.
This fixes that by pooling "to be smoothed" things into a list based off
the source of the init stoppage, which we then release when we're done.
Also fixes things staying in mapload, even during a sleep. This can
cause massive headaches so it's good to avoid.
This has a cost but it's minuscule (on the order of like 0.006s (6ms
over all of init), so I'm happy with it.
## Why It's Good For The Game
Closes#77040
## Changelog
🆑
fix: Maps loaded in after roundstart will no longer have broken
smoothing
/🆑
## About The Pull Request
adds a var to /subsystem that when toggled to true by an admin makes
/subsystem/ignite() start the profiler before calling fire() and then
stop the profiler after, this allows us to audit any individual
subsystems synchronous call chain.
## Why It's Good For The Game

when SSInput is focused

when SSair is focused
some subsystems are hard to profile performance issues for because
theres a billion procs downstream of them in the profiler and some of
them arent even unique to them (if a subsystem is spending half of its
time in some procs downstream of /_SendSignal() how could you tell). now
we can just do it. starting (and stopping?) the profiler itself is
expensive and this messes with the full round profiler but this is worth
it.
also this doesnt help with sleeping procs / timers created downstream of
that subsystem.
## Changelog
🆑
admin: admins/maintainers can now make the profiler focus on specific
subsystems by setting the subsystem var profile_focused to TRUE
/🆑
## About The Pull Request
This slightly modifies the polling subsystem. The sound/chat popup for a
new role is now only given on the first "stack" of a role signup.
Let's say 3 loneops roll at once (ty admins), you'll still get the toast
popup for 3x loneop rolls, but you'll only get one text highlight in the
chat, and only one audio stinger.
Even if the first 2 loneops don't have anyone sign up for it, using the
text or toast signup options will still sign you up for the last roll as
it completes. This shouldn't make signing up any harder, just quieter.
## Why It's Good For The Game
Less spam in chat. Less headset-blasting audio bleeps. Cool!
Closes#80998.
## Changelog
🆑 Rhials
fix: Ghost role polls should spam you less when multiple of the same
roll occur in succession.
/🆑
## About The Pull Request
Adds a new quirk for -2 points that requires you to be next to something
to examine them, like blindness but without the timer or actual
blindness itself.
## Why It's Good For The Game
For the player using the quirk, it's 2 points for losing the ability to
simply examine everything around you, making it harder to tell what
someone has in their hands when they are charging at you, for example.
You need to get up and close to things to see what they are.
For people being examined, it's just another possible excuse to be near
them, opening up plausible deniability for actions such as sleepy pens,
changeling stings, etc.
## Changelog
🆑 Atlasle, JohnFulpWillard
add: Adds the Touchy quirk, you need to be next to something to examine
it, for 2 extra quirk points.
/🆑
## About The Pull Request
This adds a proper cap for raw ectoplasmic cores, so they can actually
be refined now. Cool!
## Why It's Good For The Game
Broken thing need fix oops argh.
Closes#81369.
## Changelog
🆑 Rhials
fix: You can now refine ectoplasmic raw cores at the implosion machine
thing.
/🆑
## About The Pull Request
We currently have a list of point types that is meant to be
list(``DEFINE`` = name) but it's completely useless since the define is
just the name anyways. It's not used for anything, it has no purpose to
be this way. It seems more like a holdover from when there were multiple
types of research points (it was made for that purpose, even before
nanite points were a thing) but even for that, it serves no purpose.
I reworked it now to be the abbreviated name of the research point type,
de-hardcoding techwebs a little bit and removing the need for
downstreams to edit the techweb UI.
## Why It's Good For The Game
This at least looks better and makes more sense at people just looking
over it.
## Changelog
No player-facing changes.
## About The Pull Request
In short, we used a static list previously within the ore_generation
subsystem that held the amount of each ore that we expected a single map
to uniformly need. We held this number constant, since we were spawning
15 vents per map.
**Pros:** This worked flawlessly for Lavaland since 15 vents on a single
Z level makes it pretty densely packed map with a good amount of
map-based ore spawns, and it worked consistently.
**Cons:** 15 vents did not work well on Icebox however, even when split
so that the majority of the ores were spawning on the lower levels,
players did not feel like icebox spawned nearly enough ores and reported
the map spawning empty.
**Result:** As a result, we adjusted the ratio, so that we spawned
vastly more ores on the lower levels, now up to 4 vents on the upper
level, and 21 vents on the lower level. However, as we were still using
the ore distribution list based on lavaland, icebox vents were quickly
running out of ores to distribute between them, resulting in empty vents
-> which produced empty boulders -> which not only don't really let you
process them properly, but also just result in a metric ton of runtimes.
Icebox now has it's own list of ore distributions. These distributions
are now moved to a set of global lists as opposed to being saved on the
subsystem as a static list, which will make going and setting up new ore
distribution lists very very easy. Additionally, we've moved the setting
and getting of those ore_distributions over to the seedRuins proc, so
that we're actually setting the list of ores right before we actually
place them to make sure that the order that it's set is roughly as it's
needed, while still setting the list at the same time the
map-appropriate ruin placements are dropped in.
**Plus some misc cleanup fixes:**
`var/list/ore_vent_sizes` in SSore_generation wasn't being treated as a
similar budget list as `ore_vent_minerals`, since it `pick()`s off it's
own static size list. Which is honestly fine for this five seconds, I
can handle that later while we make sure the rest of the code code is
stable. In the meantime, I've just tweak it so that it's easy to see at
a glance how many of each random vent has spawned into the map.
Tweaked the description to not include anything about chemical
processing, as I'm planning on hitting on that in a part 2 PR that I'll
be picking back up after the freeze.
## Why It's Good For The Game
Cleans up the code a bit, but primarily fixes ores not spawning on
icebox as they should.
Should fix#81058.
Improves description to not mention mechanics that aren't in game.
Also, cleans up a piece of code that currently isn't serving much of a
purpose.
## Changelog
🆑
fix: Icebox should have it's ore distribution and it's ore vents fixed,
so that vents should now produce ore.
spellcheck: Boulder processing machines now don't mention things they
don't do.
/🆑
## About The Pull Request
Currently all ghost roles, when polling for players, shows a syndicate
poster. This is lame as hell, especially since most of the roles aren't
even Syndicate aligned.
This adds support to have your own icons for it, and adds one for the
Paradox clone since I already had an idea for it.
## Why It's Good For The Game
Paradox clones are not syndicate aligned and it does not make sense to
portray that to players, this looks much better, and hopefully soon
other antags will follow suite.

## Changelog
🆑
add: Paradox clones now have a bluespace stream instead of a syndicate
poster as their ghost poll icon.
/🆑
## About The Pull Request
You can now get station goals in a slightly better way over using a
`locate() in` call on a global list.
The Meteor Satellite goal no longer stores a giant list of ALL OBJECTS
in view. And now correctly only counts turfs.
## Changelog
🆑
fix: Meteor Satellites no longer erroneously count every piece of paper
as a protected turf.
fix: As a result the station goal is slightly more difficult
/🆑
---------
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
## About The Pull Request
With the recent changes to polling, it seems like it didn't properly
poll cultists, I fixed that and fixed other issues with it (such as it
telling players that they are signing up to BE a cult leader, when they
arent).
Also fixed the button to put yourself forward as cult leader, it
properly removes and gives itself when necessary.
## Why It's Good For The Game
Cult button works again how cool is that
Closes https://github.com/tgstation/tgstation/issues/80620
## Changelog
🆑
fix: Cultists can now vote for a Cult leader again.
/🆑
## About The Pull Request
This is an improvement on #80839 regarding how custom materials are set
on items, it's based on the following findings.
1. `set_custom_materials()` proc already comes with an prebuilt
`multiplier` var
1e8d511946/code/game/atom/atom_materials.dm (L11)
This means we can pass the machine's cost coefficiency directly to this
proc rather than creating our own list of materials with their values
scaled by the factor like so
1e8d511946/code/game/machinery/autolathe.dm (L192-L193)
We can instead just do `set_custom_materials(design.materials,
material_cost_coefficient)` without ever needing this list, thus making
code cleaner, with that the changes propogate to how `has_materials()` &
`use_materials()` procs are also used as we can now use their
`coefficiency` param rather than seeing it go to waste
2. All items custom materials will now always be integer values. With
this `SSmaterials.FindOrCreateMaterialCombo` now has better performance
because when computing the key for caching values like `1.5` or `1.7` it
will become just `1` and will point to the same cache thus reducing
memory usage
3. Materials are now uniformly split among all the contents of a printed
item from techfab or autolathe. What this means is items like the foam
ammo box printed from autolathe will have both the ammo case and their
40 bullets each set with custom materials such that their final sum
becomes equal to the design cost. For info on how that's done see the
documentation of `split_materials_uniformly` proc.
One downside of this proc is when items have a very small amount of
`custom_materials`(less than 2). In that case values like `0.8` or `1.5`
or `1.7` ends up getting rounded to 1 which means you end up getting
less materials when recycling than what you used for printing that item.
In this case You get 0.48 iron from both the box & it's ammo instead of
0.79 iron used for printing in tier1 autolathe(Or 0.50 for tier4
autolathe).
This shouldn't be an issue as you still can't make any profits from this
but at least everything in the box is now recyclable.
## Changelog
🆑
fix: items that contain recursive contents inside them (like foam dart
boxes from autolathes) now have their custom materials set to match with
its design cost rather than being nullified, meaning they are now
recyclable.
code: all custom materials are now integer values. Improved code for how
materials are used in techfab & auto lathe for printing
/🆑
## About The Pull Request
Stock market events are a system coded into the stock market system in
an attempt to keep the stocks unpredictable, at least on paper. They...
need work, I'm in full agreement on that, but I haven't been able to get
the energy to really fix stocks as of recently. I plan on going and
kicking events up and making them a lot cooler, but in the meantime,
I've refactored stock market events into their own datum type,
`/datum/stock_market_event`. This works like most similar event datum
style objects, where an event has a proc called when an event starts, a
proc called when an event ends, and a proc called between on subsequent
stock market subsystem firings.
This does some minor tweaks to the newscaster stories automatically
generated after an event fires, namely so that they can be produced
quickly while emphasizing the important part of the event, what material
is being effected, and a summary of what kind of behavior has happened
to the material stock.
Additionally, this made for a good excuse to do some code cleanup here
while I had the opportunity, swapping to `::` as opposed to `initial()`
calls where it seemed cleaner and more appropriate. This should make
adding new stock market events as well as more unique events that can
effect cargo and the round at large simple to do.
This PR shouldn't have any mechanical changes to how stock market
behaves in a live round.
## Why It's Good For The Game
Improves code quality of stock market, increases readability of stock
market events that have happened on the newscaster, and performs some
minor cleanup to the TGUI for the stock market while I'm at it, all
while keeping balance the same while we're still in the feature freeze.
Full disclosure, once the freeze is over I have some pretty easy numbers
tweaks planned to help significantly improve the stock market system
that I had layered on this branch, but we've shuttled them off this PR
for now to get this part ready to ship.
## Changelog
🆑
refactor: Stock market events are now their own objects, and are handled
by the stock market individually.
/🆑
---------
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
## About The Pull Request
This PR adds two new config options for quirks:
- *Flag* `DISABLE_QUIRK_POINTS`
- When enabled, disables quirk points balancing.
- When enabled, players can select positive quirks without first
selecting negative ones.
- When enabled, the quirk points balance visually hides itself on the
Quirks page.
- *Number* `MAX_POSITIVE_QUIRKS`
- Limits the maximum quantity of positive quirks which players can
select using the Character Preferences page.
- I ported this from the old `MAX_QUIRKS` define.
- When set to `0`, players won't be able to select any positive quirks,
and they won't appear on the Quirks page.
- When set to `-1`, players will be able to select any quantity of
positive quirks.
- When commented-out or undefined, the default is `6`.
- When set to `0` or `-1`, the positive quirk balance visually hides
itself on the Quirks page.
## Why It's Good For The Game
There is some downstream repositories asking for the quirks system to be
configurable. Additionally, I always find myself tweaking these values
on my own private servers and I thought it would be nice to share my
edits. Usually I was simply commenting-out sections of this code in
order to get the same result, so it helps to have an official way to
disable quirk points.
## Changelog
🆑 A.C.M.O.
config: Added two new config flags for quirks, DISABLE_QUIRK_POINTS and
MAX_POSITIVE_QUIRKS.
/🆑
This one's not like the last one, so much so that I'm not even going to
outsource the PR description to a robot this time!
Basically, **You should read the PR body before assuming that everything
is the same as last time. It's not.**
## Video Summary
Click the link below to see a video summary of the main features of this
pull request.
https://youtu.be/Aho2omR0mjY?feature=shared
## About The Pull Request
This pull request serves as a large rework of minerals produced by
mining, and by extension mining itself. I'll try and list each change
and it's associated nuance here.
### Ore Vents
The biggest addition to the game with ArcMining is **Ore Vents**. Ore
vents spawn as a ruin on the map, placing a randomized ore vent onto map
generation. Ore vents spawn in 3 different sizes, **Small, Medium, and
Large**. These vents will pick from a pool of materials they can
generate, and will hang out across the map. A player can use a mining
scanner to discover an ore vent, granting a small quantity of **mining
points** to begin with. Once scanned, ore vents will show what minerals
that ore vent will generate after they're fully tapped.
Scanning the vent again will trigger the extraction process. A small
drone will fly down, called the NODE drone, and buckle onto the vent.
Your job during wave defense is to protect the drone and to defeat waves
of randomly spawning mobs (dependent on if you're on lavaland or on
icebox). The quantity, duration, and time between waves is scaled to the
size of the vent you're protecting. Starting by scanning and protecting
lower tier vents earlier in the shift is a safer bet than doing a large
vent in the first few minutes. The drone has 500 health, and can take a
good few hits, but leaving it alone will cause it to meet an unfortunate
end quite quickly.
Cooperation can be your best asset, as mining with allies can greatly
help with wave defense, and mineral points are granted to anyone who
helps with defending the ore vent equally (So 500 * size tier,
regardless of how much help you receive). Once complete, the ore vent
will have a mining machine constructed on top of it, and will start to
dredge up **Boulders** from the earth automatically. More on boulders
later.
Ore vents can be located based on your mining scanner, and will provide
an appropriate audio cue based on if the ore vent has been discovered or
not, and once processed will no longer alert you to it's presence.
**Each station comes with a free vent that produces exclusively iron and
glass, free of charge.** This is to help with shifts where the station
may not have shaft miners to produce minerals, and to provide the
station with a baseline amount of minerals where none may exist
otherwise.
### Mineral Generation
Mineral generation has been completely reworked. Previously, Mineral
Generation had a flat 13% spawn rate in-game. Once minerals spawned,
they would also have a chance to propagate their minerals to nearby
tiles, resulting in a rather massive pool of minerals that could spawn
throughout lavaland on the whole.
This tweaks that, by making minerals in walls spawn based on their
proximity to ore vents on maps that use cave generation. Both the
probability, and quantity of ores spawning in walls is scaled based on
distance, with ore vents looking like large caches of ores found in
walls. This makes following ores found in walls and checking their
quantity of minerals spawned a good indicator of how close you are to a
nearby vent in-round.
This means you can collect some points form both discovering ore vents
first, as well as collecting their surrounding ores, turn those in for
mining points, and then trading them in for gear upgrades to more
effectively take on ore vents. As a result of tweaking the balance of
this, the total amount of ores spawned in walls overall has been
decreased. However, by making more of the process time based, we still
result in a mostly balanced finished product.
### Boulder Processing
On station, there are now three new machines. These are the BRM, the
Refinery, and the Smelter.
- The BRM acts as a teleporter. Instead of needing to carry boulders
back to the station, you can activate the BRM, and it will automatically
pick boulders to teleport back to itself. You can use this to teleport
boulders dredged up from lavaland onto the station for processing. **The
BRM will only lock on to boulders that are resting on an ore vent.**
Moving boulders back by hand will mean you'll have to haul it back by
hand.
- The refinery processes the non-metallic materials out of boulders.
This process sends the materials straight to the ORM, and collects
mining points from the ores smelted in the machine. Swiping with an ID
card lets you withdraw those points for your own personal account, but
remember that these points are for your whole team to share from. The
**Mining points obtained from this process is only 75% of the amount an
equivalent amount of ores would provide.**
- The smelter works nearly identically, however the smelter produces
metallic materials out of boulders instead.
- Once a boulder has had all of it's materials extracted, it's broken
down and deleted from the line. Otherwise, the boulder is spat out for
the next machine to process it (either the refinery or smelter).
- Once there's no minerals left in a boulder of any type, the refinery
or smelter will break the boulder down.
- Boulders **do not stack onto tiles with each other**, so they'll block
each other when pulled or when moving on a conveyor belt.
Boulders can also be processed by hand. Using a mining tool on a boulder
with right click will allow you to break down a boulder into it's
composite ores, but limits you to a maximum of 10 ore per boulder, where
the full amount can be extracted using the proper processing machines.
Also, processing by hand does deal small amounts of stamina damage over
time, do breaking a full large boulder can be particularly taxing.
Additional Boulder Processing Machines can be built, with the BRM board
being obtained from the Protolathe, while the Smelter and Refinery
boards being obtainable from the Autolathe instead. A _boulder
processing beacon_ can also be obtained from the mining points vendor as
a reward to assist with boulder processing. Boulder processing beacons
can be used to spawn in a new BRM, refinery, and smelter on the tile the
user is standing on, however **you'll still need to link them to the
ORM**!
All three machines can be upgraded with Stock Parts, allowing for **more
boulders to be processed at a time**. It does not, however, increase the
amount of minerals received from boulders, or points earned.
### Mining Borg Tweaks
Mining borgs have been given some minor adjustments to compensate for
the changes to mining. Their mineral scanner, which now has an active
component to gameplay, is now a module as opposed to built into the mob.
This module allows for the same ability to discover and start waves of
monsters to fight.
Mining modules will find that their PKA now has a total of 90% mod
capacity as compared to the 80% they had before, to allow for more
robust defense of ore vents.
In addition, all borgs and AIs can interact with the BRM for boulder
collection.
### Mining Mech Tweaks
Mining Mechs have had their utility tweaked as a result of these changes
as well. Mineral scanners to be used on mining mechs now have a larger
radius by comparison to their handheld cousins. Similarly, it now has an
active scanning button, which will actively discovery nearby ore vents.
To begin wave defense, you will need to hop out and scan a second time
however, so that you can properly accept the risks of drawing a horde of
bloodthirsty wildlife towards you and your companions.
Mechs can also manually process boulders, similar to mining tools using
their drill.
### Golem Tweaks
Golems, being more gentle and less aggressive than humans, while being
made out of LITERAL ROCKS, have a greater need to secure access to ores
and minerals to eat. As such, they have adapted to be able to do two new
things:
- Golems may now right click ore vents to be able to manually haul a
boulder out of the vent. This costs a hefty amount of stamina, but it
allows for golems to avoid combat during regular gameplay.
- Golems may now left click a boulder with an open hand in order to
manually process a boulder like a pickaxe. While not faster, it is
consistent and prevents golems from starving if they have access to a
vent, but no ores, somehow.
### Gulag Tweaks
The labor camp, being a camp for rehabilitation and ~~excessive manual
labor~~ has been tweaked. Boulders now replace the random minerals
located on their island, and to acquire their prizes inside, much be
excavated and then broken out of the rock. Now YOU TOO can excavate
minerals and become a true mineral hero by working your way to freedom.
### Mining Point Changes
As a result of fewer mining points being available across the map due to
the new ore spawning mechanics, and the shift in how and when ores will
be coming in, almost every progress based mining point cost has been
reduced by around 10-20%. Many numbers are still subject to change at
present, but the idea is that core progress unlocks should be made a bit
more available earlier in the round before players can start to solo or
duo larger or more difficult ore vents, after which they'll be rolling
in ores.
### Rarities
Every once in awhile, an unusual boulder will get hauled up from the
mineral rich depths of lavaland. These **Artifact boulders** can
occasionally produce rare items, but for now they've mostly just been
pulling up **Strange objects** for science. Nanotrasen Natural Sciences
department will reward you extra points to be collected by boulder
processing machines for successfully extracting one. In the future, this
opens up a passive reward space that mining can reward to the station,
like providing cytology DNA samples, ancient seeds, or other artifacts.
### Misc notes
- Boulders can be stored in all varieties of ore boxes (ground, mech)
should you choose, however as mentioned it's best to leave them where
they spawn and teleport them to the station for convenience.
- Maps that are not subject to cave generation will find that they are
largely untouched in terms of mineral balance.
- Future or existing ruins can now be tweaked to have a mineral balance
cost, as the ore vent ruin does. This will allow us to spawn in more
interesting ruins for pre-made combat challenges.
- There are unique ore vents that spawn across the map, that will summon
a boss mob relevant to that map. If the boss mob is defeated, that vent
will spawn large boulders pulling from every possible ore type that can
spawn. Not for the faint of heart!
- Similarly, the number of ore vents and mineral budget is now
adjustable in the cave generation procs, so maps may spawn with more or
less ore vents as desired for balance.
- Artifact boulders opens up a LOT of room for possible future content
like archaeology, xenoarch, artisci, and other design spaces!
- Megafauna STILL SPAWN ON THE MAP. They just happen to spawn in
addition to boss ore vents.
- **I'll add more to this as I get asked questions and remember things,
this is a huge PR and I'm confident I've missed at least something**
## Why It's Good For The Game
I outlined a lot of this in #78040, so I'll try and keep this relatively
snappy this time, while noting that I've made some concessions to make
the whole system a lot more playable while not trying to break out
design decisions that are at the end of the day, better for the game and
the overall resource balance in round.
Minerals are a very poorly balanced system, and have been since their
inception many years ago. We heavily rely on mineral balance in round,
and yet we've really only balanced it by introducing so much supply that
there's no equivalent exchange for materials that doesn't just heavily
flood the exchanged material. For example, items printed from materials
that are otherwise considered "rare" on master exist in such quantities
and they'll never practically run out in our allotted 90 minute time
slot design. This PR adjusts how ores spawn to a point where we can
minimize the amount of ores that need to exist on the map for mining to
be able to progress, while still providing enough resources for the
station that it covers the needs of the station adequately.
Miners will need to be more strategic about what resources they've
collected, and be able to make decisions about which vents are worth the
risk of attempting to fight, how to prepare for a wave defense, and when
to head back up for upgrades, while finally giving them at least some
kind of incentive to work together and use different equipment.
Resonators make cleaning up the caves around vent easy, sandbags set up
easy defenses for your vent, mechs can serve as a wider range radar
while mining, all while still providing a new gameplay loop to mining.
By limiting the amount of ores that can enter the round from the
massive, massive amounts that were coming into the round beforehand (see
#78346 ), we can make ore processing more meaningful by adding more
gameplay to the processing of minerals. I have some plans for that,
however this PR already got bloated really REALLY badly due to scope
creep and the number of intersecting systems that rammed into each other
to make this PR possible. So that'll be next. Plus, as I've mentioned,
we open up places for ore processing to find fossils, relics, and other
things that can implemented down the line.
Overall, I don't expect this PR to save or kill ore balance, but we gain
a LOT more control over it through the use of our mining defines
attached to this PR, and at the end of the day, that's a great place to
start off of.
## Changelog
🆑
add: Added ore vents. Scanning them with mining scanners shows what
minerals they contain. Scan again to fight off a horde of beasts as your
drone assistant excavates the vent, so the ore vent will produce mineral
boulders!
bal: Ores that spawn in walls now spawn based on their proximity to ore
vents, with their chance to spawn and their minerals contained scaling
from low to high.
add: Added the BRM, Refinery, and Smelter. These pieces of equipment are
used to process ore boulders into minerals for the station. Stock Part
upgrades allow more boulders to be processed at one time. They collect
mining points as well, to be redeemed with an ID card swipe.
add: Boulders are teleported to the station via the BRM if left
untouched. Boulders can also be cracked open for a reduced amount of ore
using pickaxes or golems hands.
add: All stations come equipt with a pre-excavated ore vent, which
produces a basic supply of iron and glass only. Scan other vents for
your critical resources!
add: Look there's a shit ton of changes on mining, for more detail check
out the Pull Request: https://github.com/tgstation/tgstation/pull/78524.
sound: New sounds and noises for your high octane factorio-like
gameplay!
image: All new boulder sprites for the new minerals and rocks added to
the mining gameplay loop, as well as mining machines!
image: Overlays appear over vents when scanned to let you know their
contents at a glance when actively scanned with any mining scanners.
/🆑
---------
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: Jacquerel <hnevard@gmail.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
## About The Pull Request
Nukies were using ``get_machines_by_type`` in ``assign_nuke`` to get the
nuke and set its code, which doesn't work for clown ops because they use
a subtype. This fixes it by replacing it with
``get_machines_by_type_and_subtypes`` instead.
while I was messing with clown op code I also made it a little bit less
copy paste

## Why It's Good For The Game
Clown ops now get a code to their nuke rather than it staying as
'ADMIN', pretty cool!
Closes https://github.com/tgstation/tgstation/issues/78306
## Changelog
🆑 Momo8289, Pepsilawn, Sinsinins, JohnFulpWillard
fix: Clown ops now get a code set for their nuke.
/🆑
## About The Pull Request
Situation: areas have a list of all turfs in their area.
Problem: `/area/space` is an area and has a 6 to 7 digit count of turfs
that has to be traversed for every turf we need to remove from it. This
can take multiple byond ticks just to preform this action for a single
space rune
Solution: split the list by zlevel, and only search the right zlevel
list when removing turfs from areas.
replaces `area.get_contained_turfs()` with a few new procs:
* `get_highest_zlevel()` - returns the highest zlevel the area contains
turfs in. useful for use with `get_turfs_by_zlevel`
* `get_turfs_by_zlevel(zlevel)` - returns a list of turfs in the area in
a given zlevel. Useful for code that only cares about a specific zlevel
or changes behavior based on zlevel like lighting init.
* `get_turfs_from_all_zlevels()` - the replacement for
`get_contained_turfs()`, renamed as such so anybody copying/cargo
culting code gets a hint that a zlevel specific version might exist.
Still used in for loops that type checked so byond would do that all at
once
* `get_zlevel_turf_lists()` - returns the area's zlevel lists of lists
but only for non-empty zlevels. very useful for for loops.
The area contents unit test has been rewritten to ensure any improper
data triggers failures or runtimes by not having it use the helpers
above (some of which ensure a list is always returned) and access the
lists directly.
## About The Pull Request
### Reftracking BS
Alllright so reftracking is slow, really really slow.
That's a problem for me, both because I want it to be fast so I can more
efficiently torture players by running it on live, but also because it
impedes both local and CI runs.
So I've set out to micro optimize the DoSearchVar proc, one of the
hottest in the game.
I've done this in a few different ways.
#### The simple shit
Removing redundant proc args
Yeeting assoc arg setting (extra cost)
Moving if statements around to prioritize the more common case
Ignoring empty lists.
#### The not simple shit
Throwing our snowflake list checking into the sun
(Background, byond has some special lists that cannot be accessed like
an assoc list, trying to will lead to runtimes)
The way we handle this involves inspecting their ref string, and it eats
a LOT of time.
Faster then to mark all the lists we know are special by var name, and
then use try/catch to detect and silence anything that sneaks through
(this is on the order of like 1/3 per run, kinda curious what they are
tbh)
Thanks to MSO for the idea for this btw.
Removes the vars and logic that tied ref searching to clients.
It's not how this code is used, and it slows everything else down for
really no reason
Added support for handing in a known "hanging reference" count, and then
searching for that.
This lets us early exit the ref search if we find everything we were
looking for, which is REALLY powerful, and why I asked for refcount() in
the first place.
### Harddel Fixes
[Fixes some harddels w gulag stuff born of the 515 one way ref
issues](046d7daa03)
[Ensures proximity cameras clean their ref to their proximity datum if
it's
deleted](ff607e9ccb)
[Deleting a pipe connected via the gas_machine_connector datum to a
machine should also delete that machine (harddel
fix)](9eecca22e7)
## Why It's Good For The Game
All this combined speeds up refsearching massively, on the order of
hundreds of seconds, and makes it far less time consuming for both CI
and running on live.
I'll be bullying some servers semi soon, want to see what I can cut out.
Atomizing out of #78524 as a result of that PR being too big and this
was quite easy to do.
## About The Pull Request
This adds a debug (admin) command that allows you to stop all weather
effects that are going on across the map in a given instance. This is
useful for when you are testing something on lavaland and need the storm
to stop, or if you otherwise had some other kind of weather effect
interfering with testing something. It's worth noting this directly
calls end() on the active weather effect, meaning that for more
complicated weather that may have different side effects, it may need
some extra finess, but as of current writing no weather does anything
interesting in their wind_down() procs.
## Why It's Good For The Game
God weather is so annoying while testing lavaland, plus this is just
straight admin and testing tooling so there's no harm.
## Changelog
🆑
admin: Added a new admin verb that ends all active weather within the
weather subsystem.
/🆑
## About The Pull Request
Recently, I chatted with others about how few station traits are rolled
on a round by round basis - about 59% of the shifts go without either
positive or negative traits for example - and how the mild most of these
traits are (not a bad thing per se), which results in an underwhelming
feature, despite the more interesting bits of it. So, after sharing
opinions, I've decided to make this PR to increase the rolls and odds a
bit.
EDIT: After reading comments and taking some time to think this
thoroughfully, I've decided to push the probabilities back a little in
favor of a simple budget system for station traits, to allow for smaller
things to only count as half a station trait. This mean smaller traits
won't necessarily stop "better" ones from rolling, or at least allow for
plentier permutations of traits that do not affect the round TOO much.
I've also reduced the weight of the glitched pda beeps trait from 15 to
10, the same of scarves, wallets and colored assistant jumpsuits.
## Why It's Good For The Game
I believe the current odds of station traits to be a smidge low, and
that the lack of any sort of cost-budget for station traits to hurt the
rarer, more interesting traits (and the feature in general) if the more
common, milder ones take just as much space. It's totally within the
spirit of the feature to have small, niche traits, though they can get
quite boring pretty fast on their own, so what I'm saying is that their
cost should stay low so that other traits can roll.
## Changelog
🆑
refactor: Introduced a simple budget system to station traits, so that
smaller things only count as half a trait, for example.
balance: Increased the odds and maximum number of station traits that
can be rolled each shift.
/🆑
## About The Pull Request
Goes through and changes some `in area` / `in a` loops to use
`get_contained_turfs` to cut down on `in_world` loops. Saves some free
lag.
## Changelog
🆑 Melbert
fix: Some things which affect everything in an area are less laggy, the
"all lights are broken" station trait especially
/🆑
## About The Pull Request
After https://github.com/tgstation/tgstation/pull/80628, these shouldn't
be needed anymore right?
## Why It's Good For The Game
Cleans up some vestigial code
## Changelog
EDIT: Not player-facing.
Productionizes #80615.
The core optimization is this:
```patch
- var/hint = to_delete.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
+ var/hint = to_delete.Destroy(force) // Let our friend know they're about to get fucked up.
```
We avoid a heap allocation in the form of copying the args over to a new
list. A/B testing shows this results in 33% better overtime, and in a
real round shaving off a full second of self time and 0.4 seconds of
overtime--both of these would be doubled in the event this is merged as
the new proc was only being run 50% of the time.
We frequently have issues with data loss in our long storage .json files
for various reasons, such as the file being completely blanked out on
write etc.
This introduces a system that tries to safely handle that by saving the
known working json file into a backup that will be loaded in the case a
write fails.
This system queues updates in order to send through to the next tick.
This is an improvement over the existing implementation of photo albums
and photo frames (I think all persistence, even) which do not save until
the end of a properly rebooted round, but not during a server crash.
Also saves the jsons in pretty prints, which make them easier to read
but especially make them easier to diff in a git repository, which MSO
wants to setup (and hopefully make public so I can make a dashboard on
bus.moth.fans for looking at photo albums and their history, which is
something I've wanted to do for a very long time).
## Changelog
🆑
refactor: Photo albums and photo frames are now more resilient to data
loss, especially when a server crashes.
/🆑
## About The Pull Request
this pr integrates the bot path huds to ai controllers and move loops to
allow basic bots to display their paths in the hud.
also closes#80280 and closes#80330
## Why It's Good For The Game
basic bots now can display their path on huds
## Changelog
🆑
add: basic bots can now display their paths on huds
fix: medbots can research healing again
/🆑
## About The Pull Request
This PR adds a new PDA program to the supply category, which allows
users to redeems coupons for various cargo packs (mostly goodies), like
the ones also found at the bottom of cig packs.
How it works is fairly simple:
- Once installed, the modular computer subsystem will periodically, at a
3-5 minutes interval, generate a coupon code datum associated to a plain
text code, which is sent out to everyone with the program installed.
- The user can then open the program and insert the text into an input
box to redeem the coupon code, which is then associated with their bank
account.
- He will then have to find a photocopier, and tap it with the PDA to
print the coupon. Only one coupon can be printed. Photocopier fees
apply, so it'd cost 5 creds to the average assistant to print the
coupon.
- He can then insert the coupon in a cargo console and order/reuest the
associated pack (same deal as cig coupons).
- Some coupon codes however, especially those with juicer discounts,
will expire after a while if not printed.
Albeit mostly innocuous, the program provides negative Detomatix
resistance, slowly fills the computer file storage with trash files with
each redeemed coupon, and halves the download speed of new apps. Not
really the cleanest ware out there.
This PR also extends coupons to several non-goody packs, since they have
been privately buyable for over the last couple years now. Some packs
get discounts less frequently however, with those in the uncommon
category being roughly 1 in a 12 chance and the rare being 1 in 50.
Here's a screenshot of the UI (outdated, I've reduced the height from
500 to 400 and the notice box tip to specify the right click):

Fun fact: Right now, the odds of a 75% discount coming from the Coupon
Master for the 1.000.000 credits bycycle pack are roughly 0.0012%, while
that of a 50% for the same pack, from a cig pack coupon are 0.0042%.
## Why It's Good For The Game
These last couple days I've been wanting to test myself at making simple
UIs, as well as contributing to the modular computers feature, which has
started to become pretty neat ever since PDAs were reworked into a
subtype of it.
Beside, coupons are a very small feature limited to the bottom of
cigarette packs (also possibly cursed) in the current state of affairs.
Cargo is filled with packs that are niche or fluff. Modular computers
also has those little things that, while interesting, do not contribute
a whole lot. Maybe this is one of them, but I guess free* coupons are
always a big W.
## Changelog
🆑
add: Added the 'Coupon Master' program for the PDA. Install it to
receive periodical, redeemable coupons for several cargo packs. Requires
NTnet connection and the messenger enabled to work.
add: Coupons are no longer only limited to goodies, but may also apply
discount to some other packs as well.
/🆑
<sup>*minus the photocopier fee</sup>
---------
Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
Nested tally is overkill and requires that this be handled especially in
Superset. Version is not updated as the data for this is the exact same.
I recommend running this query after merge (CC @MrStonedOne):
```sql
UPDATE feedback SET key_type = 'tally' WHERE key_name = 'quirks_taken'
```
## About The Pull Request
Fixes#80534
```
[2023-12-23 19:23:03.446] RUNTIME: runtime error: Cannot read "sentience fun balloon".layer
- proc name: poll candidates (/datum/controller/subsystem/polling/proc/poll_candidates)
- source file: code/controllers/subsystem/polling.dm,90
- usr: Bob Stange (/mob/dead/observer)
- src: Polling (/datum/controller/subsystem/polling)
- usr.loc: the floor (166,47,1) (/turf/open/floor/iron)
- call stack:
- Polling (/datum/controller/subsystem/polling): poll candidates("Would you like to be test?", "Sentience Potion Spawn", "Sentience Potion Spawn", 100, "shuttle_denizens", the sentience fun balloon (/obj/effect/fun_balloon/sentience), /list (/list), "sentience fun balloon", "Sentience Potion Spawn")
...
```
Classic off-by-one error, except instead of a mathematical error it was
a logical error.
`/datum/controller/subsystem/polling/proc/poll_ghost_candidates_for_mobs(...)`
called `poll_ghost_candidates` with an incorrect number of args,
omitting the `flashwindow` arg and causing `pic_source` to be passed as
`flashwindow` and `role_name_text` to be passed as `pic_source`.
Since `role_name_text` is a string, this causes the above runtime as the
code tries to access the `.layer` member of the string. Which strings
don't have. Because they're strings.
I added the missing `flashwindow` arg and tidied up the base proc call a
touch back at the sentience balloon layer, since I noticed it was using
named args out of order which - while valid - could cause issues in any
future refactor or copypasted code.
## Why It's Good For The Game
Sentience Fun Balloons work again!
## Changelog
🆑
fix: Fixed an issue with polling ghost roles to control multiple mobs
that prevented Sentience Fun Balloons from working as intended.
/🆑
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->
## About The Pull Request
<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->
This reworks cyborg lover to be more interesting. Taking this quirk will
start the user off with a robotic limb. The user gains mood buffs by
being around silicon based lifeforms and loses mood by being around
organic based lifeforms.
Additionally, they can gain mood buffs by replacing all of their limbs
to their silicon counterparts but can also gain a massive mood debuff if
they lose or replace their starting robotic limb with an organic one.
The idea being here that they hate organics and seek to become robotic
Also, transhumanists won't be scared of people who have two or more
augments.
## Why It's Good For The Game
<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->
Cyborg lover isn't really all that interesting since it's just a basic
mood buff upon clicking on a silicon.
This makes it more interesting by making it a dynamic between silicons
and organics and may adapt the playstyle of anyone choosing to take this
perk as they will need to stay away from organics to avoid mood debuffs.
## Changelog
<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->
🆑
balance: Cyborg lover has been replaced with Transhumanist.
Transhumanists start with a robotic limb and get mood buffs by being
near to silicon-based lifeforms. However, they get mood debuffs by being
near organics, so there is a tradeoff to taking this quirk. The cost for
this quirk has been reduced from 2 to 0.
/🆑
<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
---------
Co-authored-by: Watermelon914 <3052169-Watermelon914@users.noreply.gitlab.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
## About The Pull Request
Revived my old PR https://github.com/tgstation/tgstation/pull/68901
Replaces the annoying tgui alert popup "Do you want to be X? | Yes | No
| Never for this round" that is hard to read and steals window focus,
with a nice clean alert in the top right that counts down. If it's the
same event/mob they stack with 2x, 3x, etc. It also shows how many
candidates/ghosts are signed up.
The poll alerts have screentips too, they countdown and show if you're
signed up, how many people are signed up, if you chose "never for this
round" (which is cancelable)
## Why It's Good For The Game

Way easier to see what role is available, you get a nice pic of the role
and get it's name in big text, you can cancel "never for this round",
and you can cancel signing up for a role before the timer is up
## Changelog
🆑
refactor: Ghost roles now offer ghosts a clickable poll button. Ghosts
can select a role, deselect it, alt-click it for "Never For This Round",
can cancel "Never", can see the countdown, and can see how many other
people are signed up for the role poll.
/🆑
## About The Pull Request
At roundstart when the intercept report is sent, two announcements are
created at the same time. It's loud and overlaps. This combines them
into a single announcement.
Before:

After:

## Why It's Good For The Game
Two Centcom or any other announcements playing at the same time
(especially with two different sound files) can be annoying and the
sounds distort each other.
## Changelog
🆑 LT3
qol: Roundstart intercept report and security level announcements are
combined into a single announcement
/🆑
## About The Pull Request
as we added a command role that isn't a head of staff, itd be good to
untie some checks from the command department
so i added a job flag for that, and moved what made sense to different
traits that are added to head of staff minds
## Why It's Good For The Game
revs (the gamemode not the players) shouldnt care about the bridge
assistant existing
## Changelog
🆑
fix: bridge assistant no longer passes some head of staff checks
qol: if you steal a command member's liver, you can now sabre better!
/🆑
## About The Pull Request
See the title.
## Why It's Good For The Game
Mothblocks wanted map votes to not be simple winner take all and wanted
it to be randomly chosen based on votes.

## Changelog
🆑
add: Map Votes are now weighted random.
add: Custom Votes can now take advantage of Weighted Random winner
selection
del: Removed Herobrine from the game
/🆑
---------
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
## About The Pull Request
adds a station trait which adds a new role, the bridge assistant
he is designed to help commandeer the bridge and help out other heads
when needed. he is armed with the mini energy gun (the one heads used to
have on kilostation), a flash, a toolbelt (with an inducer), some cool
shades and a swanky scarf.
as he is a nerd he is weak and unable to twohand weapons, preventing him
from wielding the fire axe.
currently he does not have a mindshield but he cannot roll antag
he currently has access to the bridge, announcement console, eva,
teleporter, gateway, maint, and a weapon permit (somewhat (not really
other than for nerds) interestingly this is the first job that isnt
assistant that doesnt have access to any lathes, so he doesnt have orm
access unlike all the other jobs (except assistant))
the trait also makes a coffee machine spawn on the bridge
here is some useful art of your role

and ingame screenshots



## Why It's Good For The Game
Adds upon the station trait job system with a straight forward role that
IS just a human (unlike the cargorilla), and is pretty basic with no
custom assets or whatever other than hud icons
Having the bridge assistant in some rounds seems like a neat way to
protect it since it gets fucked up in like half the time, while also not
having enough mechanical depth or gameplay as to warrant it as a
permanent role
## Changelog
🆑
add: Bridge Assistant job accessible from a station trait.
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
## About The Pull Request
@Fikou requested this and it seemed like a good idea.
This change the pattern for "how we declare that we don't want a station
trait to actually exist" from "it's a bitfield" to the other
commonly-used pattern of "it's a var which points at a typepath".
The purpose of doing this is that most of the station traits which have
an abstract parent want the default `trait_flags` value of their
grandparent and have to redeclare it for no reason, which becomes more
tedious the more children there are. This means that you don't need to
do that because the `abstract_type` var will only evaluate to true when
checked on the specified abstract type, without needing to change its
value on any children.
## Why It's Good For The Game
Makes extending traits marginally easier
## Changelog
not player facing