## About The Pull Request
So something i missed from when i played Goonstation a long while ago
was my blind characters, i tried recreating them in TGCode but found
that the blind quirk here is far more harsh to play visually. So i got
some help from Melbert and got a plan goin and here's the results.

Players can see colors! But muted, this change is strictly for visual
enjoyment as the constant monochrome is just - i cant really describe
how much i hate seeing it for more than 15 minutes.
Secondly the flicker is gone from the quirk but remains for all the
temporary blindness, this is 100% Melberts code as they're a helluva lot
smarter than I am and I just nod and smile before pasting it. This did
entail creating a new fulscreen in the dmi, but i just copy/pasted the
existing one and took out the animated frames and named it as 'static'
so it wouldnt interfere with anything else using it.
## Why It's Good For The Game
Playing a blind character is great, however it causes some serious
eyestrain after prolonged playstyle
## Changelog
🆑 MrMelbert, Zergspower
qol: The world is now heavily desaturated while blind, rather than pure
monochrome, to give players some visual stimulus
qol: When blind, the brief flicker of the entire screen now only appears
for mobs temporarily blinded - ie, mobs blinded from quirk / trauma /
genetic mutation no longer experience it
/🆑
## About The Pull Request
This defaults every tgui to fancy mode and removes the preference
entirely.
## Why It's Good For The Game
If you look through the code you'll find comments like these
> //some browsers (IE8) have trouble with unsupported css3 elements that
break the panel's functionality, so we won't load those if a user is in
no frills tgui mode since that's for similar compatability support
We're far and away from IE8, therefore our need for compatibility
support, so I think it's valid to remove this so called 'no frills tgui
mode'. It's tied into the event message system with every backend
update, so there's a tad less overhead.
## Changelog
🆑
del: TGUI now defaults to fancy mode, there is only fancy mode. Welcome
to the future.
/🆑
## About The Pull Request
The slight imperfections of this were getting to me whenever I was
testing stuff that required me have two different clients intializied so
let's just retinker it a bit to look nicer without losing any
functionality of the messaging service (as well as some explicit UX
stuff to make it look less syntactically incorrect)
Before:
<img width="781" height="65" alt="image"
src="https://github.com/user-attachments/assets/bcd0c44b-8f88-40f6-8d14-ea280f00e084"
/>
After (colon missing at time of screenshot, fixed later):
<img width="821" height="42" alt="image"
src="https://github.com/user-attachments/assets/a0627414-3896-424d-8eb1-250dcfaacf70"
/>
Logged Version:
```
[2025-12-06 06:29:26.969] ADMINPRIVATE: MULTIKEY: Connecting player San7890 has the same !BOTH! IP 127.0.0.1 and Computer ID *********** as thesan7890 (no longer logged in) in the current round
```
## Why It's Good For The Game
Cleaner message that is still eyecatching for admins, uses string
concats so it's less painful to modify in the future as well as reduce
duplicated code while overall maintaining a pretty nice flow of message
generation rather than be scattered all over the place.
## Changelog
🆑
admin: Multikeying Notice Messages have taken on a new form factor but
should still furnish the same information.
/🆑
## About The Pull Request
Port of https://github.com/shiptest-ss13/Shiptest/pull/3330
Partial port of https://github.com/shiptest-ss13/Shiptest/pull/1601
Makes two changes to how guns handle recoil.
- Changes recoil from an erratic shaking to a kicking of your screen
relative to your firing angle
- Adds a small cosmetic recoil to all ballistics (with an accompanying
pref option to tweak or disable it)
Primary recoil still is only used as a balance lever for a very small
handful of guns (and sawoff)
## Why It's Good For The Game
Cosmetic recoil makes guns feel a lot more punchier. People who think
its a competitive disadvantage (nerds/loosers) or people with a
legitimate sickness to screen shake or similar can just turn it off.
Old recoil was just reused explosion, while new recoil feels like its
actually recoil
## About The Pull Request
Moves eyes to there own folder and makes it so they state there icon
folder rather then it being hard coded
## Why It's Good For The Game
It felt weird that these are lumped into a file that's mostly hair and
that its hard-coded like this. This makes it easier to sort out icons.
(Thinly veiled downstream support)
## Changelog
N/A
## About The Pull Request
1. Stairs are now on the floor plane, meaning they don't have AO and
blend in with turfs
2. Stairs now blend with adjacent stairs, forming a contiguous sprite
3. There is now a visual indicator that stairs will take you up in the
form of an arrow - The arrow appears when within three tiles and only
appears if the stairs can actually take you up.
https://github.com/user-attachments/assets/d941a312-9470-4d2a-95f0-a1834adf0212
## Why It's Good For The Game
1. The common method of making stairs (stair objects on stair turfs)
looks ugly due to AO
2. Stair turfs have these sprites but not the objects themselves
3. Given stairs now blend in better, I figured there should be a proper
indicator that stairs exist. Helps with fake stair confusion
## Changelog
🆑 Melbert
qol: Stairs now have an indicator that stepping beyond them will take
you upwards. You can disable it in accessibility settings if desired.
image: Stairs blend in and together better.
/🆑
## About The Pull Request
It's just a partial cleanup of
anti-[STYLE](https://github.com/tgstation/tgstation/blob/master/.github/guides/STYLE.md)
code from /tg/'s ancient history. I compiled & tested with my helpful
assistant and damage is still working.
<img width="1920" height="1040" alt="image"
src="https://github.com/user-attachments/assets/26dabc17-088f-4008-b299-3ff4c27142c3"
/>
I'll upload the .cs script I used to do it shortly.
## Why It's Good For The Game
Just minor code cleanup.
Script used is located at https://metek.tech/camelTo-Snake.7z
EDIT 11/23/25: Updated the script to use multithreading and sequential
scan so it works a hell of a lot faster
```
/*
//
Copyright 2025 Joshua 'Joan Metekillot' Kidder
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
//
*/
using System.Text.RegularExpressions;
class Program
{
static async Task Main(string[] args)
{
var readFile = new FileStreamOptions
{
Access = FileAccess.Read,
Share = FileShare.ReadWrite,
Options = FileOptions.Asynchronous | FileOptions.SequentialScan
};
FileStreamOptions writeFile = new FileStreamOptions
{
Share = FileShare.ReadWrite,
Access = FileAccess.ReadWrite,
Mode = FileMode.Truncate,
Options = FileOptions.Asynchronous
};
RegexOptions regexOptions = RegexOptions.Multiline | RegexOptions.Compiled;
Dictionary<string, int> changedProcs = new();
string regexPattern = @"(?<=\P{L})([a-z]+)([A-Z]{1,2}[a-z]+)*(Brute|Burn|Fire|Tox|Oxy|Organ|Stamina)(Loss)([A-Z]{1,2}[a-z]+)*";
Regex camelCaseProcRegex = new(regexPattern, regexOptions);
string snakeify(Match matchingRegex)
{
var vals =
matchingRegex.Groups.Cast<Group>().SelectMany(_ => _.Captures).Select(_ => _.Value).ToArray();
var newVal = string.Join("_", vals.Skip(1).ToArray()).ToLower();
string logString = $"{vals[0]} => {newVal}";
if (changedProcs.TryGetValue(logString, out int value))
{
changedProcs[logString] = value + 1;
}
else
{
changedProcs.Add(logString, 1);
}
return newVal;
}
var dmFiles = Directory.EnumerateFiles(".", "*.dm", SearchOption.AllDirectories).ToAsyncEnumerable<string>();
// uses default ParallelOptions
// https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.paralleloptions?view=net-10.0#main
await Parallel.ForEachAsync(dmFiles, async (filePath, UnusedCancellationToken) =>
{
var reader = new StreamReader(filePath, readFile);
string oldContent = await reader.ReadToEndAsync();
string newContent = camelCaseProcRegex.Replace(oldContent, new MatchEvaluator((Func<Match, string>)snakeify));
if (oldContent != newContent)
{
var writer = new StreamWriter(filePath, writeFile);
await writer.WriteAsync(newContent);
await writer.DisposeAsync();
}
reader.Dispose();
});
var logToList = changedProcs.Cast<KeyValuePair<string, int>>().ToList();
foreach (var pair in logToList)
{
Console.WriteLine($"{pair.Key}: {pair.Value} locations");
}
}
}
```
## Changelog
🆑 Bisar
code: All (Brute|Burn|Fire|Tox|Oxy|Organ|Stamina)(Loss) procs now use
snake_case, in-line with the STYLE guide. Underscores rule!
/🆑
## About The Pull Request
`create_from_ghost` can be called from stuff like... dynamic executing a
ruleset, so putting a sleep/user input within it causes problems
So I refactored ghost spawns a fair bit, creating a clear delineation
between where you can and can't put user input
## Changelog
🆑 Melbert
fix: Pirates will no longer randomly spawn as human
fix: Servant Golems have numbered names again
refactor: Refactored ghost spawns (like spider eggs or pirate spawners),
report any oddities
/🆑
## About The Pull Request
Allows users to edit color matrix filters and layered filters'
transforms through Filterrific, which were the two last unsupported
filter fields. The menus are pretty minimal, but you shouldn't be
touching them if you don't know what you're doing anyways.
https://github.com/user-attachments/assets/e87447f3-e5d6-4f6c-a8e4-bf50a1d5fa79
## Why It's Good For The Game
Makes our tooling actually work
## Changelog
🆑
admin: Implemented color matrix and transform modification support for
Filterrific
/🆑
## About The Pull Request
this converts the dependency on byondstorage, which is laggy (due to
being a large json file written to disk every 10 seconds), to using
indexeddb, like we did prior to 516. this is achieved by using an iframe
to give us a persistent origin, as the web is evil and has invented
same-origin policy
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy.
this also hosts the iframe page on the github pages site for a secondary
repository (see tgstation/byond-client-storage) so it works OOTB without
requiring server operators to setup the webroot cdn (which i don't
believe is configured on the tg servers at the moment)
however, if a server is using the webroot cdn, it will use that instead
of github pages
you could also host the iframe.html page on a separate host from your
cdn or github pages if you wanted to
if we can't access the configured cdn at all, it failovers to use
byondstorage anyway, if the internet stops working and you still want
your chat history to save, i guess
## Why It's Good For The Game
saving this enormous json file is laggy, and this solution would fix
https://github.com/tgstation/tgstation/issues/89988 and fix
https://github.com/tgstation/tgstation/issues/92035
i am open to other solutions, but this does seem to require the least
amount of external dependencies of posed solutions
## Changelog
🆑
fix: you should experience less stutters every 10 seconds
server: server operators can now configure an alternative storage domain
for clientside data storage, read the example configuration for more
/🆑
---------
Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
## About The Pull Request
Adds `GLOB.unrecommended_builds`, for byond build which are broken for
the end user in some way, but not in a way that warrants outright
blacklisting players from connecting with them
Looks like this (Ignore the number I changed it for testing purposes)
<img width="493" height="267" alt="image"
src="https://github.com/user-attachments/assets/d31636e8-a106-4d13-a8fa-aee6a50c6d27"
/>
Uses this system for the new byond build, 1670+, which breaks text
rendering
Also adds 1670+ to the list of builds to warn on compile
## Why It's Good For The Game
1670 broke the compilation step, probably permanently
Whether we will fix this or flip a pragma or w/e remains to be seen, but
until then we can tell people to compile an earlier version
1670 also broke the user experience, causing map text to show up as
really big. This will be fixed in an upcoming version
<https://www.byond.com/forum/post/2983385>
## Changelog
🆑 Melbert
qol: If you are on Byond 516.1670+, you will get an alert on login that
your build is less than functional
/🆑
## About The Pull Request
Despite what the code comments said we can rename them and we should
because they make no sense
## Why It's Good For The Game
The save file keys for cat features should have cat in the name and not
human
## Changelog
🆑
server: renamed feature_human_ears and feature_human_tail to
feature_cat_ears and feature_cat_tail respectively
/🆑
## About The Pull Request
Rather than having 100 separate list variables on `SSaccessories`, have
1 list for all feature keys that are associated with sprite accessories
This way you can get a feature by doing
`SSaccessories.feature_list[key]`, instead of necessitating
`SSaccessories.ears_list`, `SSaccessories.tail_list`, etc.
This lets us cut back on a lot of boilerplate in prefs, dna, and organs
## Why It's Good For The Game
We can see the benefit in this example: This is all the code for horn
DNA, bodypart overlay, and preference
```dm
/datum/dna_block/feature/accessory/horn
feature_key = FEATURE_HORNS
```
```dm
/datum/bodypart_overlay/mutant/horns
layers = EXTERNAL_ADJACENT
feature_key = FEATURE_HORNS
dyable = TRUE
/datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
return !(bodypart_owner.owner?.obscured_slots & HIDEHAIR)
```
```dm
/datum/preference/choiced/species_feature/lizard_horns
savefile_key = "feature_lizard_horns"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_FEATURES
main_feature_name = "Horns"
should_generate_icons = TRUE
relevant_organ = /obj/item/organ/horns
/datum/preference/choiced/species_feature/lizard_horns/icon_for(value)
return generate_lizard_side_shot(get_accessory_for_value(value), "horns")
```
## Changelog
🆑 Melbert
refactor: Refactored species unique organs slightly, particularly how
they are set up at game start. Report any oddities, like invisible tails
or wings
/🆑
---------
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
## About The Pull Request
discussed in #93439, a generic proc for getting a list of all types
minus abstract types.
applies this to most instances of a for loop that currently filters out
abstract types
it SHOULD be a nothing burger for performance, however I have not bench
marked the difference. (also testing, there is a total of 7 calls in
init to it)
## About The Pull Request
Ready for merge post review
No gameplay balance changes, just better AI expression options and
polished interfaces for doing so.
- Adds 32 AI Core animation sprites to the AI status screens as a player
choice
- Gives two new menus to change status displays or core display with
TGUI
- Fixes Friend Computer emote incorrectly affecting evacuation displays
- Special mention to MrMelbert who gave a few very useful points as I
embraced TGUI suffering :)
<img width="1500" height="750" alt="image"
src="https://github.com/user-attachments/assets/fbae0ea9-5220-4cf9-9fa0-c5f0385f9e52"
/>
<img width="1746" height="821" alt="image"
src="https://github.com/user-attachments/assets/f1c08fdf-8dc8-44eb-b7cd-cd86f9b8f903"
/>
There is also a new verb under "AI Commands"
<img width="433" height="127" alt="image"
src="https://github.com/user-attachments/assets/2cd69b71-7a0c-4199-959e-acd4de9d5dad"
/>
<img width="364" height="528" alt="image"
src="https://github.com/user-attachments/assets/e083784e-8251-4a55-a9e2-e27e53dfa780"
/>
## Why It's Good For The Game
- Allows AI players to express themselves more in round / stand out more
- Now it is a TGUI menu, Much easier to see what is available and change
mid round as needed.
- We had talented Spriters make these and now more players can see them
## Changelog
🆑
qol: New verb in "AI commands" to update AI display status
fix: Stopped "Friend Computer" emotion affecting evac displays instead
of just AI displays
code: Replaced radial wheel for AI status or AI core display with TGUI
menus
image: AIs can now update their status displays with way more graphics
to match core display options onto the TVs.
/🆑
---------
Co-authored-by: loganuk <falseemail@aol.com>
## About The Pull Request
- [ ] I tested this pr
Adds "Midround Mass Traitors" and "Midround Mass Changelings" heavy
rulesets
Midround Mass Traitors will turn a number of the crew into sleeper
agents
Midround Mass Lings will spawn a number of changeling meteors
BY DEFAULT:
- Traitors will spawn 2-4 sleeper agents
- Lings will spawn 2-3 changeling meteors
- They won't run without >=2 candidates
- They have no config blacklist (so the HoP can roll mass midround
traitor, despite not being able to roll normal midround traitor. However
default blacklisted roles like security officers are still blocked)
- They're weighted impossible on tier 0, same weight as most midrounds
on tier 1, and fairly high on tiers 2 and 3
- They're repeatable but very unlikely to repeat
- Significantly higher min pop brackets than their solo counter part
## Why It's Good For The Game
Adds more options for lategame antags than big midrounds
## Changelog
🆑 Melbert
add: Two new heavy dynamic rulesets: "Midround Mass Traitors" and
"Midround Mass Changelings"
/🆑
## About The Pull Request
Heretic has received a complete overhaul. This PR touches nearly every
aspect of the antagonist. For readability's sake, not every change is
going to be listed in this pull request.
For the full list of changes please refer to the design doc:
https://hackmd.io/@BiST8PJVRjiwVPY86U3bLQ/B11HyChz1g.
Code by Me, @Xander3359 and @Arturlang
TGUI by @Arturlang
Sprites by OrcaCora and GregorDM
Writing bits by @necromanceranne
### Core changes
- Cross-pathing has been removed. Main knowledge spells are now
exclusive to their path (for the most part).
- For every main knowledge unlocked (save for the robes and the blade
upgrade), Heretics can choose one option from a draft of 3 random side
knowledges (this is a free point).
- Heretics can now purchase side knowledges from a new tab, the
"Knowledge Shop". Side-knowledges have been divided by tier (Stealth,
Defense, Summons, Combat and Main). Tiers are unlocked as you progress
toward your main path.
- Heretics now gain the grasp and mark upgrade immediately, but their
main knowledge choices cost twice as much (except for the first spell,
the robes and the blade upgrade).
- Path specific robes have been introduced! They come with their own set
of quirks.
- Each Path has received a passive ability. This passive is upgraded
when you first create your robes, and again when you complete the Ritual
of Knowledge.
- Paths have been rebalanced as a result of the removal of cross-path
progression. Cosmic and Moon paths have received soft reworks.
- Upon unlocking the path 2nd level or reaching a total of 8 points
worth of knowledge, Heretics will lose the ability to blade break (and
the limit on blades all together).
- Ascension now automatically calls the shuttle with no possibility of a
recall.
- Late join Heretic has been removed.
### New UI
<img width="750" height="635" alt="moon path ui"
src="https://github.com/user-attachments/assets/184ef783-5c9c-48a1-a2f7-4807ca93e990"
/>
### Knowledge shop
<img width="787" height="669" alt="Knowledge shop"
src="https://github.com/user-attachments/assets/3dc89b84-8c70-4d47-b612-54396e3ea6e7"
/>
### Quality of life //General balance changes
- Heretics will now gain X-ray vision for a few seconds when nearby an
eldritch essence (this effect has a cooldown).
- Ritual of knowledge now requires 1 uncommon item instead of 2. You may
now use a stunprod instead of a baton to complete the ritual. Beartraps
have been removed from the list of possible reagents.
- The maximum number of possible sacrifices required to ascend has been
reduced from 6 to 5 while the minimum has been upped to 4.
- Codex Cicatrix no longer requires a special pen to be made.
### Passive abilities
- Heretics now start with a passive ability. You can find what it does
on the path info tab after a path has been selected, and what they gain
when upgraded.
- Crafting your first set of Eldritch robes will bump your passive to
level 2.
- Unlocking the 2nd level will subsequently unlock your "Ritual Of
Knowledge"
- Completing the ritual of knowledge or ascending will net you the final
level.
### Path Specific Robes
- Armorer's Ritual is no longer a side knowledge. Each path will have
their own unique version of the ritual. This is placed after the 2nd
spell in the tree.
- Robes can no longer be destroyed by fire and acid, grant t4 flash
protection (Moth Heretics stay winning) and protection against basic
syringes, to bring them on par with other antagonist's armor sets.
- The recipe to craft the robes is now a set of armor/vest, a mask (any
mask will do now, not just gas masks), plus the unique reagent required
for the blades (Plasma for Cosmic, Trash For Rust, match for Ash and so
on)
- Wearing the robes as a non-heretic may yield some unfortunate
side-effects.
### Moon Path Rework
Moon path rework.
Moon Heretics gain immunity to brain traumas and slowly regenerate brain
health. Equipping the moon amulette channels its effects through the
moon blade; making it unblockable and cause sanity damage instead of
brute. Ring leader's Rise now summons an army of harmless clones that
explode when attacked; the explosion briefly stuns non-heretics and
cause sanity and brain damage to them. Moon blade can also now be used
when pacified and Moon spells are no longer blocked by regular anti
magic, only mind magic protection.
**Cosmic Path Rework**
Cosmic path has received the biggest batch of changes alongside Moon.
The path has been dead last in ascension and pickrate (less than 5%) for
almost 2 years. It did gain some popularity over the last few months,
reaching the highest ascension rate in the game (12%) while mantaining a
relatively low pickrate.
Cosmic sits in a weird spot, where pretty much every knowledge
surrounding the path is either mediocre or, in the case of the
ascension, dysfunctional. Yet it has maintained a smidge of relevancy
due to how quickly Cosmic heretics can capture and sacrifice targets
thanks to Star Touch.
As a result, the best course of action would be to rebalance the
entirety of the kit; granting the heretic more tools to manipulate space
and dictate the flow of a fight, while lessening their ability to end a
confrontation by instantly sleeping their opponents.
lastly The Star Gazer is now ghost controlled ; And they shoot lazers!
<img width="636" height="451" alt="gazer gag 3"
src="https://github.com/user-attachments/assets/601d6881-c042-4e42-8ce6-ac90cd27848b"
/>
## Why It's Good For The Game
### Ok...but why do we want this?
Again, if you want my full reasoning, please check my doc
https://hackmd.io/@BiST8PJVRjiwVPY86U3bLQ/B11HyChz1g.
To keep it short and concise; Heretic is too complex and unintuitive for
its own good. Too impenetrable for new players and too abusable for
experienced players. This can be chalked up to a lot of poor design
decisions. But ultimately, what I believe being the biggest contributor
to the current status of Heretic is the ability to move into different
paths, also known as "Cross-Pathing".
### Cross Pathing my beloathed.
Cross-pathing, while cool in theory, overcomplicates the antagonist and
overloads them with power. Players dealing with the heretic are
incapable of working out what a given heretic can do. This also leads to
late game heretics having 3 rows Worth of action buttons and virtually
no weakness.
Over the last year, I've often received the understandable but also kind
of unfair accusations of making Heretic too powerful without a clear aim
or purpose.
My goal with the paths I've reworked over the last year (Rust,Void and
Blade) wasn't necessarily to just make them stronger (although that was
also part of the goal, as they were paths that were underperforming),
but for them to have more interactions with the sandbox and to better
live up to the fantasy presented to the player.
If an harbringer of frost gets countered by a cup of coffee, we probably
messed something up.
Unfortunately, the current incarnation of Heretic doesn't really allow
for surgical balance changes to specific paths. Every time a knowledge
gets buffed, we make every path that can easily tap onto that knowledge
stronger by default. It doesn't take a genius to understand why this
system is ultimately unsustainable.
### Blade Breaking
I feel that after a heretic has reached the near peak of their power,
they no longer need the ability to instantly escape any encounter. Check
my doc for my full reasoning.
## Less versatile, more specialized paths.
By removing cross-pathing, we remove a huge maintainability burden from
the antagonist. Paths can now be designed around clearer strengths and
weaknesses. They become easier to balance and less of an headache to
understand for everyone.
It also means we can give paths some needed quality of life quirks
without having to worry how such a change might have a knock-on effect
for other paths.
Ash heretics can finally let loose without dying by their own flames.
Cosmic Heretic can go to space without having to carry a modsuit. Moon
Heretic can use their abilities without fear of one random trauma
ruining their day, and so on.
### What a horrible night to have a curse...., wait how do I curse
people again?
As of right now the heretic tree has quite a hefty amount of trinkets
that pretty much never see use.
Partly because the tree itself is a nightmare to navigate. And partly
because why would anyone set up an elaborate plan or scheme when they
can unleash 2 rows of spell in the span of bunch of seconds.
Heretics mostly gravitate towards powers that push them towards greater,
more potent combat strength. If it doesn't contribute to killing people
quicker, it isn't worth doing for most. And given the opportunity cost
associated for taking those powers, they will remain that way so long as
there are better choices to be poached.
The new draft system encourages Heretics to play more with the tools at
their disposal. If you want to go for a specific combo from the side
path options, you may now do so by tapping into the knowledge shop.
Yes, the shop does include a few knowledges from the other paths. But
these are limited to 1 per path, are very expensive and can only be
unlocked very late into the shift.
## Drip Of the Mansus
The iconic heretic robe is actually sequestered to a side path that is
most easily access by only two paths at a time. Since heretic paths are
being made to be much more specialized, the most obvious way in which
this can be showcased is through an easily
identifiable outfit.
By using the robes, we can both telegraph WHAT heretic you are looking
at, and just how much power they've accumulated and when it is
reasonable to take the kid gloves off and treat them as a genuine
threat. If a heretic is in their
robes, that heretic is now a significantly more prominent danger to the
station.
It also serves as a useful means for gating some of the more powerful
effects of a heretic's path behind the robes, AND enable options for
disarming them of that power should they be captured without making it
something endemic to their mob.
A major problem with heretics is a lack of certainty as to how powerful
they have become. A heretics robes is one of the milestones to help
players dealing with heretics identify that.
### Will this be 100% fair and balanced?
This is a massive overhaul to a pretty complex and bloated antagonist.
I've done my best to show the changes to several maintainers and other
members of the community for their feedback. But at some point we'll
have to see how this behave in the environment to get a feel if
something is over or undertuned. (that's my way of saying, yes this is
likely gonna require a testmerge or two).
What I will say is that I'm not trying to change the core identity of
Heretic.
Heretics should have the upperhand in single encounters early on, be
able to joust a small group of players after they unlock their final
spell, and end the round when they ascend. They're a progression
antagonist. They should retain their payoff as well as pose a danger as
they grow stronger.
But if more players feel like they are more reliably able to play the
antagonist in more varied and interesting ways, rather than the
antagonist largely existing as a measuring stick for 'robustness' due to
its elitist design philosophy, then the rework has been a success. There
should be something for
everyone in the antagonist, as is true for all of our antagonist roles.
## About The Pull Request
Just a simple find + replace PR. All the other tail defines match their
text strings, but for some reason cat tails are just `FEATURE_TAIL`
which is inconsistent.
## Why It's Good For The Game
Consistency, + a lot of downstreams have a generic "tail" feature key
which is distinct from cat tails, so not taking up that define is
better.
## Changelog
Nothing any players would notice
## About The Pull Request
When more Felinid ear styles were added, no one updated the jank old
randomization code
When Felinid ears were refactored, no one updated the jank old
randomization code
Sooo let's do that shall we?
1. Species `get_mut_organs` -> `get_organs`, it gets gets all organs the
mob has anyways
2. Prefs `relevant_external_organ` -> `relevant_organ`, it applies to
any organ type
3. Del organ `preference`, the preference itself handles it via
`relevant_organ`
## Changelog
🆑 Melbert
fix: Felinids will randomize their ear type properly
/🆑
## About The Pull Request
If someones delete a keybind this runtime will appear.
<img width="689" height="172" alt="image"
src="https://github.com/user-attachments/assets/1fd9c6c3-00a7-4890-89ba-002943a06a32"
/>
This pr preverents it
## Why It's Good For The Game
Fixes are good, bugs are bad (except hk)
## Changelog
Not player faced
## About The Pull Request
#91419 removed change_view in mob login for un-inited clients, which
leaves 1 second delayed fit_viewport calls from
attempt_auto_fit_viewport as the only way for new clients to adjust
their viewport from the default square (which is also only ran once all
subsystems finish initializing).
Just calling apply() after applying our prefs to the view_size is enough
to make it work, also we don't need the said second delay in
attempt_auto_fit_viewport anymore either.
## Changelog
🆑
fix: Fixed delayed viewport fitting on server join/init
/🆑
## About The Pull Request
moves all implementations (im aware of) for "Im a parent type dont spawn
me please" to the datum layer to standardized behavior
adds a standerized proc for filtering out "bad" items that we dont want
spawning. applies to it the subtype vendor, gifts, and a new spawner and
mystery box for a random gun (neither playerfacing)
"port" of https://github.com/shiptest-ss13/Shiptest/pull/4621https://github.com/user-attachments/assets/22f6f0b2-b44e-411a-b3dc-6b97dc0287aa
small warning: I dont have EVERY abstract type defined right now but,
ive done a good enough job for now. Im tired of data entry rn
## Why It's Good For The Game
standardizing behavior. Might be a micro hit to performance however
having this lets us not rely on icon state to determine whether
something is a parent type and makes it much easier to tell something is
a parent type (could be applied further to things like admin spawning
menus and things like that).
need feedback on if this is actually good for the game.
## Changelog
🆑
add: Soda cans show up in the silver slime drink table.
add: Examine tag for items that are not mean to show up ingame.
refactor: Standardizes how gifts rule out abstract types.
fix: gifts no longer check if something has an inhand, massively
expanding the list of potential items.
/🆑
## About The Pull Request
Tin.
Runtiming in this spot is really not good and may have potentially
caused a crash for one of our rounds.
Not sure how it happened exactly, but it costs nothing to be safe here.
<img width="696" height="38" alt="image"
src="https://github.com/user-attachments/assets/c56c5c18-8ae0-428f-a407-b2e3de79d87a"
/>
## Why It's Good For The Game
Let clients finish their destruction
## Changelog
Not player-facing
## About The Pull Request
A verb is now available on localhost called `"Export Save as Dev
Preferences"`
This exports your current savefile to `/config/dev_preferences.json`
If you then connect to your localhost as a guest, it will load
`dev_preferences.json` as your preference datum
This allows for devs testing the game locally to load preferences for
guests.
(Guests connecting to live servers are completely unaffected.)
## Why It's Good For The Game
Initially I only did this because the recent keybinding changes have
destroyed my muscle memory when testing w/o logging in.
But as I worked on it I thought of a few other usecases, like when
implementing preference version migration - the dev preference is never
saved which means you can re-compile as much as you want without needing
to revert your save manually.
## About The Pull Request
Extends the max range for integer scaling up to 9x, corrects some
misinfo in the visuals guide
## Why It's Good For The Game
This allows proper integer scaling up to 8k resolution, which not only
is generally the highest consumer-available resolution currently, but
also the next resolution that is able to perfectly display a 480p image
on it via integer scaling.
Also corrects misinfo because misinfo is bad.
## Changelog
🆑
qol: Increased the integer scaling range up to 9x
/🆑
## About The Pull Request
Moves all the dna block handling onto singleton datums initialized
inside global lists, to make the handling dna less of a copy-paste mess
and make adding new blocks significantly easier. There is still some
work to be done in the copypaste department but ultimately that falls
under its own PR scope after the core refactor goes through. (Ill
probably do those but it will also be easier for everyone else as the
code is now significantly less of an eyesore)
Both features and identities have been tested through and through, and
seem to be working fine.
Also removed the reliance on weird hardcoded lookup tables for length,
and other similar things that just didn't make sense when I was passing
through DNA code. There's a lot more that fall out of scope for this
exact PR's goal however
## Why It's Good For The Game
I've been told the maintainers will love me for doing this
## Changelog
🆑
code: feature keys are no longer magical strings floating around the
codebase and use proper defines
refactor: DNA blocks are now handled with singleton datums.
/🆑
## About The Pull Request
Fixes#92125
Very simple, when working without an instantiated datum we would read
from the config manually, but some places neglected to do that.
So I added a macro to help in the future.
## Changelog
🆑 Melbert
fix: Fixes some places where dynamic configs were not being read
correctly
/🆑
## About The Pull Request
Savefile versioning is quite robust, but it relied a lot on comments to
explain why exactly it worked (such as needing to explain that
error/empty states were negative integers only because any valid
savefile version would be a positive integer). Anyways, let's spell it
out a lot more using `#define` values and dmdoccing said values in order
to make the whole system a bit more cohesive.
This also corrects an issue that has irked me for a while, which is that
we call and go through `update_preferences()` or `update_character()`
_every single time_. `SAVEFILE_VERSION_MAX` is essentially just a
placeholder, it's not checked against anything! Let's use that in one of
the new macros we created so we can slim down on the proc call overhead
(as well as whole branches of code) that we iterate through every single
time we load a savefile. Like we were generating a backup json every
single run without fail, let's trim that out when it's not necessary.
## Why It's Good For The Game
More clear for people operating on this code in the future as well as
does a lot less work. Win win.
## Changelog
Tested it and it migrated my savefile from 48 -> 49 without any ill
effect. Let me know if we want to have the redundancy behavior baked in
where we call these procs/enter code branches every single time though-
I would rather just bake the code in that way rather than live in a
world of confusion on why it operates that way.
🆑
server: Savefile migration has been tweaked a bit, though there
realistically shouldn't be any issues with this. Keep a wary eye out
though.
/🆑
## About The Pull Request
Borg me dogtag is a loadout item instead of a quirk
## Why It's Good For The Game
The quirk doesn't do anything
## Changelog
🆑 Melbert
del: "Cyborg Pre-screened dogtag" quirk. It's a loadout item now.
/🆑
## About The Pull Request
Ok there's a lot here, sorry bout that.
- Cleaned up the permissions panel backend pretty signficantly
- Added some extra security measures to said code, mostly proc call
checks
- Properly implemented filtering code jordie wrote years and years ago
for permissions logs
- Cleaned up the permissions ui generally, more bars, nicer lookin
stuff, etc
- Fixed the Management panel's relationship with combined roles, and
renamed it to Housekeeping. Its display is expanded too.
- Added tracking to rank datums on where exactly they came from
- Added a new tab to the permissions panel which allows the modification
and deletion of ranks
- Beefed up rank modification to try and avoid accidential temp rank
additions to the db
I'm doing my best to avoid perms escalation issues, tho they are always
possible right.
Also, got mad at some query cleanup handling, did a pass on it. this
isn't nearly all of em, but it's some.
## Why It's Good For The Game
I realized there is no way to, in game, cleanly edit/create ranks, and
that the way the existing system worked was quite opaque.
I'm trying to fix that here. It does mean potentially opening up DB rank
deletion/modification to bad actors, but frankly I am not overly worried
about that. Admin modification has always been a vulnerability so like.
Here's a video with my changes (mostly, it's lightly outdated)
https://file.house/XqME7KWKk0ULj4ZUkJ5reg==.mp4
## Changelog
🆑
refactor: Fucked with admin rank setup very slightly, please yell at me
if anything is wrong.
admin: Updated the permissions panel to be a good bit more user
friendly, added rank management support to it.
server: I've added code that gives the game modification/deletion perms
for the rank table, be made aware.
/🆑
---------
Co-authored-by: san7890 <the@san7890.com>
## About The Pull Request
Implements https://hackmd.io/@tgstation/SkeUS7lSp , rewriting Dynamic
from the ground-up
- Dynamic configuration is now vastly streamlined, making it far far far
easier to understand and edit
- Threat is gone entirely; round chaos is now determined by dynamic
tiers
- There's 5 dynamic tiers, 0 to 4.
- 0 is a pure greenshift.
- Tiers are just picked via weight - "16% chance of getting a high chaos
round".
- Tiers have min pop ranges. "Tier 4 (high chaos) requires 25 pop to be
selected".
- Tier determines how much of every ruleset is picked. "Tier 4 (High
Chaos) will pick 3-4 roundstart[1], 1-2 light, 1-2 heavy, and 2-3
latejoins".
- The number of rulesets picked depends on how many people are in the
server - this is also configurable[2]. As an example, a tier that
demands "1-3" rulesets will not spawn 3 rulesets if population <= 40 and
will not spawn 2 rulesets if population <= 25.
- Tiers also determine time before light, heavy, and latejoin rulesets
are picked, as well as the cooldown range between spawns. More chaotic
tiers may send midrounds sooner or wait less time between sending them.
- On the ruleset side of things, "requirements", "scaling", and
"enemies" is gone.
- You can configure a ruleset's min pop and weight flat, or per tier.
- For example a ruleset like Obsession is weighted higher for tiers 1-2
and lower for tiers 3-4.
- Rather than scaling up, roundstart rulesets can just be selected
multiple times.
- Rulesets also have `min_antag_cap` and `max_antag_cap`.
`min_antag_cap` determines how many candidates are needed for it to run,
and `max_antag_cap` determines how many candidates are selected.
- Rulesets attempt to run every 2.5 minutes. [3]
- Light rulesets will ALWAYS be picked before heavy rulesets. [4]
- Light injection chance is no longer 100%, heavy injection chance
formula has been simplified.
- Chance simply scales based on number of dead players / total number
off players, with a flag 50% chance if no antags exist. [5]
[1] This does not guarantee you will actually GET 3-4 roundstart
rulesets. If a roundstart ruleset is picked, and it ends up being unable
to execute (such as "not enough candidates", that slot is effectively a
wash.) This might be revisited.
[2] Currently, this is a hard limit - below X pop, you WILL get a
quarter or a half of the rulesets. This might be revisited to just be
weighted - you are just MORE LIKELY to get a quarter or a half.
[3] Little worried about accidentally frontloading everything so we'll
see about this
[4] This may be revisited but in most contexts it seems sensible.
[5] This may also be revisited, I'm not 100% sure what the best / most
simple way to tackle midround chances is.
Other implementation details
- The process of making rulesets has been streamlined as well. Many
rulesets only amount to a definition and `assign_role`.
- Dynamic.json -> Dynamic.toml
- Dynamic event hijacked was ripped out entirely.
- Most midround antag random events are now dynamic rulesets. Fugitives,
Morphs, Slaughter Demons, etc.
- The 1 weight slaughter demon event is gone. RIP in peace.
- There is now a hidden midround event that simply adds +1 latejoin, +1
light, or +1 heavy ruleset.
- `mind.special_role` is dead. Minds have a lazylist of special roles
now but it's essentially only used for traitor panel.
- Revs refactored almost entirely. Revs can now exist without a dynamic
ruleset.
- Cult refactored a tiny bit.
- Antag datums cleaned up.
- Pre round setup is less centralized on Dynamic.
- Admins have a whole panel for interfacing with dynamic. It's pretty
slapdash I'm sure someone could make a nicer looking one.


