Commit Graph
5688 Commits
Author SHA1 Message Date
df7832aa43 Replaced our NPC AI with Behavior Trees. (#96628)
This PR replaces our current NPC AI with a [behavior tree
system](https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control)).
Behavior trees are a common way of creating AI in which you place nodes
in a tree structure to define what actions an AI should take.

AI controllers defined a list of /datum/ai_planning_subtree types in
behavior_nodes. Each subtree was a self-contained unit that could call
queue_behavior() to fire off /datum/ai_behavior actions. The controller
iterated subtrees in order, each one deciding independently whether to
queue something and deciding whether the next subtree would run.

This has a few issues:
1. There's no real structure; you are just defining a list of things to
try in order.
2. There was a loooot of subtrees that were basically the same as
another but with some slight modification
3. It was hard to understand.

Controllers now define a single json file describing a tree of nodes.
The tree is composed of structural composites:

Sequence - do A, then B, then C (and so on)
Selector - try A, if it fails try B, then C (and so on)
Parallel - run A and B simultaneously, with configurable failure/success
policies and or looping behavior
Subplan - loop a child continiously

Along that we also have "Decorators". These are nodes that basically
check a condition (E.g.; do we have a combat target). These decorators
can be used to gate behavior and are re-useable across behavior trees.
They also have a concept known as "Observers". Which lets them cancel
lower priority behavior in case their condition changes (Which we check
whenever a signal fires that fits that specific decorator). This makes
the AI much more responsive to change in environment.

For behaviors, we still use the ai_behavior datums. These are the actual
behaviors such as "Move to X", "Attack X". The only major change is that
these can no longer sleep() since they now run in the ai_controller.

Lastly, we now also have subtrees, except now they are essentially
pieces of behavior tree that can be re-used, or even overriden at
runtime or as a variable. Allowing for making modular AI made out of
several smaller trees.

You can set variables on these nodes directly via the extension (see
below), which should reduce the need to make subtypes of behaviors by a
lot. All of these vars are saved on the JSON and will be applied at
runtime.

If you are using subtrees, you can also assign "bindings" to these
variables, which will allow instances of the subtree to override those
variables.

Since a tree structure with variables becomes hard to parse in a JSON,
I've made a VSCode extension to edit these JSONs:

https://marketplace.visualstudio.com/items?itemName=BehaviorTreeG.behaviortreeg
https://github.com/CabinetOnFire/BehaviorTreeG

<img width="1795" height="1268" alt="image"
src="https://github.com/user-attachments/assets/56aa2f0b-3cf9-449f-bca4-8281fca82db6"
/>

This extension allows you to edit the behavior tree JSONs, and browse
through all the behaviors/decorators/subtrees we have

If you'd like more info on how to build these AI check out the
learn_ai.md. I will also make a tutorial to go over more depth on what
the system offers because I kind of suck at doing technical write-ups.

Targetting has been changed to. I've made a new acquire_targets behavior
that takes a target_source (what am I targetting) and
targetting_strategy (what does the candidate need to fulfill to be
considered a target). This allows us to make composites targetting
combinations to reduce the amount of specific find_and_set esque
behaviors we had before. Not everything is ported to this system but
that would be a longer term goal.

I've added a new build_bt script that converts all the behavior tree
JSONs into compiled versions. Why is this needed? Because I wanted to
keep using defines in behavior trees, so we need a way to convert this
into literal values before we send it to DM. This script runs on compile
and should also run in CI (If I didn't fuck that up!). This saves to a
new build/ folder.

I've ported every single AI in the game to this system (except raptors,
Kobsa is working on those so should be in soon!), so I do expect some
bugs to come out of this. But I also fixed some issues that have
probably been in the game for a long time such as:
- Fixed penguins being unable to fish
- Fixed bileworms not being able to devour people
- Fixes goldgrubs not grubbing gold (they could not mine!)
- Lizards actually eat food they find

Either way, I'd reccomend a long TM on this.

1. (Hopefully) a better development experience for making AI
2. Less copy-paste for behaviors, we should be able to re-use more
pieces to make behavior
3. Behavior trees is a more common pattern in making AI, so it should be
easier to find resources to find out how to do things.

🆑 CabinetOnFire, Iamgoofball, SmartKar, Ben10omintrix
refactor: Replaces our AI system with behavior trees, porting all
datum/ai to it
/🆑

I will add this PR with more details down the line. I think I got the
big picture but its a big PR, so sorry if I missed something important.

---------