- Maybe some other things.
## Why It's Good For The Game
See readme for more info.
Will you see a massive change in how rounds play out? My hunch says
rounds will spawn less rulesets on average, but it's ultimately to how
it's configured
## Changelog
🆑 Melbert
refactor: Dynamic rewritten entirely, report any strange rounds
config: Dynamic config reworked, it's now a TOML file
refactor: Refactored antag roles somewhat, report any oddities
refactor: Refactored Revolution entirely, report any oddities
del: Deleted most midround events that spawn antags - they use dynamic
rulesets now
add: Dynamic rulesets can now be false alarms
add: Adds a random event that gives dynamic the ability to run another
ruleset later
admin: Adds a panel for messing around with dynamic
admin: Adds a panel for chance for every dynamic ruleset to be selected
admin: You can spawn revs without using dynamic now
fix: Nuke team leaders get their fun title back
/🆑
## About The Pull Request
This is an atomized revival of #82419, with this part containing the
simplest of its features:
- Fixes AO pref refreshing the wrong plane, thus not updating until you
swap bodies
- Removes supermatter's copypasted warp effect
- Culls distortion effects when they're not in use because its a chonky
filter
- Hides the escape menu when its, well, hidden
- Fixes hide_highest_offset not working upon parent's creation (we're so
good at our jobs hell yeah)
- Replaces runechat's AO dropshadow with an outline, because its barely
visible due to low opacity.
## Why It's Good For The Game
Our rendering performance is shit and we need to improve it, and the
first step in this task is optimizing planecube's simplest parts. The
next step is conditional culling, better non-multiz handling and
parallax rework/removal, but all of those need to be atomized as to
prevent the PR from sharing the fate of the original.
## Changelog
🆑
fix: Ambient Occlusion pref should now update immediately upon being
changed, instead of having to swap bodies or waiting for server restart
to get it updated.
code: Slightly improved rendering code/performance just a tiny bit.
/🆑
## About The Pull Request
It breaks by setting ``is-fullscreen`` to false so we need to basically
not call set_fullscreen ever as it will permanently remove it from the
client. I can't figure out why this happens, but setting
``is-fullscreen`` to any value permanently removes ``menu`` from
mainwindow, which is what this subtitle bar thing uses.
## Why It's Good For The Game
I don't like the title bar and i want it gone but this is a bug fix.
## Changelog
🆑
fix: The title bar is back for non-fullscreen users.
/🆑
## About The Pull Request
Removes the blur of the escape menu so players can sorta see what's
going on in their game while going through, so they can react in case
something's happening while they're in menu.
Changes the font of the escape menu so it's no longer the LISA font
Makes the title only show up on the home menu, so being on the suicide
panel wont show you "another day on space station 13".
Moves the 'back' button on the suicide menu to the top left.