Co-authored-by: Iamgoofball <iamgoofball@gmail.com>
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
2026-08-15 10:33:57 -06:00
91a15ba310 Turns the Hemophage Species into a Quirk (#5919)
## About The Pull Request
The goal of this PR is twofold:
1. Remove hemophages as a species.
2. Allow anyone to be a hemophage through the use of a quirk.

Currently, hemophages are somewhat limited in what they can look like
bodyshape wise due to being tied to a species, yet almost all of their
abilities and traits are tied to organs.

To-Do:

- [x] Properly implement the removal of the organs when the quirk gets
removed.
- [x] Test the quirk with the other hemophage specific quirks, possibly
work them into toggles with this quirk.
## Why It's Good For The Game
This helps shorten our list of playable species while keeping the core
aspects of hemophage gameplay able to be done. It also increases
customization potential, yippee.
## Proof Of Testing
See below.
<details>
<summary>Screenshots/Videos</summary>
<img width="1917" height="1004" alt="image"
src="https://github.com/user-attachments/assets/f2b6cb97-1425-4888-a9c4-4a7ed30d74bf"
/>

<img width="619" height="154" alt="image"
src="https://github.com/user-attachments/assets/de0c21f9-bca5-4171-8fc9-d6d28b7e3ea0"
/>

</details>

## Changelog
🆑
del: Removed the hemphage specific quirks Masquerade, Sol Weakness, and
Pseudo-Respiration. They are now toggles on the hemophage quirk.
refactor: Refactored the hemophage species into being a quirk:
Hemophagia.
/🆑

---------

Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com>
2026-08-14 19:42:35 +02:00
Alexis 88e84645b1 Merge commit '6b52b564a50e4f3091470529c683587e5de15d49' into upstream-sync-7-22-2026 2026-07-22 13:39:09 -04:00
MrMelbertandGitHub 97cb4ae3b5 Maybe improves radio tts somewhat (hypothetically halves the cost but who really knows) (#96799)
## About The Pull Request

Right now for radio TTS we get hearers twice. 


https://github.com/tgstation/tgstation/blob/62eb74613a141f197cca1f274431b734bd064034/code/game/machinery/telecomms/broadcasting.dm#L165-L170

This is not ideal as it's quite an expensive part of radio handling

<img width="765" height="141" alt="image"
src="https://github.com/user-attachments/assets/8245183b-c810-46bf-b466-9879c33e766c"
/>

My thought is we can remove one of the calls by only calling one or the
other
- If TTS is enabled, call `get_hearers_in_radio_ranges_track_radios` and
combine the list of hearers from *that* list
- If TTS is disabled, just use `get_hearers_in_radio_ranges`

```dm
	// Flat list of mobs who can hear the message
	var/list/receive
	// Assoc list of weakref to a radio to list of weakrefs to mobs who can hear the message
	var/list/receive_radios

	if(tts_radio_id) // only do this if we have a TTS identifier to save on perf
		var/list/recieved_radios_raw = get_hearers_in_radio_ranges_track_radios(radios, frequency)
		receive = list()
		receive_radios = list()
		for(var/radio, radio_hearers in recieved_radios_raw)
			receive |= radio_hearers
			var/datum/weakref/radio_ref = WEAKREF(radio)
			for(var/mob/possible_hearer as anything in radio_hearers)
				if(!isnull(possible_hearer.client) && can_hear_radio_tts(possible_hearer, frequency))
					receive_radios[radio_ref] ||= list()
					receive_radios[radio_ref] += WEAKREF(possible_hearer)

	else
		receive = get_hearers_in_radio_ranges(radios)
```

I also went through and cleaned up TTS handling a bit to make it easier
to parse, mostly completing my reviews from
https://github.com/tgstation/tgstation/pull/95369

No I did not test it

## Changelog

🆑 Melbert
code: Cleaned up radio TTS handling a bit, maybe it'll perform better,
report anything weird
/🆑
2026-07-16 16:03:15 +02:00
Aliceee2chandGitHub c7408ce841 Mapping previews tool for mapper's mapping needs (#96872)
## About The Pull Request

Makes more machinery using MAP_SWITCHes so their fancy preview icons
could be displayed in SDMM. MAP_SWITCH takes original icon+icon_state of
machinery as first argument and icon+icon_state (basically a machinery
part because the naming system, like `MAP_SWITCH("computer",
"/obj/machinery/computer/slot_machine")` ) from
icons/obj/fluff/map_previews.dmi

Adds a tool (subsystem) for that need that generates preview icons for
stuff that has overlays. To include them in preview generating you have
to set specific variable to TRUE.


## Why It's Good For The Game

Lets us do this instead of black boring consoles: 
(before)
<img width="641" height="575" alt="image"
src="https://github.com/user-attachments/assets/35fc5a19-bc24-4c02-957a-43ddef86e684"
/>
(after)
<img width="641" height="575" alt="image"
src="https://github.com/user-attachments/assets/99310823-747f-4e0a-acf8-60abcc8f2ed1"
/>


## Changelog

🆑
qol: Made machinery with overlays actually be properly displayed in SDMM
editor.
/🆑
2026-07-15 12:48:22 +00:00
0716e3fff4 Atmos refactor & speedup by utilizing BYOND 516 vector functions (#96448)
## About The Pull Request

### Summary
This PR changes internal structure of `/datum/gas_mixture`:
`gases[gas_id][MOLES]` refactored into `moles[gas_id]`,
`gases[gas_id][ARCHIVE]` into `moles_archive[gas_id]` and
`gases[gas_id][GAS_META]` into `gas_meta` static variable. This allows
us to use BYOND 516 vector functions for calculating total moles and
heat capacity. Also it simplifies some parts of the code, allowing us to
get rid of macros `ADD_GAS` and `ASSERT_GAS`. According to the profiler
`/turf/open/process_cell` time is reduced by ~20%.

### Details
`gas_mixture.gases` was a nested 2d-list with MOLES, ARCHIVE and
GAS_META for each gas_id. For example, to get gas moles you had to do
`gases[gas_id][MOLES]`. I've changed this structure to be as follows:
`moles[gas_id]` - moles for the gas, `moles_archive[gas_id]` - archived
version of moles, `gas_meta[KEY][gas_id]` - static var with meta
information for the gas.

Since I removed key GAS_META from the gases, `gas_meta` was moved to the
static variable and the order of keys in the array was changed from
`gas_meta[gas_id][META_KEY]' to 'gas_meta[META_KEY][gas_id]`. This was
done to allow using it in vector calculations (for example heat capacity
or fusion power). Static variable access is very fast and it is
considered as accessing a global in the bytecode.

Byond 516 introduced new vector functions: `values_sum`, `values_dot`
and others. These functions are very fast, but operate only on
associative lists. This allows us to change the way we calculate
total_moles and heat_capacity - very hot and heavily used functions.
`total_moles()` became just `values_sum(moles)`, and `heat_capacity` is
just a dot product: `values_dot(moles,
gas_meta[META_GAS_SPECIFIC_HEAT])`.

As a side bonus, since `moles` is just an associative list, you don't
really need old macros `ADD_GAS` and `ASSERT_GAS` - all they did was to
make a copy of a list[3] with default value [0, 0, gas_meta] for
specific gas. Now when you're adding gas you can just use `moles[gas_id]
+= amount` and when you query amount of gas you can just query the key
(for example `moles[/datum/gas/oxygen]`) if the key does not exist, it
returns null and works as 0 for all arithmetic and logic operations. For
example, old code would be `if (!air.gases[/datum/gas/oxygen] ||
air.gases[/datum/gas/oxygen][MOLES] < 1)` and now it is `if
(moles[/datum/gas/oxygen] < 1)`. This simplifies some parts of the code
and also speeds things up.

For the performance comparison I used Tracy profiler. I've done many
different tests, and they all show slightly different numbers, but
overall speedup for `process_cell` is about 20%. (-20% to average time
per call from ). My testing setup was as follows:
Load Icebox, drop 30/60/90 radius bomb in the middle of the bridge, set
code to blue, wait 10 minutes until the round ends.
Also I fixed random seed in the master controller and in the planetary
gas randomization so generated maps are the same between tests.
Althought it's not very realistic, it generates a lot of samples for the
`process_cell` (around ~3.5M per 10 minutes).
Another test I did was a plasmafire in an 8x8 space, on runtime station,
it showed (-24% time on process_cell).
Another test was a emagged holodeck burn test, it showed (-13% time)
As for other functions of gas_mixture: `total_moles`: -50%(2x speedup),
`heat_capacity`: -65%(3x speedup), `share`: -30%, `react`: -20%. Timings
of all those functions is in microseconds range and they are very hot
(call count is in the same order as process_cell)

<details><summary>Some pictures from profiler</summary>
<img width="569" height="642" alt="process_cell"
src="https://github.com/user-attachments/assets/76fa0c27-719d-485d-9bfc-859fef788999"
/>
<img width="572" height="315" alt="image"
src="https://github.com/user-attachments/assets/f68497e9-4db8-4a9c-b43f-ad04e6dc5cac"
/>
<img width="569" height="317" alt="image"
src="https://github.com/user-attachments/assets/d7249e7b-f344-47a6-8b39-1bab0521182d"
/>
<img width="541" height="316" alt="image"
src="https://github.com/user-attachments/assets/1bef71fd-533d-40fa-a85e-7a803ad322f7"
/>
<img width="519" height="409" alt="image"
src="https://github.com/user-attachments/assets/51165289-174e-403d-a09c-787dd9af136a"
/>
<img width="523" height="318" alt="image"
src="https://github.com/user-attachments/assets/fe4b1db0-17d8-47f9-8fd0-e2ecef2ee66a"
/>
</details>

<details><summary>Setting up a profiler</summary>
If you wanna to reproduce my results here is a list of steps

1. download: https://github.com/goonstation/byond-tracy-writer (this one
has offsets for my version 1677)
2. build the dll, drop in the tgstation/ folder
3. download rtracy https://github.com/Dimach/rtracy
4. download Tracy profiler (0.13.1) https://github.com/wolfpld/tracy
5. uncomment `#define USE_BYOND_TRACY` in `_compile_options.dm`
6. build tgstation
7. open dream daemon, run the desired test, after round end dream daemon
closes
8. navigate to tgstation/data/profiler, find the `123412341234.utracy`
file
9. run `rtracty 123412341234.utracy`
10. open tracy-profiler.exe, press Connect, save the profiler data
11. repeat steps 5-10 with another branch, save another profiler data
12. open tracy-profiler, open first data, press compare, open second
data
</details>

## Why It's Good For The Game

## Changelog
🆑
refactor: Atmos refactor & speedup by utilizing BYOND 516 vector
functions
/🆑

---------

Co-authored-by: san7890 <the@san7890.com>
2026-07-14 20:34:31 -07:00
MrMelbertandGitHub 18a1d31ca2 Maybe fix sound token hard deletes (#96903)
## About The Pull Request

`remove_listener` would fail on logout so instead I figure we could
track the tokens on the mob, rather than the client

Functionally not much is changed - but if you go from ghost to mob it'll
remove the token from the ghost and adds the token to the new mob, so it
should fix the issue

There also doesn't need to be any code in `/mob/destroy` because we
listen for `listener_deleted` and remove listeners on the token itself
2026-07-10 22:39:25 -06:00
FalloutFalconandGitHub 13266d8c55 Job sorting using department order for Jobs (#96835)
## About The Pull Request
Reworks the code for job sorting so that job order is ADDED onto
department order, to create a sorted list that properly mimmics how its
acctually displayed in game (which is the only way its used anyway)
This means we can shift all the display orders to be inner-department,
meaning we can cut down the size of indecies you have to shift to update
a job(if any)

Also adds a unit test to ensure jobs and departments dont overlap orders
to prevent any odd sorting behavoirs
## Why It's Good For The Game
Prevents having to shift a ton of entires every time a job is sorted or
removed.
Creates a more sensible ordering so we dont have stuff like assistant
being 1, prisoner being 40, despite the fact that they are displayed
grouped.

The only playing facing change is the command roles now get sorted how
there departments appear in the order.
<img width="1012" height="658" alt="image"
src="https://github.com/user-attachments/assets/e641cdd1-a9b8-4f32-be19-f133b8c987dd"
/>
Old order for reference (putting the hos higher up makes alot of sense
here tbh)
<img width="268" height="200" alt="image"
src="https://github.com/user-attachments/assets/42737704-8527-4dee-bac2-a09279d3b64e"
/>
## Changelog
🆑
refactor: Job sorting is based on department
/🆑
2026-07-09 16:53:44 +02:00
SmArtKarandGitHub 12bca76e5d Fixes broken DreamSeeker debug launch option (#96860)
Verb PR broke the dreamseeker debug launch option and will spew runtimes
until the debugger chokes and crashes. A lot of our devs use this option
so this is pretty high prio.
2026-07-07 22:53:31 +02:00
SmArtKarandGitHub 8f6c36dc76 Fixes particle weather bleeding through z-levels when different weathers are present (#96802)
## About The Pull Request

The original implementation was flawed as it added all particle holders
to vis_contents and displayed/masked all of them at once if the z-level
had any weather present. This caused "bleed-through" if two z-levels
with the same z-stack offset had particle weather running at the same
time (such as ash storm on lavaland and a weather anomaly rain on
station's first z-level) causing particles from both z-stacks to display
on both z-levels. By tracking holder's assigned z-levels we can filter
holders not affecting any levels in the current plane z-stack, which
solves this issue. There's still the problem of multiple particle
weathers running on the same z-level, but this is so insanely rare (and
also some other code would break anyways) I don't think its worth
currently bothering with as it would require some insane code to
resolve.

## Changelog
🆑
fix: Fixed particle weather bleeding through z-levels when different
weathers are present
/🆑
2026-07-07 09:32:15 +02:00
PapaMichaelandGitHub 01987d37b5 Paradox Clone poll now names the target (#96806)
## About The Pull Request

Instead of rolling the target of a Paradox Clone after the poll, rolls
the target before the poll, so ghosts are opting in to a specific
"Paradox Clone of John Spaceman (Assistant)"

Also lets admins choose the target of paraclones from the dynamic panel

## Why It's Good For The Game

Paradox Clones are a pretty unpopular antagonist which, depending on the
target, can have a drastically varying impact on the round. People might
be more willing to sign up if they can see ahead of time that they'll be
able to play as the captain's clone and have a high impact on the round,
vs. an assistant's clone and have less impact.

## Changelog

🆑 PapaMichael
balance: Paradox Clones ghost poll for a specific target; ghosts are now
signing up to be a specific person's clone.
admin: If admins spawn a Paradox Clone, they can choose the person to be
cloned.
/🆑
2026-07-05 19:15:01 +02:00
ff8b3e2b41 Lizard Gas Rework, Fixes & More (#5802)
## About The Pull Request

A big update that reworks the Lizard's Gas Station, that fixes existing
issues and makes the role overall more interesting.

A third spawner is added, which is the Manager, who will be held to a
higher standard, and is expected to be in charge of interactions between
Lizard's Gas and other factions, along with controlling the budget. The
manager spawns in with slightly more equipment that better allow them to
protect themselves, their workers, and the station itself from danger.
(A unique outfit for them is also planned, but it is still a WIP)

Lizard's Gas will now have their own unique budget, which is mostly for
fluff, but is also intended to be used for tracking the profits, paying
the workers, and for making orders through trade - as an express console
(like Tarkon or Persistence) would be counterproductive as the ghost
role is intended to interact with others.

Entirely new map layout, highly inspired by European service stations.
This reworked layout has the following features:

- A bigger shopfront, with shutters and direct connection to the
employee only areas.
- Store area itself made bigger, with a greater variety of goods on
sale, along with a pair of flatpacked quantum pads.
- The removal of the old shed outside of the gas station itself, which
held the majority of equipment.
- A garage, being the new dedicated workspace. Now holds most of the
equipment that was in the shed.
- A utility closet, containing the rest of the equipment, along with a
big air tank and an SMES that actually works.
- A CCTV system for the gas station, so you can view both what is
outside and inside from relative safety.
- A proper break room, for the employees, with privacy and access to the
CCTV.
- A nice fancy office, for the manager, with privacy and additional ways
to contact other factions (holopad and fax machine), and of course
access to the CCTV.
- Air conditioning, could you imagine having to work on lavaland or an
icemoon without it?


Three new biogenerator machines that are (currently) entirely unique to
Lizard's Gas, these combine some of the functionalities of other already
existing biogens, while adding much more to them to create additional
incentives to both play the roles and interact with them. These could
potentially be added to other ghost roles in the future, as they are
intended to cover for the lack of access to certain machinery or just
general lack of space or extra hands to achieve the desired outcome. The
medical biogenerator specifically is also meant to cover for negative
quirks that normally would result in a quick death due to the lack of
access to the quirk specific medicines, or to simply treat most common
injuries on lavaland - making the role accessible to way more player
characters.

Also currently _planned_:

- New power generators, fueled by wood and biomass.
- New outfit for the manager.
- Fixing the prefab shutters, as their animation is broken and their
sprite could use more work and additional frames.
## Why It's Good For The Game

The intention is to give the gas station the means to easily be
self-sufficient, along with the right tools to connect themselves to a
trading partner of their choosing without being intrusive - a cargo
teleporter and a pair of quantum pads. This will allow Lizard's Gas to
establish a direct link with others, allowing there to be much more
interactions between it and their partner of choosing with much more
ease, but still requiring the other side to assist by setting up their
own cargo teleporter and deploying the quantum pad on their end. Also,
being a neutral faction in a (literal) hotspot, they could act as an
interesting hub for interactions between other factions or themselves.

Here's a much more detailed breakdown of the issues being solved:

- Spawn reliance - A bad spawn entirely dictates who you can and will be
able to interact with, for a ghost role which is guaranteed to spawn,
the spawn location shouldn't play this much of a factor. As such,
Lizard's Gas now is provided a pair of flatpacked quantum pads and a
cargo teleporter to be able to cooperate with any other entity to
establish a quantum pad link (Communication being done by fax or PDA).
Using the Cargo Teleporter allows the Quantum Pads to be set up without
needing someone to actually manually to the Gas Station.
- Quirks - Certain quirks that rely on medicines completely screw you,
as getting more will require a full chemical setup, such as Phobia,
Brain Degeneration, or the worst offender: Asthma. This is solved by the
medical biogen added to Lizard Gas.
- Husked = Roundremoved - If you somehow managed to get husked, or
suffer a serious infection, you are pretty much dead dead. With your
only real options is being taken to the station, or praying the
Persistence players somehow stumble upon your dead body. To solve that
issue without giving Lizard Gas a full chem setup, they instead can just
make synthflesh patches with one of the biogens.
- Bad Piping & Cables - The original map had serious issues with the
piping, such as certain devices not being connected, being useless, or
just going through walls when it is unnecessary, the worst offender was
the oxygen recycler which is meant to suck in oxygen from lavaland not
even working. Cables wise, the SMES was only able to draw power, and not
output any of it.
- No Theft Prevention - Coming across Lizard Gas previously without
knowing about it could easily result in people accidentally stealing
from the Ghost Role, as most of their supplies were completely out in
the open and protected by two notes left on the floor. All of those
supplies are now moved inside.
- No Unique Access - Anyone could wander into the Gas Station if it was
unbolted, and then enter the back areas and snatch whatever they wanted,
which is even more of an issue when they are now provided with three
unique machines that are fairly powerful. Giving the doors special
access only provided to the Gas Station workers fixes that before it is
even an issue.

Along with fixing the aforementioned issues, there are quite a few
additions that are meant to provide the following benefits:

- Interaction Incentives - Now that it is more accessible, Lizard Gas
required a bit more of a unique 'stock' to provide to people visiting
it, and since none of them operate any plasma-fueled vehicles, the next
best thing is selling them items for convenience, at a store, a
convenience store if you will. With the three new machines, Lizard Gas
will have access to a lot of products they can mass produce on the spot
using only biomass. They can make you a burger on the spot! Sure, it
tastes very synthetic and not that high quality, but it is produced on
the spot. Most of the other products are already available in Company
Imports, but this will be an option to trade for it for cheaper, player
interaction is a good thing!
- Neutral Hub - Being able to link themselves up other locations using a
Cargo Teleporter and a pair of Quantum Pads allows the Lizard Gas
workers to link up with the Station, Tarkon, and the Persistence - as
long as there is someone else on the other end with a Cargo Teleporter
as well. This allows all three groups a Neutral ground to be in,
hopefully allowing for more interactions between players without having
to worry about antags, while also being able to return to their
workplace quickly and with ease.
- Third Spawn - Adding a Manager, which fits thematically, and is
expected to be held to higher standards. Now Lizard's Gas is a three
slot Ghost Role!
## Proof Of Testing
<details>
<summary>Screenshots/Videos</summary>

Comparisons!
**Old Lizard Gas:**

<img width="799" height="799" alt="StrongDMM_VGH8uAiA9r"
src="https://github.com/user-attachments/assets/1f72c14c-b070-4871-9058-bb7a540768c0"
/>

**New Lizard Gas (Icebox):**
<img width="1356" height="1017" alt="dreamseeker_KLV97bjWii"
src="https://github.com/user-attachments/assets/8b09df34-a64b-42a3-8af0-70de6b74fcd1"
/>
<img width="1356" height="1017" alt="dreamseeker_OAcImdnaPf"
src="https://github.com/user-attachments/assets/86f6a343-3979-4ed6-a5eb-7e8db9ad4cc8"
/>

**New Lizard Gas (Lavaland):**
<img width="1360" height="1017" alt="dreamseeker_N0k7u5zD8i"
src="https://github.com/user-attachments/assets/3848a851-2213-44f2-bfac-eb2133f68526"
/>
<img width="1356" height="1017" alt="dreamseeker_dedS1dHqaB"
src="https://github.com/user-attachments/assets/d928713e-8bef-40eb-acfc-dbb3ba8d5cfd"
/>

**The new machines & Contents:**
<img width="275" height="138" alt="dreamseeker_NpTCSRoj6k"
src="https://github.com/user-attachments/assets/06579bbe-11eb-4972-9fba-b5df4b30c51b"
/>
<img width="1189" height="973" alt="yLPMyfBjkU"
src="https://github.com/user-attachments/assets/5174833f-bc91-43b6-a472-873e94c4e93b"
/>
<img width="1189" height="711" alt="lRgw4dVQux"
src="https://github.com/user-attachments/assets/8d6cf74e-5e3e-4110-b6b5-ae1800a8f97b"
/>
<img width="1189" height="679" alt="7myy2173s3"
src="https://github.com/user-attachments/assets/c949851c-f487-47a5-9bf5-4db6c2b62e7f"
/>

</details>

## Changelog
🆑 Moldb, Cerberushopeless, Dr.arielpro & Projectkepler-RU
add: Added 3 new unique biomass based machinery intended for ghost roles
only. They are functionally similar to cargo-orderable biogens (Organic
Ration Printer, Organic Material Printer, Colonial Supply Core, Wall
Med-Station) but are consolidated into much more specific roles, while
also adding additional items to their lists.
add: Added an additional spawner to Lizard's Gas, in the form of a
manager role.
add: Gave Lizard's Gas their own budget card, which can only be spent
through trading with others. Their card is actually capable of
withdrawals.
image: New sprites used by the new biogens, taking direct inspiration
from pre-existing machines to fit in nicely.
map: Near complete rework of the Lizard Gas station, making it much more
roomy and more akin to an European service station.
/🆑

---------

Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
2026-07-05 12:12:45 -04:00
e4b395055c Makes prefs application for ghost roles more flexible and granular (#96683)
## About The Pull Request

Tin, also applies this to the nightmare role since they shouldn't be
getting prefs applied to their mob.

## Why It's Good For The Game

You don't always want prefs to be applied the same way (or sometimes, at
all) for each ghost role, and by just moving that logic out to
overridable procs. this allows for granular control over that

## Changelog

🆑
fix: shadows will no longer get the candidate's prefs applied to their
mob
/🆑

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
2026-07-05 09:02:56 +02:00
LemonInTheDarkandGitHub 9f0abf30a0 Unfucks the map stale system (#96770)
## About The Pull Request

The idea is to remove from voting maps which have ran twice in the past
3 rounds + the current round we are voting in.

This is fine at highpop, bad at lowpop. Config to clear was added in
#95120, that config was broken because it was spelled incorrectly in the
config file (min instead of minimum). Easy fix.

Second problem, this can recreate the "0 votable maps" problem from
#96493 because it can trim the only votable maps out. Let's just add a
case for this and ignore staling if it happens.

I have not tested this in detail due to hand issues, I think it's fine
tho.

This should resolve the infinite not meta we've been sometimes seeing
during lowpop.

## Why It's Good For The Game

Headmins will yell at me less.

## Changelog
🆑
fix: Fixed some sillyness with the stale map system
config: MAP_VOTE_MIN_POP_TO_REMEMBER_MAPS ->
MAP_VOTE_MINIMUM_POP_TO_REMEMBER_MAPS
/🆑
2026-07-04 19:58:53 +02:00
ff006aa4a5 verb macro system (pr 1/3) (#96720)
## About The Pull Request

just macro-izes all the usages of verbs in the codebase as a
pre-requisite to my follow up pr that serializes all the verbs arguments
so we can tgui-ify the command bar, so we can then put it on the
onscreen map.

this also basically does the same as #94487 so can easily be integrated
into the verb queueing stuff... but does not actually do any verb
queueing by itself. basically im just trying to be
https://github.com/tgstation/tgstation/labels/Atomic
## Why It's Good For The Game
it doesn't really do anything by itself but it does let us do more stuff

## Changelog
🆑
code: the backend to all verbs in the game has been played with, please
report any issues to github
/🆑

---------

Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
2026-07-04 02:45:07 -04:00
Richard BlonskiandGitHub c656ba9945 Semi Port - Add Wine/Linux users CID to an ignore list (#96484)
## About The Pull Request

This PR attempts to somewhat port
https://github.com/cmss13-devs/cmss13/pull/11252
In order to add Wine/Linux CID into an ignore list to stop the
`Your ComputerID has already logged in with another key this round,
please log out of this one NOW or risk being banned!`
Jumpscare message from appearing and log users which connect with
ignored CID's to admins properly.

### Testing the Pull Reuqest
I've attempted to test the PR locally, but I have been unable to
replicate the duplicated CID message, so this might need to be **test
merged** if approved.

In addition, please review the code, my experience with Byond is very
limited so feel free to edit, commit, or requested changes per need.

## Why It's Good For The Game
If two players with the same CID (such as the case with players who play
using Wine), the joining players will get a pop-up saying they are using
the same CID and get a **scary** message that they risk getting banned
for multiboxing if they don't log off.

Experienced game staff, most of the time already know to ignore the CID
`4055623708` which is often thrown by Wine.

However, players could abuse this fact to still and try to multibox for
whatever reason, and even if a legit Linux player uses this CID, giving
the admins a separate log for it is useful, to be distinct from normal
multibox messages.
`MULTIKEYING: [key_name(src)] Connecting player joined with IGNORED CID
[computer_id].`

## Changelog
🆑 Richard Blonski
admin: Added Ignored CIDs, a message will appear when a player joins
with an Ignored CID.
/🆑
2026-07-02 06:34:52 +02:00
Roxy de4c3b255d Merge branch 'master' of github.com:tgstation/tgstation into upstream-2026-06-23 2026-06-23 15:51:55 -04:00
LT3andGitHub 5e9e8f3f99 Fixes tram duplicate/unlabelled tram announcements, reduces range (#96606) 2026-06-22 22:33:45 -04:00
RoxyandGitHub eca87996a5 Fix build script always recompiling dm target (#96568)
## About The Pull Request

Juke is supposed to use file modification times to decide whether a
target needs to be rebuilt, this isn't working because the Greyscale
Previews system always replaces the DMIs in `icons/map_icons` even if
they haven't changed, so everything in that folder will end up with a
more recent modification time than the DMB. Tweaks the code so that the
copy only happens if the file has changed

## Why It's Good For The Game

If I'm doing debugging that requires repeatedly launching the server
with no code modifications in between, it'd be nice to not have to wait
for a pointless compilation every time

## Changelog

N/A
2026-06-18 13:05:20 -06:00
ReturnandGitHub a9c562038b Fixes station time being broken (#5777)
## About The Pull Request
This fixes the station time being incorrect on the statpanel, due to the
way time is handled being changed upstream
## Why It's Good For The Game
Correct time. It is not 2026 in setting
## Proof Of Testing
<img width="327" height="99" alt="image"
src="https://github.com/user-attachments/assets/b5c23b31-a0f7-4d2d-8fba-c3799f0c98ee"
/>

</details>

## Changelog
🆑 ReturnToZender
fix: Station time now shows the correct year
/🆑
2026-06-17 18:32:39 -05:00
MrMelbertandGitHub 79cdde5b4e Head revs get codewords, rev antag info panel (#96425) 2026-06-17 22:37:58 +10:00
33824ac7c1 TTS 3.0: Blips Rework, Radio TTS, Unknown Languages are Blips now (#95369)
## About The Pull Request

Re-did blips to be significantly nicer sounding and way better. Alien
speech you don't understand now comes through as Blips. If you have TTS
entirely disabled, you won't hear blips. Blips also now include more
customization options, and a dedicated Blips preview button by clicking
the leaf icon.

<img width="1749" height="354" alt="ApplicationFrameHost_5nKJEvaNV1"
src="https://github.com/user-attachments/assets/ef6c6b61-7c22-4a87-94c9-be50e89c65bb"
/>


https://github.com/user-attachments/assets/8cab7e55-6370-4e4e-99ba-ea2475569453

Radio TTS has been implemented. By default, you will hear all TTS over
the radio, but will not hear yourself over the radio. You can configure
this in Game Settings.


https://github.com/user-attachments/assets/94a44d84-17a9-4e6e-ac5c-3b800b11c159

<img width="743" height="193" alt="chrome_MOIcXaC2gh"
src="https://github.com/user-attachments/assets/907379b7-0689-486c-b29c-9be0a2259b05"
/>

The new TTS stack is located at
https://github.com/Iamgoofball/tgtts-qwen3 and is AGPLv3 licensed. The
new blips design was inspired by
https://github.com/joshxviii/animalese-typing.

The configuration to disable TTS on whispering has been removed, as it
is no longer needed and also interferes with radio TTS functioning
properly.

The Tram now utilizes TTS, and has had a general audio tune-up.


https://github.com/user-attachments/assets/f532d002-939c-43a1-95d0-0f0c43048997

TTS audio is now 3D and in space, see attached.


https://github.com/user-attachments/assets/b00df49a-9d1d-4b27-a8a0-d103099f5c7e

## Why It's Good For The Game

Quality of life improvements to the TTS system, long overdue. Also, TGMC
can migrate to this new method of doing radio audio so they aren't
sending double the TTS requests anymore.

## Changelog

🆑
add: Added support for Radio TTS. You will now hear players over the
radio via the TTS system.
add: Configure this in Game Options under the Sound tab.
sound: Re-did blips to be significantly nicer sounding and way better. 
sound: Alien speech you don't understand now comes through as Blips. If
you have TTS entirely disabled, you won't hear blips.
sound: The Tram and Computers now utilize the TTS system. Configs have
been added to set a consistent voice.
sound: TTS audio now utilizes 3D audio; you can now walk away from
people saying stupid shit and it gets quieter.
sound: Blips also now include more customization options, and a
dedicated Blips preview button by clicking the leaf icon.
del: The configuration to disable TTS on whispering has been removed, as
it is no longer needed and also interferes with radio TTS functioning
properly.
/🆑

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Lucy <lucy@absolucy.moe>
Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
2026-06-15 18:54:24 -04:00
Ben10OmintrixandGitHub fc55a930a9 Baby stoats can become adults (#96491)
## About The Pull Request
Baby stoats can now grow into adult stoats. ive also included kits into
the spawn pool of maints, (the overall chance of running into a stoat
whether adult/baby remains the same), and you can also now find baby
stoats rummaging through bins. since baby stoats are cute ive made their
growth rates slow so people can enjoy them at their youths for longer.

## Why It's Good For The Game
fixes an oversight.

## Changelog
🆑
fix: baby stoats can now become adults
add: baby stoats are added to the spawn pool of maints, (the overall
chance of running into a stoat whether adult/baby remains the same)
/🆑
2026-06-15 15:41:27 +12:00
LemonInTheDarkandGitHub b5f3b89d8a Fixes rotation breaking on one votable map (#96493)
<!-- 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

Basically, if it's forced, we rely on create_vote to catch the "no
options" case.
This used to be the behavior, but it was removed in persistant tallies.
I have no idea why.
I've also cleaned up the quite dubious caching code to avoid the bugs I
was getting when testing locally.

## Why It's Good For The Game

S been causing forced icebox (15 pop min, meta can't replace it because
meta's the only one with 0 minpop) on the servers, that's silly.

Of note, it's possible this will still be an issue due to the stale map
system, but yaknow, one thing at a time, and that'll be louder so we
should find out pretty fast (fix would be defaulting to some marked
default map if only one can be rolled).

## 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 its 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. -->

🆑
fix: End of round mapvotes will now properly default to the only option
if only one map is votable.
/🆑

<!-- 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. -->
2026-06-14 22:27:28 +02:00
FalloutFalconandGitHub 58108d629d Fixes ambience subsystem removing players permanently (#96498)
## About The Pull Request
Fixes #96497 which was created by #59071

Im not really sure why the mob check exists, im moving it to a continue
for the same reason as the newmob check.
## Why It's Good For The Game
Unless this is meant to be a micro op, it just doesn't make sense to
completely drop them from the list, especially if we never readd them 😿
## Changelog
🆑
fix: Clients who sit in the lobby after pregame will no longer have
there ambience disabled till they reconnect
/🆑
2026-06-14 17:08:28 +02:00
anetteraandGitHub e3cd6981c2 Use lore time for a couple spots that list NST (#96320)
## About The Pull Request
Use the year offset value to display accurate time in statpanel 
<img width="351" height="84" alt="image"
src="https://github.com/user-attachments/assets/302782c8-3e7d-463c-8a2d-1feecd8a1f4b"
/>
Statpanel won't doesn't have access to client prefs and I'm not fixing
that so no 12hr clock
## Why It's Good For The Game
muh immersion
## Changelog
🆑
fix: statpanel uses year offset
/🆑
2026-06-13 14:54:35 -07:00
Ben10OmintrixandGitHub 64baa1979d Basic mulebots. last basic bot refactor (#95899)
my watch has ended

<img width="401" height="256" alt="ffffff"
src="https://github.com/user-attachments/assets/a539203c-020b-4ad8-b034-f69ec0eafa78"
/>



## Changelog
🆑 Profakos (originally pulled from their branch, did massive chunk of
this), Ben10omintrix
refactor: mulebots have been refactored. please report any bugs
/🆑
2026-06-11 23:58:13 -07:00
IajretandGitHub 8ef4eb31bc De-hardcodes wilderness levels z-traits (#96426)
## About The Pull Request
Tin. If someone decides to add wilderness levels for maps that isnt ice,
they will not suffer anymore. Uses default icy wilderness traits
(renamed define for clarity), also adjusted another var name, for
clarity too.
## Why It's Good For The Game
Allows for a higher degree of customisation for wilderness levels, which
is a very good idea, but somehow it was hardcoded to only work with snow
maps.
## Changelog
Nothing player facing (i hope)
2026-06-12 01:03:50 +02:00
0bd4b0820f Adds TGMC Tactical maps to the game and to Nuclear Operatives! (#96068)
<!-- 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

Brought to you by Team Powercrèpe.(same group of people that delivered
the Heretic Overhaul)

This PR ports the TGMC Tacmaps and grants em to our NukeOps.

Code by Me, @Xander3359, @Arturlang, @Absolucy.

Mapping by @RipGrayson 

Sprites by @KillerOrcaCora

Writing bits by @necromanceranne

Tacmaps are essentially dynamically generated minimaps,

<img width="1711" height="1335" alt="Tac map examples"
src="https://github.com/user-attachments/assets/f936fac0-fb7c-4b84-970d-7195b4995ca7"
/>



<img width="1274" height="714" alt="Tac-Maps Icons"
src="https://github.com/user-attachments/assets/0f04e388-af4b-4955-be7a-04650cfd746b"
/>






As you can see from the screenshots above, departments are classified by
color, hovering your cursor over an area or a team mate, will display
their name, the system does allow the user to switch between Multi-Z,
and lastly you can draw and add labels to the map, although the last
option is only available to the NukeOps Leader and OW agents.


The functionality is tied to the Syndicate implants nukies start with,
Cayenne, Syndie borgs and Mechs also have the ability to toggle the map.

Likewise, the tacmaps will display the positioning of the following in
real time!

- Nuke ops agents

- Syndie borgs and Mechs

- Cayenne

- Location of the nuclear fission device (and beer nuke)

- Location of the Nuclear Authentication Disk.

<img width="1274" height="714" alt="SkyBridge OFF"
src="https://github.com/user-attachments/assets/3915e7d7-644a-4e9a-b213-997834dde2ea"
/>

<img width="1274" height="714" alt="SkyBridge ON"
src="https://github.com/user-attachments/assets/13748290-fd16-42ba-a9c4-a6b4f7e69c79"
/>

<img width="566" height="459" alt="Holo table done"
src="https://github.com/user-attachments/assets/1a43c5b7-ee51-4794-9c09-16b4fb50e2ad"
/>






https://github.com/user-attachments/assets/caf38538-ef04-4330-992c-3137a67ea0d0






Lastly The tactiical map implant cannot be be used on the nuke ops
base,If the team wishes to interact with the map they'll have to
Interact with the "Reconnaisance Platform" (Sprite by Orcacora) in the
briefing room, which has seen some mapping changes (Brought to you by
TheLastGrayson).



<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->

## Why It's Good For The Game

Originally this feature was planned for the Upcoming Contractor Rework
our team is currently working on, but given the massive size of it all,
we decided to atomize it.

But without that consideration in mind, I think it makes sense for
Nuclear operatives of all antagonists to have the means to Recon and
plot an assault plan onto the station and actually be able to know the
whereabouts of their teammates.

Obviously this feature has a lot of other potential applications, we
have wanted to have functional Maps for a very long time, if someone
wants to give it a go once the feature is merged, by all means.

<!-- 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. -->

## 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 its 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. -->

🆑
add: Tactical Maps have been added to the game!
add: Nuclear Operatives implants now grant the ability to open a
Minimap, this map will display and show the names of various areas of
the station, and the positioning of the Nukeops team,borgs,mechs,Cayenne
and the nuke disk in real time!
add: Nukie leaders and OW agents can also draw and apply labels to the
map.
add: the "Recoinassance Platform" has been added to the Nukie Base, it
allows displaying of the Tactical maps while on the Syndicate Base Z
level.
map: The briefing room in the NukeOps base has been remapped to better
accomodate the new Holographic table.
map: Changed the front shutters on the Syndicate Infiltrator to the more
fitting Syndicate Shutters.
/🆑

<!-- 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: Xander3359 <66163761+Xander3359@users.noreply.github.com>
Co-authored-by: Artur Lang <24881678+Arturlang@users.noreply.github.com>
Co-authored-by: Lucy <lucy@absolucy.moe>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: RipGrayson <49290523+RipGrayson@users.noreply.github.com>
Co-authored-by: necromanceranne <40847847+necromanceranne@users.noreply.github.com>
2026-06-09 16:38:00 +02:00
soulwareandGitHub e843f46d1f Move carving block to basic recipes (Allows carving blocks to be made out of any material) (#96347)
## About The Pull Request
Allow carving blocks to be made by any material, instead of just rigid
materials.
## Why It's Good For The Game
<img width="612" height="70" alt="pride"
src="https://github.com/user-attachments/assets/afb5ed16-ba7a-4910-9b36-8fed8267536a"
/>

This allows for the construction of
Ice Statues (Hot Ice)
Beige Statues (Sand + Sandstone)
Snowpeople (Snow)
Origami Statues (Paper)
Cardboard (Cardboard)
REAL ghosts (Hauntium)
Meat Statue... 🤤🤤🤤🤤 (Meat)
(Not pictured) Pizzer Statue (Pizza)
Also more player expression + if you could make chairs and airlocks and
toilets and sinks and all that other shit out of these, why the hell NOT
a carving block!?
## Changelog
🆑
balance: Carving blocks can be made out of any material now!
/🆑
2026-06-07 22:52:18 +02:00
67bbc096a8 Introduces particle weather, converts rain and ash storms to it (#96297)
Co-authored-by: Lucy <lucy@absolucy.moe>
2026-06-06 19:33:45 -04:00
CabinetOnFireandGitHub cfd1c8bb67 Replaces lavaland generation (Cellular automata caves) with a more sophisticated cave network system (#96026) 2026-06-06 15:36:14 +00:00
5a68cb5ff3 Implements "Sound Tokens", a way to have spatial audio. And implements it on looping sounds. (And also some tweaks to fall-off) (#96018)
## About The Pull Request

This pull request implements sound tokens, based on the implementation
by Kapu at https://github.com/DaedalusDock/daedalusdock/pull/1379

I've taken that implementation and extended it to looping_sounds,
allowing us to have spatial audio that updates much more nicely when
players walk closer. This system also lets players that walk into range
after the sound has started playing to also hear the sound, before if
you missed the sound, you would never hear it. This is particularly
noticeable with long sounds (Which is lame!)

**VIDEOS**:
griddle:
https://streamable.com/v7ayqm

engineering / SM:
https://streamable.com/5lr1oj


The system essentially sends the sound to every client, and changes the
volume based on distance to the sound. There are some performance
concerns here, so we will need to testmerge this and see how impactful
it is. It is in a subsystem though, so there is some limit to the amount
of cpu it will use. Do keep this in mind when watching the videos; it
will probably not be AS responsive as in there.

I've also changed how intense our fall-off is, making sounds lose their
volume slower. Before taking one step away from a 50 volume sound would
make it 18 volume, this is way too big of a drop and it became
particularly jarring with the changes in this PR.

Some sounds might be too long range now, but I think we should just
reduce the max range of those sounds as we were basically playing them
at <5 volume after 10 tiles, at which point we should maybe just reduce
the range a bit since at those volumes theyre really not audible.

**OLD FALLOFF;** note the MASSIVE drop from 1 tile to 2 tiles
<img width="1416" height="897" alt="image"
src="https://github.com/user-attachments/assets/805b270e-6aa5-4e84-868e-39585966f0a4"
/>

**NEW FALLOFF:**
<img width="1418" height="905" alt="image"
src="https://github.com/user-attachments/assets/eabbd592-ae9c-4690-8945-fbd0b4f6614f"
/>

Also tweaked a few looping sounds (deep-fryer in particular got some
clean-up, as its mid-length was way too short for the sounds and it had
a double-definition)


## Why It's Good For The Game

This system allows us to have a richer audio experience, I really don't
like how choppy our looping sounds are, especially in some areas where
you hear them a lot (kitchen and engineering)



## Changelog

🆑 CabinetOnFire, Kapu
sound: Changed our falloff to be less intense, as it was punching volume
down way too fast.
refactor: Implements a system for spatial audio to improve our looping
sounds
/🆑

---------

Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com>
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
2026-06-05 16:24:25 -07:00
WisemonsterandGitHub 370a529ace Changes slaughter/laughter demons to use sentient mob pref (#96342) 2026-06-05 11:55:34 -04:00
mrmanlikesbtandGitHub 31967bed59 Makes Destroy() a protected proc to safeguard against improper calls (#96331) 2026-06-04 15:32:12 -04:00
shayoki f17515f75d Update statpanel.dm 2026-06-03 17:10:08 -05:00
shayoki a3e7973adf soft statpanel revert 2026-06-03 17:03:58 -05:00
shayoki 7b6e5356b9 Update statpanel.dm 2026-06-03 16:11:11 -05:00
shayoki f601a6ddaf Merge remote-tracking branch 'tgstation/master' into upstream-6-2-2026 2026-06-03 01:23:54 -05:00
f5fc272810 Random recipe logging (and other stuff) (#96148)
## About The Pull Request
-Log outcomes of random recipe init
* Whether recipe failed to load, and why
* Whether recipe failed to generate, and why
* Whether recipe regenerated due to conflicts, and how many attempts it
took

-Stop saving random recipe results to the persistence file
* They aren't randomized anyway

-Split recipe loading and recipe generation into separate procs
* It was kind of a mess
* This way, you can regenerate recipe without qdel'ing it and then
reinitializing

-Generate recipe if it failed to load
* We used to qdel it instead

-Consider recipe generation to be a failure if there aren't enough valid
ingredients or catalysts
* We used to only check whether possible ingredient list is empty
* Since the possible ingredient/catalyst lists don't change from round
to round, this could probably be made into a unit test in the future

-Reorganize random recipe conflict checks to make them more streamlined
* I had to do it in order to log regeneration outcomes

-Fix bugs which won't ever matter anyway
* optimal_ph_max no longer rolls above 14
* optimal_ph_max can no longer be below optimal_ph_min + 1 (we used to
check for CHEMICAL_MIN_PH + 1, which is just 1)
## Why It's Good For The Game

Logs help spot&diagnose issues which might not come up when testing
locally, like the issue where timestamps wouldn't update which was fixed
by #95895
## Changelog
🆑
fix: random recipes can no longer have upper pH bound above 14
/🆑

---------

Co-authored-by: l0 <-->
2026-06-03 08:04:56 +02:00
MrMelbertandGitHub 6b631cb2c2 Roundstart nuke ops now spawn on an elevator to wait while the base loads in (#96178) 2026-06-02 20:59:42 +10:00
mcbalaamandGitHub 052b3a654d feat: Vote panel UI cleanup; auto-close fix (#96166) 2026-05-27 20:42:04 -04:00
John WillardandGitHub ad450f76e8 Re-attempt at vv editing lobby music (#96093)
## About The Pull Request

Previous attempt was in
https://github.com/tgstation/tgstation/pull/95870 but I got 0 feedback
and it just staled and closed.
Instead of adding it as a secret button I am simply making it so vv
editing the ticker's lobby music will properly update it for everyone.

## Why It's Good For The Game

QoL for admins.

## Changelog

🆑
admin: Changing lobby music now updates for people in the lobby.
/🆑
2026-05-20 19:13:42 +02:00
MrGloopyandGitHub 7303e7777c remove mutual exclusivity of Common second language and Bilingual because i wanted multiple languages once (#5582)
## About The Pull Request
Simply removes the mutual exclusivity of CSL and Bilingual quirks, since
you can have the other language quirk with CSL but not Bilingual.

## Why It's Good For The Game
If you can have the other language quirk with CSL, why not Bilingual?

## Proof Of Testing
if it compiles it works, submitting via vscode
<img width="525" height="447" alt="image"
src="https://github.com/user-attachments/assets/aaf562a6-3ee5-433e-bbed-924196441bb5"
/>

<details>
<summary>Screenshots/Videos</summary>

</details>

## Changelog

🆑
balance: Removed mutual exclusivity of Common Second Language and
Bilingual quirks.
/🆑
2026-05-16 01:04:56 +02:00
+37 21b4095dfd [MDB IGNORE] [IDB IGNORE] Upstream Sync - 04/17/2026 (#5453)
Upstream 04/17/2026

fixes https://github.com/Bubberstation/Bubberstation/issues/5549

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com>
Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com>
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com>
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com>
Co-authored-by: loganuk <fakeemail123@aol.com>
Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com>
Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
Co-authored-by: Lucy <lucy@absolucy.moe>
Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com>
Co-authored-by: Isratosh <Isratosh@hotmail.com>
Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com>
Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com>
Co-authored-by: Alexander V. <volas@ya.ru>
Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com>
Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Tim <timothymtorres@gmail.com>
Co-authored-by: Iamgoofball <iamgoofball@gmail.com>
Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com>
Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com>
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com>
Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com>
Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com>
Co-authored-by: Josh <josh.adam.powell@gmail.com>
Co-authored-by: Josh Powell <josh.powell@softwire.com>
Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com>
Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com>
Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com>
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
2026-05-16 00:56:00 +02:00
John WillardandGitHub e698a66f5e Fixes a merge conflict that broke stat panel (#96071)
## About The Pull Request

Fixes a merge conflict between 2 of my stat panel PRs that caused the
'Toggle Stat Panel' button to not work.
Also converts more skin stuff to defines that I missed in the last PR.

## Why It's Good For The Game

Button works wahoo!

## Changelog

🆑
fix: Stat panel's "Toggle Stat Panel" button now works.
/🆑
2026-05-14 22:35:12 -07:00
JinsheeandGitHub 45a5980443 Tele-Port: Ports Telepathy changes from NovaSector (#5531)
## About The Pull Request

This ports changes from
https://github.com/NovaSector/NovaSector/pull/6016 and
https://github.com/NovaSector/NovaSector/pull/6398.

- The quirk no longer automatically applies the Genetics power to the
quirk user. Prior to this PR, communication was mostly anonymized and
only _not_ so when one possessed the gene. This presented a clear
downgrade for individuals who had the genetic variant over the quirk
variant. With this PR, communication through the quirk is not anonymous,
but adding the gene on top of the quirk will allow a user to upgrade it
into being anonymous.
- Every time someone uses the quirk everyone else (in sight) will see
where their attention is sent. This does not add a visual cue besides
the warning in the chat, so it's still somewhat discrete.
- Added a new quirk, Psionic Dampener. This blocks most forms of
telepathic communication.
- Telepathy was made multiline for readability.

## Why It's Good For The Game

Currently, Telepathy as a quirk has a discrepancy where non-synths
receive the mutation Telepathy, while synths receive a different
version. The mechanical differences of these created a problem where,
depending on who was using it, this either did or did not anonymize the
identity of the caster. Additionally, these changes allow the quirk
holder who seeks the genetic variant in-round to properly receive the
benefits of such.

Other changes allow people to opt-out of receiving telepathic messages,
in order to avoid negative interactions from those who abuse it.

Multiline telepathy is a desirable feature for the sake of proof
reading.

## Proof Of Testing

<img width="654" height="279" alt="image"
src="https://github.com/user-attachments/assets/056f4d52-5365-4b5f-a422-40791c5e568d"
/>


## Changelog

🆑
add: Added a new quirk Psionic Dampener, affecting telepathy from
quirks, genetics, slimes, xenomorphs, revenants and so on.
balance: Telepathy (Quirk) no longer automatically gives the gene.
qol: The telepathic communication power granted by the quirk or the
genetic power is only anonymous if the caster has the mutation, not the
target.
qol: Telepathy (Quirk) now shows when the user uses the power and on
whom, but not the contents of the message.
qol: Telepathy is now multiline.
/🆑
2026-05-14 03:07:32 +02:00
af8f69da13 Adds "Event Logging", or EVLogging, A new debug system that allows us to track individual datums and log events on a timeline (#96035)
## About The Pull Request

This Pull Request adds a new logging system that uses a timeline to
track and visualize important events for specific datums.

This is done via a new window in which you can select a datum for
tracking, which adds it to the timeline. If this datum implements the
EVLOGGING macros, it can track important events onto this timeline. As
an example, we can log whenever an AI is deciding to make a new path, if
it decides to generate a new decisionmaking plan, it finishes an action,
or it decides to target someone/something.

We can select these events to see more information, and optionally get a
snapshot of important variables at the time this event was logged (like
the blackboard and current plan for AI controllers).

You can also filter out specific events / track info, which is done via
categories. Each event / piece of track info is given a category and if
you disable a category all events / track info in that category is
hidden. This lets you filter out things you might not care about.

<img width="2346" height="1209" alt="image"
src="https://github.com/user-attachments/assets/0763077c-e349-4c7c-b017-23d29e1d089b"
/>

_whoever thinks we didnt need advanced cleanbot logging is a noob_


In the video below I showcase how this works;
https://file.house/7nsOiqdvmSTxlsk3fs-e8g==.mp4
A cleanbot is roaming the halls, I turn on the event logger, click the
"pick target" button and click on the datum I'd like to track (the
cleanbot). This results in the cleanbot now tracking its events. I spawn
some dirt and the cleanbot decides to clean it, and I go through the
events; You can see theres different events being listed, such as when
the cleanbot starts targetting the dirt, when it cleans plan, when it
makes it JPS path and every time it moves over it.


The macros I've currently implemented are as follows:

**EVLOG_TEXT(DATUM, CATEGORY, INFO)**
Only adds text to the event logger window, no world-visuals

EVLOG_LOCATION(DATUM, CATEGORY, INFO, TURF) 
Adds text to the event logger and adds an image to where that turf is.

EVLOG_TURFS(DATUM, CATEGORY, INFO, TURFS)
Adds text to the event logger and adds an image to each turf in the
TURFS list

EVLOG_LINES(DATUM, CATEGORY, INFO, TURF_A, TURF_B)
Adds text to the event logger and adds a line from turf_a to turf_B

EVLOG_PATH(DATUM, CATEGORY, INFO, TURFS)
Adds text to the event logger and visualizes a path from A to B (same
way as the pathfinding debugger, of which I moved the visualization
before to SSPathfinder)

In terms of performance, the logger is a singleton, and events are ONLY
logged if
1. The logger is running
2. The datum has the DF_EVLOGGING flag.

This means most of the time, logging an event is a single var lookup
(Since the runner is off by default). The DF_EVLOGGING flag is off by
default as well and has to be enabled by the event logger, or set
temporarily by a dev in code.

This system can easily be extended with more event types / visualization
types as well. (I'm thinking of datumizing the ones I have now)

The TGUI is still a bit of a mess, I would love some pointers because
I'm not really good at react so I just kind of hit it with a hammer
until it did what I wanted 😎

Also, all of this is based on VisLogging from Unreal Engine, so it will
have some likeness https://unreal-garden.com/tutorials/visual-logger/

## Why It's Good For The Game

This system allows us to debug more complex systems (like basic AI) in
an understandable and clear way. While the implementation cases are not
super common right now, extending this system could make debugging these
systems much more comprehensible, and hopefully lets more developers
help us with improving these systems. (plus, we LOVE timelines)

## Changelog

🆑 CabinetOnFire
refactor: Implements "Event Logging" an improved way for programmers to
debug specific datums.
/🆑

---------

Co-authored-by: Lucy <lucy@absolucy.moe>
2026-05-13 12:37:56 +00:00
ArturlangandGitHub d67ca75e37 kills cargo imports (#5491)
## About The Pull Request
kills cargo imports with no mercy, moves it into goodies with
newly-added subcategories
also adds a persi only agent ID single pack per request
also also tarkon and persi can buy private packs via id money
## Why It's Good For The Game
ugly UI that doesn't work for other factions and needs hacks to work
with cargo ui is not great

## Proof Of Testing


<summary>Screenshots/Videos</summary>
<img width="1268" height="1124" alt="image"
src="https://github.com/user-attachments/assets/fd3d9a58-ea0b-4242-88d2-b6123a214c72"
/>

## Changelog

🆑
add: cargo imports moved into it's own category with a brand subcategory
system, and orderable without a private account (god why did i do this)
add: persistence only agent ID single pack
add: persistence and tarkon can now buy stuff via ids directly
add: captain access can always unlock departmental orders
fix: persistence and persistence cargo consoles sending cargo pods to
the station if cargo bay is selected
del: entire cargo company imports system
/🆑
2026-05-12 17:20:32 -07:00
LemonInTheDarkandGitHub 2dfbf0b81a Adds a unit test that makes sure subsystem flags make sense (#96022)
## About The Pull Request

There's a few of these that conflict, mostly relating to timing. This
conflicting won't actually break anything but it does muddy "what is
this doing" somewhat and it's good to be clear so here we go

## Why It's Good For The Game

Makes the MC very slightly harder to confuse yourself with
2026-05-11 11:20:24 -04:00