## Why It's Good For The Game
This hopes to make the escape menu a little more easy to go through,
removing some obstruction of your game's screen so you can see what's
happening around you, and give a little generic part of submenus in case
we add more (which I do have at least one planned).
## Changelog
🆑
qol: The escape menu no longer blurs the game in the background.
qol: The escape menu now has a more readable font, and the escape menu's
back button is now smaller and in the corner.
/🆑
## About The Pull Request
Prettier (an auto formatter) is set to only run within the tgui folder
currently. This removes that limitation, allowing it to automatically
format all supported files in the repo (.js, .html, .yml
[etc](https://prettier.io/docs/))
I made a few exceptions for bundled and generated files
## Why It's Good For The Game
I'm of the opinion that code should look uniform and am lazy enough to
want CTRL-S to format files without having to think beyond that
## Changelog
## About The Pull Request
This is my second contribution to the move towards removing the stat
panel (first one being https://github.com/tgstation/tgstation/pull/90572
)
This moves the info buttons at the top right of the game's screen
(Changelog, Rules, Wiki, etc) to the Escape menu, except for Fullscreen
which is now a pref instead. This means you can set Fullscreen to be on
permanently and every launch will automatically fullscreen you (the
viewport will be a little off because it only fixes it once
initialization is complete). This follows through rounds and auto
updates if you set your game to fullscreen with the OOC button or F11,
so players will learn about the pref after playing a round with
fullscreen enabled.
What the game now looks like
##### Alt ideas for sprites: Changelog can be a newspaper and Forums can
be a newscaster
https://github.com/user-attachments/assets/7871a226-1e0b-410d-a690-88f3616bebb0
This is something I wanted to do since the Esc menu was added but just
never got around to it, but here it is.
## Why It's Good For The Game
These buttons don't warrant being in the player's face 24/7 and since
we've want to remove the stat panel and this has to be somewhere, I
thought it would be a better fit in the Escape menu. It helps make the
Esc menu the tool players use to access their OOC tools and overall I
think improves the appearance of the game's screen to something more
like an actual game would look like, especially when our comparison is
SS14.
## Changelog
🆑
qol: Info buttons previously at the top right of your screen (Changelog,
wiki, forums) is now in the Escape menu.
qol: Fullscreen is now a preferences and will follow you through rounds.
/🆑
## About The Pull Request
Adds a new HUD element that only shows up when you're resting that
flicks when you click it once, and puts you to sleep for 40 seconds if
you double click it (so you don't accidentally sleep yourself for 40
seconds), which is meant to replace the verb in the stat panel.
Doesn't show up if you're sleep immune.
I also fixed alien huds a bit, putting rest on the right side where it
is for every other mob, and brought the floor change buttons down to
compensate.
New Larva HUD (other xenos have Throw between rest and sleep)

Demonstration
https://github.com/user-attachments/assets/11f7574d-dd6d-4da5-ab39-6fcf6d6694b9
Rest can be seen in IDB
### New accessibility setting
As a compromise to putting a tgui confirmation menu in your face or
requiring a double click, I added a new setting in accessibility tab
that allows you to disable "double click" features. So far all it does
is give a tgui menu instead of require double click for sleeping, and
allow you to further examine things with a linked button in base
examine.
## Why It's Good For The Game
Sleep is currently only a verb available in the stat panel, this
provides an alternative so it doesn't become a chatbar-only verb when
the stat panel is removed. It's also just good feedback to the player
that this action exists.
## About The Pull Request
This is part of my ongoing project to remove the Stat panel which you
can read/contribute to here: https://hackmd.io/443_dE5lRWeEAp9bjGcKYw
Replaces the pAI button at the bottom of Ghost's HUD with a new button
for Ghost settings
Default look

With fun verbs (admin only, the 2 buttons at the top right), No body,
and lag switches on (disables T-Ray and Zooming)

The ghost icon next to "re-enter body" is the DNR button, which requires
double click.
Extra view is now easier to understand, 0 is "default", anything more is
extra vision you get. Goes to 3 for regular users, 7 for BYOND members.
Removes the "Ghost" tab from the stat panel entirely, this replaces it.
## Why It's Good For The Game
The Ghost tab of the stat panel is filled with barely functional stuff,
like "Jump to Mob" which allows you to jump to "oranges ear" which
teleports you to nullspace, or the 4 different jump to verbs for
different things which is irrelevant from the Orbit menu and the many
improvements it got over the years, and even the Notifications panel,
which seems pretty useful, but because it's delegated to a small button
filled with the rest of these it gets entirely drowned out.
This puts all the important things in front of the user at the click of
a button, meant to be easy to navigate and giving important information
first.
## Changelog
🆑
add: Added a 'Ghost settings' button, taking the spot of the pAI
candidate button and replacing the "Ghost" tab of the Stat panel. This
button contains buttons pertinent to your time as an Observer.
/🆑
Being colorblind now makes you see all wires in tones of grey.
Also fixes the eyechart not taking the monochromacy quirk into account
when checking for colorblindness
Makes the quirk/trauma a bit more immersive and can lead to funny
situations when you know which color to cut but can't find it.
## About The Pull Request
Currently the button to open a map in webmap is tied to a config entry,
which would then take the name of the map being played and get the link
to that, however for cases like new/tested/admin uploaded maps where
there is no webmap available, this would still have a link to a url that
doesn't exist.
Instead, we'll make the webmap link be in ``maps.txt``, same as
feedbacklink.
## Why It's Good For The Game
Explained in the about section, this prevents webmaps appearing for maps
that aren't supposed to have a webmap link available.
## Changelog
Nothing player-facing, webmaps aren't currently used (afaik) currently
cause they're broken for tg codebases.
## About The Pull Request
This PR adds a secondary character preference which allows you to pick
gender for silicon characters, and have the option of matching or
separating that with their character's main gender. Silicon gender is
displayed in their examine text as expected.
## Why It's Good For The Game
People will have a way to identify the gender of their characters when
playing as a cyborg and AI!
## Changelog
🆑 A.C.M.O.
add: Adds an option for picking silicon gender to secondary character
preferences. Matches the main gender preference by default.
add: Adds gender pronouns in cyborg/AI examine text.
/🆑
## About The Pull Request
This PR started with the idea of adding support for map feedback
threads, which I added to the roundend report, escape menu, and stat
panel. To do this though I had to make pretty annoying changes to the
stat panel and had to touch every single time something to the stat
panel was added, so since we now have a way to have links in the stat
panel I thought of taking full advantage of it and add some QOL.
AIs can now track their borgs by clicking their status on the stat panel
https://github.com/user-attachments/assets/1789dc46-5d12-48e9-bb8d-d3278aa19639
With Melbert's comment, I added another stat panel entry that directs
you to the Webmap page, which currently seems to be a little messed up
(https://github.com/AffectedArc07/SS13WebMap/issues/41 &
https://github.com/AffectedArc07/SS13WebMap/issues/42) but if they get
fixed this would be a swag asf feature
##### Code bounty for Ezel/Improvedname
## Why It's Good For The Game
Feedback threads was a suggestion from a player and is fully in control
of admins as an optional thing, and while we still have stat panel I
think it's nice to be able to take advantage of its features.
## Changelog
🆑
admin: Admins can now link a URL for maps, used to give feedback on said
maps. Accessible through the roundend report, escape menu, and stat
panel.
qol: AIs can track their borgs by clicking on them in the stat panel.
qol: You can now directly go to the webmap of maps from the stat panel
(assuming it's set in config).
/🆑
## About The Pull Request
- Tweaks partial understanding.
Paragraphs are now split into sentences first creating more natural
breaks between sentences.
- Adds "Common Second Language" quirk
This quirk changes your default understanding of common (up to) 90%
(your choice), meaning you drop the occasional word.


Additionally, when your sanity drops below a threshold, you become
forced to speak your native language, albeit with a partial
understanding applied for everyone else.
Incompatible with similar language quirks + can't be taken by humans
(yet?)
## Why It's Good For The Game
Just a fun way to play around with the new "partial understanding"
system.
## Changelog
🆑 Melbert
add: "Common Second Language" quirk
qol: Language translations chunk sentences together better, making
partial understanding a bit easier to parse.
/🆑