Commit Graph

794 Commits

Author SHA1 Message Date
SmArtKar
44c968f75e Adds a unit test for techweb design presence, puts some missing designs into protolathes (#90219)
## About The Pull Request

Adds a unit test that checks that all designs are accessible through
some source, be it techweb, disks, or innate designs. Certain designs,
like pocket extinguishers, entertainment screens, etc, that have been
present in autolathes but not in the techweb despite having PROTOLATHE
flag assigned have been put into protolathes (where it made sense,
otherwise the flag was removed).
An important change is that restaurant portals are now printable, and
thus can be constructed and deconstructed. Indestructible portals have
been a major gripe of mine for a while, and I don't see a solid reason
for keeping them indestructible if they can easily be printed from the
service protolathe.

Closes #90212

## Why It's Good For The Game

Initial argument for keeping portals unbreakable was to prevent people
from griefing the chef/bartender, but by that logic we can make most
machinery unbreakable too. I don't think that having an unbreakable
portal is good if its locking us out from allowing chefs/bartenders to
reorder or even outright reposition their lunchroom/bar.

## Changelog

🆑
balance: Restaurant portals can now be printed, constructed and
deconstructed. They're also no longer completely invulnerable.
/🆑
2025-04-03 08:05:08 +02:00
RikuTheKiller
4ee5cb9dcc Allows setting tick_interval on status effects to 0, effectively passing process() straight to tick() (#90248)
## About The Pull Request

Adds STATUS_EFFECT_AUTO_TICK, a define with a value of 0 that just makes
process() call tick() every time.

## Why It's Good For The Game

An unambiguous way to make tick() consistent with process() is quite
nice.
Sometimes you just have a status effect that only needs to run every
0.2s or every 2s. (past cases downstream)
Other times you have a status effect that is reliant on being in sync
with process() (my case downstream that started this PR)
2025-04-01 12:29:57 -05:00
SmArtKar
6b83a91956 Revert "Refactor for storage initialization & organization (#89543)" (#90332)
## About The Pull Request

Reverts the storage initialization refactor and all subsequent related
PRs.
The original PR is below our standards both for code quality and
testing, and is majorly flawed at its core. This has been discussed with
other maintainers and headcoder(s?) over on discord. A lot of changes
from the PR could be brought over later, but in its current state it
should not have been merged.

- Closes #90322
- Closes #90313
- Closes #90315
- Closes #90320
- Closes #90312
- Closes #90344

## Why It's Good For The Game

This PR causes a series of major issues which cannot be resolved without
either completely rewriting a lot of the original PR, or bad code.
Not matching our standards is grounds for not merging a PR, and the fact
that a PR should not have been merged is a reason for a revert.

## Changelog
🆑
fix: Fixed a series of storage-related bugs caused by a refactor PR.
/🆑
2025-03-30 21:30:31 +00:00
SmArtKar
bdfe18fbad Blacklists certain RNG-dependant crates from testing (#90333)
## About The Pull Request

Blacklists dumpster, hide, random toys, contraband and random medical
equipment crates from the cargo_crate_sanity unit test. These crates are
innately random, and while we have to be aware of potentially having
their average be over their price, we cannot (sanely) test for that
(without spawning a thousand crates, and even then we're affected by
random). The whole point of these crates is gambling on their value.

Closes #90328 
Closes #90314
Closes #90298
Closes #90253
Closes #90216
Closes #90181
Closes #90178

## Changelog

Not player facing
2025-03-30 21:12:30 +02:00
MrMelbert
4a4f6db8f9 Fix storage whitelists / blacklists being ignored in some contexts (#90231)
## About The Pull Request

It did not return FALSE unless it was set to print messages.

Fixes #90226

## Changelog

🆑 Melbert
fix: Fix storage whitelists / blacklists being ignored in some contexts
(hotkeys)
/🆑
2025-03-25 21:24:39 -07:00
Ghom
523b0b37e8 Simplifies fish traits inheritability a little (#90014)
## About The Pull Request
I'm thinking of removing some of the redundant or unnecessary bad design
from fishing, especially aquariums, which are definitely a bit fringe
and difficult to attend to on top of other stuff. However I don't have
all time of the world so I'd rather start small, even if it isn't the
main obstacle (which is keeping fish alive and getting them to reproduce
in the first place).

Thinking about it, the fact that some traits have a chance not to be
passed down to the offspring even if both parents have them is plain bad
and it's led situations where I couldn' tell if it was a bug or a
feature. The solution? Forgo the probability check for traits shared by
both parents.

## Why It's Good For The Game
Clearly that was bad design. 

## Changelog

🆑
balance: Made fish traits inheritability easier. They're now guaranteed
to be passed down to offsprings if both parents have them.
/🆑
2025-03-22 11:39:39 +01:00
OrionTheFox
38dc2369ef Adds GAGS fedoras, updates all other fedora sprites to match the Detective's (+ other related tweaks) (#90132)
## About The Pull Request
First just to get it out of the way, yippee, greyscale fedoras.
Available in the Clothesmate. Now you can make a hat to match those
custom buttondowns+suitjackets we already have.

![image](https://github.com/user-attachments/assets/98f1c53b-058e-4244-ac04-45197da6ccba)

However, because so many of the fedoras pair with other sprites, I
couldn't just make all of them greyscale. Then they wouldn't quite
match!
So I've updated them all - most of the on-mobs are just slight tweaks to
shading so they (as mentioned) match the detective fedora.
The obj sprites were also changed - most are the newer sprite (again,
detective's) but I opted to keep the Reporter and Curator fedoras as
slightly updated old ones because those in particular feel cooler to
have the wide-brims and the angle.


![image](https://github.com/user-attachments/assets/904a0da8-a134-4629-b8ea-56ee07b6ed18)


**Additional changes you might notice in the screenshot:**
- Beige Suit had its contrast just _barely_ tweaked to match the fedora.
- Carpskin hat has like 3px changed because they were stray/inconsistent
- Curator's `treasure hunter jacket` had its color changed to pair with
the hat. As it was, the hat being the same color would have been near
identical to the detective's, and this actually matches up with the
intended reference better too. (Plus it inadvertently matches the boots)
- All the hats are down 1px to match the detective. With hair masks, it
looks a **lot** better over hair now...
<details><summary>However, for spritetainer's curiosity, this is the
comparison of how it'd look if they were all up 1px</summary>


![image](https://github.com/user-attachments/assets/36a99466-05ab-4474-ae40-19ec190a0b1b)

</details>

<details><summary>I also had to slightly alter the mask because it
originally cut off 1px too much.
No visual change on the only other hat that uses it (the sec helmet)
</summary>


![image](https://github.com/user-attachments/assets/13d95e08-87aa-4bce-9c8b-bb5420f0f3b1)

</details>
## Why It's Good For The Game

**Greyscale Fedoras**
We #love customization. Players can already make their own suits, why
not their own hats to match?

**All the resprites**
Having all of the fedoras looking similar is nice, especially with the
onmob sprites' shading and obj sprites' shapes. Helps players associate
the items with each other better. Plus, the curator's was _really_
soulful.

As for the curator's jacket, I feel having it not be as similar to the
detective's palette will make it stand out more as the unique item it
is. It's a treasure hunter. Give them the admiration they deserve.

**Height/Hairmask**
The height is consistency - one fedora being lower than the other is
confusing and almost looks like a bug.
The hairmask solves the issue that lowering them previously caused - no
more severe clipping with hair.
## Changelog
🆑
add: Added greyscale Fedoras, available in the Clothesmate!
image: Resprited most of the Fedoras - now they'll all be much more
consistent with the detective's updated and sleek ones. They also all
have a hairmask now, so hair will no longer clip with them!
image: To pair with this, the Beige suit has been just slightly tweaked
and the Curator's "Treasure Hunter Jacket" entirely recolored to better
match their fedoras.
/🆑
2025-03-22 03:24:19 -04:00
SmArtKar
64cf28cc4f Adds bodypart visuals for different implants, improves eye color/blinking handling (#90010)
## About The Pull Request

Added visual overlays for all arm implants, HUD implants (not the
headrev one), internal thrusters, breathing tube, nutriment pumps and
reviver implant.


![dreamseeker_wd79oYLszL](https://github.com/user-attachments/assets/76582c23-8639-4261-8414-622a0419dc5b)

![dreamseeker_MnlpCHD0nQ](https://github.com/user-attachments/assets/c4692105-0435-401b-aa30-66a33a813fc4)

![dreamseeker_nLJrSPGC63](https://github.com/user-attachments/assets/5b43a1a6-45d6-454e-9348-c119db3cfb43)

Additionally, added a wrapper for eye color setting which solves the
issue where non-pref sourced eyecolors got reset after changing them,
and changed how blinking works so now update_body calls don't force you
to blink.

## Why It's Good For The Game

Gives you incredible drip (which makes augments feel more impactful) and
allows others to see if you have certain important augments (reviver)
that could matter.
As for technical changes, both were required for this to HUDs to work
nicely and fix some bugs as a side effect.

## Changelog
🆑
add: Certain implants now have visuals when implanted
fix: You no longer blink when you adjust your clothing
fix: Fixed an issue where some NPC/midround humans would not get their
eye color set correctly
/🆑
2025-03-17 19:09:55 +01:00
SmArtKar
845ed7459e Bravo Six, Going Dark: Refactors client colors to fix dupe issues and support filters (#89843)
## About The Pull Request

Completely refactored how client colors are handled. Now they're similar
to traits, having a source associated with them. Instead of adding and
removing by strict type (which makes client colors prone to getting
duplicated and not cleaned up) you remove a filter associated with a
specific source. Adding another client color with the same source as an
already existing one will replace the existing one if its of a different
type, or do nothing if they're the same (unless force is set to TRUE).
Client colors can also force filter splitting, putting all colors that
come before them, themselves, and all colors after them into separate
filters - this is useful to prevent mixing in filters which are supposed
to remove a certain color.

<details>

<summary>Example of how Perceptomatrix and nightmare vision goggles
combined before this PR:</summary>


![dreamseeker_fBOse2i0jq](https://github.com/user-attachments/assets/fb164e1f-ce8b-4a8c-8820-5db25e710056)

And this is after, as you can see nightmare vision effect's red is only
slightly tinted by perceptomatix instead of being literally halved.


![dreamseeker_U6A24fetK8](https://github.com/user-attachments/assets/8d8b3eb5-9f53-4646-bc56-0f5897013c6f)

</details>

Additionally, added support for custom filters (and not just colors) to
client color code to allow us to work with more colorspaces.

Also fixed weird blindness behavior, so this also 
Closes #89787

## Why It's Good For The Game

Makes code less ass to work with, fixes weird color mixing, etc.

## Changelog
🆑
fix: Fixed perceptomatix helmet allowing you to see even when
unconscious
refactor: Refactored how client colors are handled, ensuring that
certain effects like nightmare goggles don't disappear when another
vision-affecting piece of clothing is worn.
/🆑
2025-03-17 11:35:11 +00:00
SSensum13
cb8b669b1b Pointblank shots in combat mode! (#89799)
## About The Pull Request

This PR will allow you to shoot guns pointblank in combat mode by
remaping melee only attack to RMB in combat mode. You still can hold
people on a gunpoint, just use non combat mode to do so.

## Why It's Good For The Game

I think it's much more convenient and intuitive to be able to shoot
pointblank in combat mode.

## Changelog

🆑
qol: Now you can shoot guns pointblank in combat mode! If you want to
attack melee only: use combat mode + right mouse button.
/🆑

---------

Co-authored-by: Sensum <121913313+SSensum@users.noreply.github.com>
2025-03-17 02:07:21 +01:00
SmArtKar
d23f0c6557 Fixes a reagent exposure test flaky (#90053)
## About The Pull Request

I'm highly confused as to A) why this was flaky B) how this even worked
before, converted this to use proper healing/health adjustment methods,
also incorrect feedback in inhalation tests

## Changelog

Not player facing
2025-03-16 17:41:02 +01:00
itsmeow
93a2b723da IconForge: rust-g GAGS (250x faster edition) (#89590)
## About The Pull Request

Offloads GAGS generation to rust-g IconForge.

**Key Notes**

- The builtin GAGS editor still uses the 'legacy' generation to allow
for debugging.
- Does not support `color_matrix` layer type, which is currently not
used by any GAGS configs. Will do nothing if used.
- Does not support `or` blending mode, which is currently not used by
any GAGS configs. Will error if used.
- Has some 'quirks' compared to BYOND when it comes to mixing icon
states with different dir/frame amounts. BYOND will just silently handle
these and it's basically undefined behavior because what should you
expect BYOND to do? IconForge will spit errors out instead. So this PR
also fixes a few of those cases.

Functions by writing output to `tmp/gags/gags-[...].dmi`, copying that
output into the RSC and assigning the file object to `icon`.

Saves ~1.7s init by reducing worst-case GAGS icon generation from 250ms
to 1ms.

Also optimizes `icon_exists` by using `rustg_dmi_icon_states` for file
icons, saving ~60ms. Would have more savings if not for json_decode as
well as DMI parsing in rust being somewhat slow. Perhaps having
`rustg_dmi_icon_states` share a cache with IconForge could reduce this
cost, however I'd still recommend limiting these tests to unit tests
(https://github.com/tgstation/dev-cycles-initiative/issues/34),
especially for GAGS configs. I'm not sure they're worth 700ms.

Saves another ~400ms by replacing `md5asfile` with `rustg_hash_file` in
`/datum/greyscale_config/proc/Refresh`

Savings are likely even higher when combined with #89478, due to
spritesheets sharing a parsed DMI cache with GAGS. This means GAGS will
spend less time parsing icons synchronously and can generate output
faster. Tracy tests with this combo seem to yield ~2sec savings instead
of ~1.7sec

Total savings: ~2.16sec to ~2.46sec

- Ports https://github.com/BeeStation/BeeStation-Hornet/pull/10455
- Resolves https://github.com/tgstation/dev-cycles-initiative/issues/9



## Why It's Good For The Game

GAGS go zoooom

<details>
<summary>GAGS Working Ingame</summary>


![image](https://github.com/user-attachments/assets/28df25a5-bdf0-4a63-a6cf-b15f85467b23)


![image](https://github.com/user-attachments/assets/6a9dab46-5814-47ea-ad9b-f5ec84a6333d)

</details>

<details>
<summary>GetColoredIconByType</summary>


![image](https://github.com/user-attachments/assets/1698729f-1101-4413-bfb3-0922b389c347)

</details>

<details>
<summary>icon_exists</summary>


![image](https://github.com/user-attachments/assets/9e72c6aa-287f-4ce3-8dbe-9d3bebf3a762)

</details>


<details>
<summary>Refresh</summary>


![image](https://github.com/user-attachments/assets/18c15073-a294-4db6-bdd0-cdc7d8682221)

</details>


## Changelog
🆑
tweak: Optimized GAGS using rust-g IconForge, reducing worst-case
generation time to 1ms
/🆑
2025-03-13 20:59:12 -04:00
ArcaneMusic
5624a33c26 Adds a unit test for Cargo Crates to prevent infinite credit oversights. (#89023)
## About The Pull Request

I was kinda shocked that we didn't have something for this considering
that it's an unspoken rule of cargo to check that a crate does not sell
back for more than it's price and that the one comment saying to do so
has been doing some heavy lifting for the last 12 years.

I'm a novice when it comes to unit testing specifically so hopefully the
smoothing out that needs to be done should be fairly quick.

*Edit (2/22/25):*
The following changes were also made in order to allow for this unit
test to work smoothly:

Exports now have a market define added to them, as the purpose of this
unit test is to test exports that occur on the station, bought from
supply and then sold back to supply. As such, these market defines
exclude exports specific to pirates (since the cargo shuttle cannot sell
living mobs back, preventing you from making 10k per parrot crate.).

I've also added the `abstract` variable to some export datums, to
signify that a given export is either variable, or not meant to be
compared against the value of it's own container, such as with gas
canister's base export value as their export datums are generated
dynamically. (The subtypes are not abstract, however.)

The verb, `/mob/living/verb/tally_physical_credits()` has been changed
to `/mob/living/proc/tally_physical_credits()`, because that's my B and
does effect some economy back end but it's a one line fix so I just
absent-mindedly fixed it here instead of atomizing it out. I can
one-line it otherwise.

Mulebots now no longer runtime on spawn as they set their own to their
own `get_turf` as opposed to pulling their `loc`.

A few supply packs have had their prices bumped up slightly to actually
pass the test itself:

* `/datum/supply_pack/misc/candles_bulk`
* `/datum/supply_pack/security/armor`
* `/datum/supply_pack/security/helmets`
* `/datum/supply_pack/security/baton`

## Why It's Good For The Game

Prevents future infinite credit bugs that could have been missed by
simply checking the sale value in game.

## Changelog

🆑
fix: To prevent infinite sales issues, security helmets, armors, and
batons packs now all cost 600 credits, up from 400.
fix: Candle packs now cost 400 credits, up from 300, and candles now
sell for 12.25 cr each.
/🆑

---------

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
2025-03-13 23:26:53 +01:00
Ghom
7c703fc712 Food types are now passed down when cooking from recipes. (#89706)
## About The Pull Request
~~I have some beef with the cooking system.~~

Cooking recipes are coded in a way that disregard the possibility for
their components to have different foodtype flags than the ones you
would find normally find.
For example, if I wanted to make corned beef, but instead of a standard
steak, I used a killer tomato "steak", the result would still have the
meat food type, even if none of the components has it.

I've had to resort to a few hacky lines of code to manipulate the food
types from the edible component, but that can be easily fixed if #89687
is merged.

## Why It's Good For The Game
This also makes cooking recipes less strict about their food types and
can help us spot inconsistencies with recipes.

## Changelog

🆑
qol: Food types are now passed down when cooking from recipes. For
example, a plate of corned "beef" made from giant killer tomato slabs no
longer counts as meat but only vegetables now.
fix: Fixed a metric ton of inconsistencies with food types and recipes.
fix: Dank-pockets (the weed variant) can now be microwaved.
/🆑
2025-03-13 20:06:35 +01:00
SmArtKar
eb2796831b [MDB Ignore] Refactors pills, patches, and generalizes stomach contents, nothing to see here. (#89549)
## About The Pull Request

Currently patches are a subtype of pills, and while they have the
``dissolveable`` var set to FALSE, barely anything checks it (because
people don't expect patches to be pills in disguise) so we end up
patches being dissolveable and implantable, which is far from ideal.
Both have been moved into an ``/obj/item/reagent_containers/applicator``
class, which handles their common logic and helps handling cases where
either one fits. As for gameplay changes:
* Pills no longer dissolve instantly, instead adding their contents to
your stomach after 3 seconds (by default). You can increase the timer by
dropping sugar onto them to thicken their coating, 1s per 1u applied, up
to a full minute. Coating can also be dissolved with water, similarly
-1s per 1u applied. Pills with no coating will work like before.
* Patches now only take half as long to apply (1.5s), but also slowly
trickle in their reagents instead of instantly applying all of them.
This is done via embedding so you could theoretically (if you get lucky)
stick a ranged patch at someone, although they are rather quick to rip
off. The implementation and idea itself are separate, but the idea for
having a visual display has been taken from
https://github.com/Monkestation/Monkestation2.0/pull/2558.

![dreamseeker_Ywd4jQcy3t](https://github.com/user-attachments/assets/7ce0e549-9ecd-4a8a-98ea-12e00754bdd9)
* In order to support the new pill mechanics, stomachs have received
contents. Pills and items that you accidentally swallow now go into your
stomach instead of your chest cavity, and may damage it if they're
sharp, requiring having them surgically cut out (cut the stomach open
with a scalpel, then cauterize it to mend the incision). Or maybe you
can get a bacchus's blessing, or a geneticist hulk to gut punch you,
that may also work. Alien devour ability also uses this system now. If
you get a critical slashing wound on your chest contents of your cut
apart stomach (if a surgeon forgot to mend it, or if you ate too much
glass shard for breakfast) may fall out. However, spacemen with the
strong stomach trait can eat as much glass cereal as they want.

Pill duration can also be chosen in ChemMaster when you have a pill
selected, 0 to 30 seconds.

![image](https://github.com/user-attachments/assets/1f40210e-74dd-49c2-8093-432a747ac8dd)

## Why It's Good For The Game

Patches and pills are extremely similar in their implemenation, former
being a worse version of sprays and pills, with only change being that
pills cannot be applied through helmets while patches and sprays ignore
both. This change makes them useful for separate cases, and allows
reenactment of some classic... movie, scenes, with the pill change. As
for stomach contents, this was probably the sanest way of implementing
pill handling, and everything else (item swallowing and cutting stomachs
open to remove a cyanide pill someone ate before it dissolves) kind of
snowballed from there. I pray to whatever gods that are out there that
this won't have some extremely absurd and cursed interactions (it
probably will).

## Changelog
🆑
add: Instead of dissolving instantly, pills now activate after 4
seconds. This timer can be increased by using a dropper filled with
sugar on them, 1s added per 1u dropped.
add: Patches now stick to you and slowly bleed their reagents, instead
of being strictly inferior to both pills and sprays.
add: Items that you accidentally swallow now go into your stomach
contents.
refactor: Patches are no longer considered pills by the game
refactor: All stomachs now have contents, instead of it being exclusive
to aliens. You can cut open a stomach to empty it with a scalpel, and
mend an existing incision with a cautery.
/🆑
2025-03-13 17:31:37 +01:00
Bloop
c9c39dcf5b Adds one more space ruin area type to excluded areas for mapload space verification (#89867)
## About The Pull Request

Tin. This looks like an oversight that this wasn't in here. This is the
area type used for hidden space ruins.

## Why It's Good For The Game

Less CI failures for overhanging lattices in space.
2025-03-08 13:40:19 -06:00
SmArtKar
8bc74ce874 Resprites all eyes and gives cybernetic eyes unique sprites (#89841) 2025-03-06 21:17:01 -05:00
Ghom
9154e28668 unblacklists botany fruits and vegetables from unit tests. (#89683)
## About The Pull Request
subtypes of `/obj/item/food/grown` have no reason to not be spawned by
the `create_and_destroy` unit test, which prevents us from knowing if a
type fruit or veggie doesn't have a set seed in the tests. The only path
that needs to be blacklisted is the common `/obj/item/food/grown` path
itself, since its seed variable needs to remain null so that we can be
warned about any subtype that hasn't overriden that value.
This PR also removes the `/obj/item/food/grown/shell` path which serves
no purpose anymore.

## Why It's Good For The Game
Backend improvements. Atomizing changes from my refactor.

## Changelog
N/A
2025-03-05 14:24:35 +01:00
itsmeow
cc335e7e9e IconForge: rust-g Spritesheet Generation (#89478)
## About The Pull Request

Replaces the asset subsystem's spritesheet generator with a rust-based
implementation (https://github.com/tgstation/rust-g/pull/160).

This is a rough port of
https://github.com/BeeStation/BeeStation-Hornet/pull/10404, but it
includes fixes for some cases I didn't catch that apply on TG.

(FWIW we've been using this system on prod for over a year and
encountered no major issues.)

### TG MAINTAINER NOTE


![image](https://github.com/user-attachments/assets/53bd2b44-9bb5-42d2-b33f-093651edebc0)

### Batched Spritesheets

`/datum/asset/spritesheet_batched`: A version of the spritesheet system
that collects a list of `/datum/universal_icon`s and sends them off to
rustg asynchronously, and the generation also runs on another thread, so
the game doesn't block during realize_spritesheet. The rust generation
is about 10x faster when it comes to actual icon generation, but the
biggest perk of the batched spritesheets is the caching system.

This PR notably does not convert a few things to the new spritesheet
generator.

- Species and antagonist icons in the preferences view because they use
getFlatIcon ~~which can't be converted to universal icons~~.
- Yes, this is still a *massive* cost to init, unfortunately. On Bee, I
actually enabled the 'legacy' cache on prod and development, which you
can see in my PR. That's why I added the 'clear cache' verb and the
`unregister()` procs, because it can force a regeneration at runtime. I
decided not to port this, since I think it would be detrimental to the
large amount of contributors here.
- It is *technically* possible to port parts of this to the uni_icon
system by making a uni_icon version of getFlatIcon. However, some
overlays use runtime-generated icons which are ~~completely unparseable
to IconForge, since they're stored in the RSC and don't exist as files
anywhere~~. This is most noticeable with things like hair (which blend
additively with the hair mask on the server, thus making them invisible
to `get_flat_uni_icon`). It also doesn't help that species and antag
icons will still need to generate a bunch of dummies and delete them to
even verify cache validity.
- It is actually possible to write the RSC icons to the filesystem
(using fcopy) and reference them in IconForge. However, I'm going to
wait on doing this until I port my GAGS implementation because it
requires GAGS to exist on the filesystem as well.

#### Caching

IconForge generates a cache based on the set of icons used, all
transform operations applied, and the source DMIs of each icon used
within the spritesheet. It can compare the hashes and invalidate the
cache automatically if any of these change. This means we can enable
caching on development, and have absolutely no downsides, because if
anything changes, the cache invalidates itself.

The caching has a mean cost of ~5ms and saves a lot of time compared to
generating the spritesheet, even with rust's faster generation. The main
downside is that the cache still requires building the list of icons and
their transforms, then json encoding it to send to rustg.

Here's an abbreviated example of a cache JSON. All of these need to
match for the cache to be valid. `input_hash` contains the transform
definitions for all the sprites in the spritesheet, so if the input to
iconforge changes, that hash catches it. The `sizes` and `sprites` are
loaded into DM.

```json
{
	"input_hash": "99f1bc67d590e000",
	"dmi_hashes": {
		"icons/ui/achievements/achievements.dmi": "771200c75da11c62"
	},
	"sizes": [
		"76x76"
	],
	"sprites": {
		"achievement-rustascend": {
			"size_id": "76x76",
			"position": 1
		}
	},
	"rustg_version": "3.6.0",
	"dm_version": 1
}
```

### Universal Icons

Universal icons are just a collection of DMI, Icon State, and any icon
transformation procs you apply (blends, crops, scales). They can be
convered to DM icons via `to_icon()`. I've included an implementation of
GAGS that produces universal icons, allowing GAGS items to be converted
into them. IconForge can read universal icons and add them to
spritesheets. It's basically just a wrapper that reimplements BYOND icon
procs.

### Other Stuff

Converts some uses of md5asfile within legacy spritesheets to use
rustg_hash_file instead, improving the performance of their generation.

Fixes lizard body markings not showing in previews, and re-adds eyes to
the ethereal color preview. This is a side effect of IconForge having
*much* better error handling than DM icon procs. Invalid stuff that gets
passed around will error instead of silently doing nothing.

Changes the CSS used in legacy spritesheet generation to split
`background: url(...) no-repeat` into separate props. This is necessary
for WebView2, as IE treats these properties differently - adding
`background-color` to an icon object (as seen in the R&D console) won't
work if you don't split these out.

Deletes unused spritesheets and their associated icons (condiments
spritesheet, old PDA spritesheet)

## Why It's Good For The Game

If you press "Character Setup", the 10-13sec of lag is now approximately
0.5-2 seconds.

Tracy profile showing the time spent on get_asset_datum. I pressed the
preferences button during init on both branches. Do note that this was
ran with a smart cache HIT, so no generation occurred.


![image](https://github.com/user-attachments/assets/3efa71ab-972b-4f5a-acab-0892496ef999)

Much lower worst-case for /datum/asset/New (which includes
`create_spritesheets()` and `register()`)


![image](https://github.com/user-attachments/assets/9ad8ceee-7bd6-4c48-b5f3-006520f527ef)

Here's a look at the internal costs from rustg - as you can see
`generate_spritesheet()` is very fast:


![image](https://github.com/user-attachments/assets/e6892c28-8c31-4af5-96d4-501e966d0ce9)

### Comparison for a single spritesheet - chat spritesheet:

**Before**


![image](https://github.com/user-attachments/assets/cbd65787-42ba-4278-a45c-bd3d538da986)

**After**


![image](https://github.com/user-attachments/assets/d750899a-bd07-4b57-80fb-420fcc0ae416)

## Changelog

🆑
fix: Fixed lizard body markings and ethereal feature previews in the
preference menu missing some overlays.
refactor: Optimized spritesheet asset generation greatly using rustg
IconForge, greatly reducing post-initialization lag as well as reducing
init times and saving server computation.
config: Added 'smart' asset caching, for batched rustg IconForge
spritesheets. It is persistent and suitable for use on local, with
automatic invalidation.
add: Added admin verbs - Debug -> Clear Smart/Legacy Asset Cache for
spritesheets.
fix: Fixed R&D console icons breaking on WebView2/516
/🆑
2025-03-03 14:58:27 +01:00
SmArtKar
f40bb684b1 Fixes an old simplemob damage bug (#89759)
## About The Pull Request

Literally every single bit of our code assumes that adjustXLoss returns
the total health delta (old_damage - new_damage), so negative values
when damage was taken and positive when it was healed, ***except***
simplemobs had this inverted for (supposedly) two years. Yeah. This
broke crushers, mending touch and slime feeding - not sure if anything
else was screwed due to this.

Closes #87550

## Why It's Good For The Game


![despair-suffer](https://github.com/user-attachments/assets/cc18bc20-2fd5-48fc-833e-046433185ec5)

## Changelog
🆑
fix: Fixed inconsistent crusher trophy droprates
/🆑
2025-03-03 20:26:52 +11:00
Ghom
da31ea158c The edible component now uses DUPE_SOURCE mode (#89687)
## About The Pull Request
The edible component now uses DUPE_SOURCE mode, which is needed to avoid
conflicts between sources. This includes some other tidbits from my
refactor like renaming dcs/flags.dm to ds/declarations.dm (in virtue of
the fact it doesn't only contain flags anymore even before this PR),
meat materials giving protein and fat reagents to affected atoms instead
of generic nutriment and oil, and the pizza material no longer
containing meat, because margherita pizza, which the material is
extracted from, doesn't contain meat either. The pepperonis were
magically conjured space bs.

## Why It's Good For The Game
There are multiple sources of the edible component and we don't want
issues with that. Also atomizing stuff from my refactor.

## Changelog

🆑
balance: objects made out of meat are no longer classified as gross food
on top of being raw and meaty, and actually contain protein and fat
instead of standard nutriment and oil.
balance: the pizza material stacks, crafted with margherita pizza and
rollig pin mind you, no longer magically contain pepperoni.
/🆑
2025-03-02 13:15:08 +01:00
SmArtKar
889c6dc9fd Implements a quirk spawn validity unit test and fixes a runtime preventing cyborg dogtag quirk from working roundstart (#89728)
## About The Pull Request

Fixes a roundstart-exclusive runtime in the cyborg dogtag quirk, makes
sure that spawning with a fishing toolbox (from a settler quirk) doesn't
runtime and implements a unit test which ensures that all quirks set up
correctly for ***both*** roundstart and latejoin mobs. The cyborg tag
issue is just too stupid and may float up again, considering how easy it
is to accidentally fetch owner's client instead of using the passed one.

## Changelog
🆑
fix: Cyborg pre-screening dogtags should once again be given to crew
with the quirk of the same name.
/🆑
2025-02-28 19:00:47 +01:00
Ghom
d3a56bf429 [NO GBP] Fixes lobstrosities being able to fish other lobstrosities yet again. (#89580) 2025-02-22 11:45:12 +01:00
EnterTheJake
7809f0f501 Introduces 6 New Heretic sideknowledges, 1 new spell to Blade Path. + changes to the Research Tree. (#89169)
## About The Pull Request

Introduces 6 new Heretic Sideknowledges.

**Warren King's Welcome:** Starting side-knowledge, Grants to the
Heretic's id Maints and External Airlock access.

**Phylactery Of Damnation:** T1 Knowledge, located between Imperfect
Ritual and Keykeeper's Burden, creates a bottle that can Siphon a small
quantity of blood from your victim, (they'll still feel a tiny prick).


![potion_red](https://github.com/user-attachments/assets/b000300a-2f2c-47f1-9fd3-b9d8e0f4f587)

**Ether Of The Newborn:** T2 knowledge, replaces Curse Of Paralysis slot
in the tree (Inbetween Mark of Madness and Moonlight Amulette).


![potion_green](https://github.com/user-attachments/assets/bc45c69f-4a16-4879-b788-661112e35638)

1 use potion, fully restores the inbiber to full health, removes any
sort of affliction,trauma,disease or implant at the cost of knocking the
user out for 1 minute.

**Codex Morbus:** T3 knowledge, located between Caretaker's Refuge and
Ringleader's RIse.


![codex
gif](https://github.com/user-attachments/assets/8a15dc78-30b9-4a21-93eb-bafbeebd59a4)


![Codex Morbius
Final](https://github.com/user-attachments/assets/04c8739c-5c65-4246-9408-3cbdbc57a164)


Upgrade of the Codex Cicatrix, draws and siphons runes and essences a
bit faster, can be used on a rune to curse a crewmember, provided their
blood is on the rune or on the Heretic.

**Greaves Of The Prophet:** T3 knowledge, located between Entropic Plume
and Wolves Among Sheep.



![Greaves](https://github.com/user-attachments/assets/287b592e-b771-40ed-99b3-25820550d6a0)

They work as magical magboots minus the slowdown; they confer full
immunity to slips (yes, even space lube).

**Rust Sower Grenade:** T2 knowledge, replaces curse of corrosion in the
tree (between Aggressive Spread and Star Blast).



![Rustsower](https://github.com/user-attachments/assets/297f045c-38c3-4ed0-9046-52d797610339)

Eldritch grenade, Releases a smoke that rusts all affected turfs, blinds
whoever doesn't have mask protection and utterly annihilates silicons,
mechs, augs and bots.

Video Showcase: https://www.youtube.com/watch?v=H1GeO7MYFek

**New Blade Path Spell: Wolves Among Sheep**

Video Showcase: https://www.youtube.com/watch?v=2LsmUiQzpzA

- Briefly transforms the surrounding the heretic into an arena.

- Both The Heretic and Crew members caught inside the spell cannot leave
or change z level until the spell expires.

- The arena is impassable to outsiders.

- Everyone caught inside the spell receives a special buff that makes
them immune to most enviromental hazards and all forms of Crowd Control
while blocking teleportation.

- Non Heretics are granted a temporary Heretic Blade and an antag datum.

- Scoring a critical hit grants the winner the ability to leave the
arena, Critting the heretic fully dissolves the spell.

- Critting yourself doesn't remove the debuff.

- The Heretic receives a heal upon critting someone.

- Breaking a blade while inside the arena will rip off your arm
regardless if you are crew or a Heretic.

- 2 minutes cooldown.

- Replaces Furious Steel as the last spell unlocked pre-ascension.


Lastly as you may have guessed, curses have been completely refactored,
they are now bound to the new item (Codex Morbus), are no longer
empowered by blood but require it as a reagent.

Curse of Corrosion and Paralysis have been rebalanced to be slightly
stronger than they were at their base value now that they can no longer
be empowered.

2 new curses have be introduced.

**Curse Of Indulgence:** tanks the target hunger, makes them a carnivore
and drastically increases their hunger decay rate, lasts 8 minutes.

**Curse Of Transmogrification:** Allows the Heretic to change the
target's Race(minus plasmamen for obvious reasons), lasts until the
Codex Morbus is destroyed.

Lastly the Blade Heretic tree has been shuffled a bit to introduce the
new spell.

Stance Of the Torn Champion has been **TEMPORARILY** Removed, it will
come back in a later PR.

Code by me and Xander

Sprites by INFRARED_BARON and OrcaCora.

Lore tibids by NecromancerAnne.

## Why It's Good For The Game

The following is an atomisation of The Heretic Knowledge Rework I'm
currently working on alongside Edge (Heretic's Grandaddy).

Given the whole PR was probably going to be impossibly big to review; I
asked Melbert If could introduce the new knowledges first, so here we
are.

Do not stress the locations of these knowledges in the tree; While they
do fill what few empty slots we still have, it doesn't change the fact
that the Heretic tree is an incomprehensible mess and will soon be
reworked.

**Warren King's Welcome:**

Not having mantainence access as an antag sucks.

Arguably it sucks even more for Heretics as they are required to find
some place discrete in order to be able to cast their rituals.

It's not unusual for the station to be so crowded, that setting up a
base in space is the only option, the external access helps with that a
little bit.

**Phylactery Of Damnation and Codex Morbus**

Explaining them in the same paragraph as they are intended to be used
together.

Curses might as well not exist in their current state.

The process of cursing a crewmember is way too machineous, annoying, and
nowhere near as affective as simply running to your victim and smacking
it with your blade.

All Curses have now been bundled to the new Codex, they no longer
require X reagents, only a drip of the victim's blood.

That's when the phylactery comes into play.

Victims still feel "a tiny prick" upon being juiced, so beware.

**Ether Of The Newborn:** The point of this knowledge is to serve as a
backup plan to "random bullshittery".


It's not really fun rolling one bad trauma or disease and have it
completely invalidate your Heretic round.

We already have potions that either heal or provide remedies against
wounds/limb loss, the Ether is supposed to be an extreme solution, hence
why it causes a 1 minute sleep upon consumption.

**Greaves Of The Prophet:** Heretic to this day is fairly lacking when
it comes to passive immunities or tools we grant to most of our core
antagonists.

Specifically, for a melee-focused antagonist, a total lack of antislip
is kinda lame, being one of the most common defense tools employed by
the crew against newbie antagonist players.

Given these cannot be concealed unlike the traitor counterpart and how
far down the tree they are, i felt like making them lube resistant was a
unique twist and sensible for what's essentialy our core progression
antagonist.

**Rust Sower Grenade:** directly inspired by the 40k Blight Grenades.

The Rust Sower nades serve a double purpose.

1) They introduce a new form of area Denial available to all heretic
paths.

2) They confer to non Rust Heretics a way to deal with the so hated
Silicon Menace.

I'm of the not-so-unpopular school of thought of "Mechs and Silicons
have had it too good for too long".

A massive chunk of our threat roster gets to this day completely shut
down by mechs.

I feel like it was about time to make everything Inorganic feel afraid
again.

To make it a bit more fair, these grenades have a fairly long detonation
timer and have been given a couple of unique SFX.


**Wolves Among Sheep**

Even after the last batch of Changes, Blade Heretic still felt a bit
uninspired to me.

The path is still essentialy just about running at people and stabbing
them in the face.

While that's part of the appreal, I'd reckon it's still lacking a bit on
the eldritch side of things.

Trapping opponents into an arena when they are forced to either engage
you or betray their friends to escape can create some potentially
interesting story-telling.

It also warps the ,oh, so beloathed stun meta we live in by forcing
participants to resort to lethal weaponry.

Ultimately, this is supposed to be a high risk/high reward spell, if you
trap 5 people arm them with heretic blades, and make them all fully stun
immune, you are likely gonna get lynched.

To free up a slot in the tree I **TEMPORARILY** Removed Stance of the
Torn champion, it will come back in my nextish pr, so don't worry about
it too much.

## Changelog

🆑
add: New Heretic starting Side-Knowdge Warren King's Welcome
add: New Heretic T1 Side knowledge, Phylactery Of Damnation.
add: New Heretic T2 Side knowledge, Ether Of The Newborn.
add: New Heretic T3 Side knowledge, Codex Morbus.
add: New Heretic T2 Side knowledge, Rust Sower grenade.
add: New Heretic T3 Side knowledge, Greaves Of The Prophet.
add: New Blade Path Spell, Wolves Among Sheep.
balance: Heretic curses have been removed from the tree and bundled in
the new Knowledge, Codex Morbus.
balance: Blade Path tree has been shuffled a bit, all spells have been
moved up by one tier to make space for the new spell.
removal: Stance Of The Torn Champion has been removed.
/🆑

---------

Co-authored-by: Xander3359 <66163761+Xander3359@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: carlarctg <53100513+carlarctg@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
2025-02-17 11:15:20 +01:00
Ghom
e6c03fec85 Fixing issues with non-human mobs that can fish (#89434)
## About The Pull Request
This PR fixes an issue that has been reported about the profound fisher
trait, because even then, a projectile is fired that may hit things
other than the intended target, making it impossible for the mob to
continue fishing if the abstract fishing rod hooks on something else. To
fix this we just need to skip the projectile stuff and go straight to
the `hook_hit` call ~~also allowing someone to fish on oneself (eg.
through the fishing spot generated by the organ manip surgery)~~.

Also dealt with a few other issues like a "interrupted!" balloon alert
being sent after the minigame is already completed, fritterish icons,
layering of the float, a bad signal and a redundant check meant to stop
explosions from spawning fishing loot from chasms (because someone
forgot to add the relative flag).

## Why It's Good For The Game
This should fix #88974 and other stuff as well

## Changelog

🆑
fix: Trying to fish on an adjacent spot won't end up hitting other
things on the same turf (provided you actually click the fishing spot
and not other things).
fix: Fixing the icon state for the "fritterish" fish variants.
/🆑
2025-02-16 17:44:44 +11:00
Jacquerel
23ac16411d Removes Secondary & Final Objectives from Traitors (#89466)
## About The Pull Request


![image](https://github.com/user-attachments/assets/cb0bffb3-33be-4fb1-baec-a4d0f4a4cd57)
Pre-discussed with @Watermelon914, this PR removes Secondary & Final
Objectives from all Traitors, rather than just midround ones. It also
removes all of the surrounding supporting code.
Randomly assigned Primary Objectives still exist, I just used the
ability to rewrite mine to take the screenshot.

In terms of final objectives, the surrounding items that were available
still exist but don't necessarily have sources.
If anyone has good ideas for readding these in some other form it can be
done in future PRs.

It also allows all traitors to buy the Contractor kit, previously
limited to midround traitors which lacked secondary objectives, because
now all traitors lack secondary objectives.

This essentially limits all traitors to a maximum of 20 TC (16 if they
spawn with an uplink implant). Currently I don't foresee that they
strictly need any additional way of gaining TC during a round as 20 is
quite sufficient, but it may take some time to adjust and get used to it
after such a long time of having access to more. If we need to adjust
the starting value or add a slow drip of more points over time or
something, that can be done in followup PRs.

This also removes the ability to recreate your uplink added by my
beautiful wife in #74315
This was part of the progression traitor design document, but ultimately
probably a bad idea as it essentially made traitors impossible to
properly disarm. You will once more just need to carefully protect your
uplink.

**This does not remove the threat/progression system**. 
Like midround traitors, all Reputation requirements on gear are now
simple timelocks, most of which will have elapsed by the time 30 minutes
have passed.

**Finally** this PR also adds Romerol to the traitor uplink for 25 TC
and 30 minutes of reputation, as a treat (and because I removed the
final objective that previously granted it).

## Why It's Good For The Game

We've tried this system for a long time (3 years last month!) and while
I think it had a lot of promise, enabled some cool moments, and also
solved several of the problems it set out to solve, overall I think some
of the behaviours it has encouraged in players have been overall
negative for the game.
While the _game systems_ are fine, even quite fun and cool (especially
final objectives) I am of the opinion that having them in the game
creates a net negative purely in the way that they react with players'
_brains_, creating incentives towards behaviour we don't actually want
people to pursue.

While it's hard-to-impossible to prove any of this with hard data, there
has been a prevailing feeling for some time among many (though certainly
not all) people that the simple fact of _having_ a constant drip-feed of
objective available to players leads directly to less interesting
antagonist play. While certainly nobody is _forced_ to do secondary
objectives you are directly and quite strongly rewarded for doing so,
doing so efficiently, and doing so in a way which makes sure that nobody
(alive) sees you do it. This leads to a tendency to play defensively and
try to maximise the number of tasks you can complete in one round, which
also has a knock-on effect of generally minimising the number of people
you attempt to interact with in a round (unless you are killing them).

Even people who _intend_ on doing some more interesting gimmick can fall
into this trap, as "having more tools" is always useful for anyone who
is intending on any kind of plan at all, but then executing on the
secondary objectives again incentivises you to lay low, not interact
with anyone, be efficient, and then reduces the time you are spending
doing the thing that's your actual plan for the round. Removing the
ever-present temptation to fish for extra TC leaves "doing whatever your
actual plan is" as the sole thing to optimise.

Final Objectives too have created unfortunate psychological effects
between crewsided players and other antagonists. Because of the _threat_
(no matter how remote, Final Objectives have always been tuned to be
appropriately rare) that leaving any antagonist alone will cause them to
snowball by acquiring more power, it starts to feel foolish to respond
to any threat with less than the maximum possible level of force even if
they seem relatively innocuous in the moment. This even has an effect on
other non-progression antagonists, as traitors are the most common
antagonist type and how people treat them is going to be their default
level of reaction to most other station threats.

While there has always been the promise of expanding the system with
novel and exciting objectives that leverage appearing mid-round to do
something unique, we've taken very little advantage of that over time.
Most objectives we have added that didn't boil down to "kill someone,
with a twist" have been somewhat unsuccessful, serving either as ways to
get yourself arrested and killed for no reason or ways to get free
telecrystals by doing something the crew don't really care about
stopping you from doing. The option still exists to add more roundstart
objectives to traitors, if someone suddenly has a great idea that would
fit in this space.

The ideal outcome of making this change is a slight relaxation of crew
attitude towards feeling like their only option after catching an
antagonist that isn't sandbagging is to permanently remove them from the
round (although it's fine to do this still in many scenarios), and a
broadening of traitorous activity which is not purely focused on
collecting as many checkboxes as possible and might give people more
time to roleplay with other players, not worrying that this time could
have been more efficiently spent pursuing a different secondary goal.
I don't anticipate or desire that this will prevent traitors from
killing anyone (or even stop them from killing people they don't have a
specific objective to kill), I just want to remove the FOMO from
people's minds.

Also this gives us something to talk about at the coder townhall meeting
on the 22nd.

## Changelog

🆑
del: Misplaced or stolen traitor uplinks can no longer be recreated
using a radio code and special device, guard yours carefully or buy a
backup implant.
del: Roundstart traitors can no longer take on additional objectives in
order to earn additional Telecrystals and fast-forward any unlock timers
on items. They also cannot earn the ability to complete a Final
Objective.
balance: Roundstart traitors can now buy the Contractor Kit from their
traitor uplink, rather than only midround traitors.
add: Traitors can buy Romerol for 25 TC, after 30 minutes of time has
passed in a round.
/🆑
2025-02-14 12:46:56 +00:00
MichiRecRoom
344d3b6266 Optimizes /proc/icon_exists() (#89357)
## About The Pull Request
This PR reimplements https://github.com/tgstation/tgstation/pull/71538
atop `master`. Quoting the original PR:

> Every `icon_exists()` call will cache the entire file. Past me didn't
realise _why_ file opts were so expensive, but I do now. This is
immeasurably slower on a single call, and _significantly_ faster on
subsequent calls to the same file.

I attempted to handle some of the review comments that were posted
there, by splitting screaming functionality into its own proc.

* `if(icon_state in icon_states(file))` and `if(!(icon_state in
icon_states(file)))` were refactored to use `icon_exists(file,
icon_state)`.
* Where screaming was seemingly wanted (and where there wasn't a more
descriptive error inside the `if` block), I refactored them to use
`icon_exists_or_scream(file, icon_state)`
* The exception to the above was under
`/datum/unit_test/turf_icons/Run()` and
`/datum/unit_test/worn_icons/Run()`, where `icon_states()` was being
passed a mode flag. Given that this is only used in unit tests (where
performance isn't a priority), I opted to leave these be.

Additionally, I revised the documentation comment for
`/proc/icon_exists()`, as I felt it was a bit vague currently.

## Why It's Good For The Game
https://youtu.be/Z9G1Mf6TZRs

## Changelog
No player-facing changes (hopefully).

---------

Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
2025-02-05 20:00:27 +01:00
Jacquerel
940e2d31cf tgstation is back online and you are a horrible goose (#89204)
## About The Pull Request

Converts geese to basic mobs.
Nobody else did this one because two separate other developers have said
they started and then examining what the goose does made them feel
mildly ill, but I am stronger.

I will admit though I wasn't 100% committed to making it work exactly
the same way, I rewrote the entire system to use interfaces I like more
(read: I put all this shit in a status effect which means any mob can be
given the ability to vomit out everything in its contents) and if that
means the behaviour is only "inspired by" that didn't bother me that
much.

**Geese:**
- Wander randomly around.
- Peck people who attack them.
- Occasionally start pecking other nearby animals for absolutely no
reason.
- Eat any food they randomly wander within one tile of, but don't seek
it out further than that.
- Eat anything made of plastic that they randomly wander within one tile
of.
- Choke to death over 30 seconds if they eat anything made of plastic.
- Vomit out whatever it was that they choked on when they die.
- Honk (this is new).

The more famous subtype of goose is Birdboat. Birdboat is a unique goose
present on several maps with some additional behaviour.

**Birdboat:**
- Is chill and doesn't start pecking people for no reason.
- Is occasionally possessed by ghosts.
- Builds up an internal vomit-meter as he eats things. Moving around and
just sort of generally hanging will start rolling dice to find out when
Birdboat's tummy gets upset.
- May start vomiting instead of choking to death on plastic, thereby
saving his own life.
- Vomits out everything that he just ate while running around, making a
mess of the floor.
- Starts eating everything he just vomited out again.

Unlike regular geese who just eat your food and it's gone, Birdboat's
miraculous digestion preserves all of the food he eats so if he consumes
the entire kitchen counter it will eventually come back out again the
way it went in. Although you might not want to eat it any more.

The precise way in which this manifests may be slightly different, but
largely this is also what these animals did before.

Other stuff:

I noticed a bunch of find/set behaviours were not setting a search
range? I think that means they were never finding anything?
I did not actually test any of them to see if they were broken, but it's
possible that a bunch of broken AI behaviours like "climbing trees" may
now actually start triggering because they have a search radius greater
than an orange of 0.

I added "keep this in contents instead of deleting it" as a parameter
for generic eating and slapped it on the goldgrub, as it is used in two
places and may end up being used in more.

## Why It's Good For The Game

This kills off the last user of the `retaliate` subtype and makes our
list so so much closer to finish.
It's like... a couple of bots, a handful of oddballs (I'll probably
handle these soon), and then just the mining bosses and minibosses to
go.

If you give a human the vomit goose ability (now that I made it work on
any mob) they will eject all their organs and body parts via the mouth
until they die, if you don't do the brain or heart first you can vomit
your own head off.

## Changelog

🆑
refactor: Geese have been moved to the basic mob subsystem, please
report any unusual behaviour.
/🆑

---------

Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
2025-01-27 14:54:34 +02:00
Lucy
cc80029518 Process certain status effects using a new "priority effects" subsystem (#89076) 2025-01-26 14:34:38 +01:00
Jacquerel
2aeeed086f Basic Dark Wizards (#89147)
## About The Pull Request

Simple animal Dark Wizard => Basic mob Dark Wizard.
This mob is I think used in literally one ruin, and very occasionally
spawned in deathmatch.
They don't really do anything except shoot you with slowing projectiles
and hit you with sticks.

I gave them a version of blink with a longer cooldown that they use when
attacked in melee range purely to make them very marginally more
wizard-like, and they will also now try to back away from you while
shooting you instead of running towards you.

They will also retaliate against anyone who attacks them including as a
response to friendly fire from other Dark Wizards, because I think it is
funny if they have very little loyalty to each other and that's a fun
thing to trigger when you are playing Doom.

Finally, we have a component called "revenge ability" which is mostly a
standin for AI responses to getting attacked. I made all existing uses
of it turn off if you're controlled by a sapient player who can hit
those buttons themselves, because they can choose when they want to use
those abilities themselves.

## Why It's Good For The Game

The march of progress is almost complete

## Changelog

🆑
refactor: refactored some code
balance: Dark Wizards now teleport when attacked, but are more likely to
turn on their allies
/🆑
2025-01-22 20:50:07 -07:00
Jacquerel
6dee384568 Basic Mob Vatbeast (#89158)
## About The Pull Request

Another pretty easy conversion; this mob doesn't really do anything
except melee people and become rideable after you feed it cheese fries.
Changes in behaviour are that it will now seek out cheese fries by
itself if they happen to be lying around, and if it stays mad at you for
10 seconds it will use its powerful tentacle slap ability to hurl you
across the room, probably breaking a bone. Really just don't approach
this thing if you don't have cheese fries.

This mob basically only exists from cytology so I would be surprised if
it has existed in more than one round in the past four months.

## Why It's Good For The Game

I'm working down the remaining simple animals and a lot of them turn out
to still be quick fixes.

## Changelog

🆑
refactor: The Cytology Vatbeast now uses the basic mob framework, please
report any unusual behaviour.
/🆑
2025-01-22 20:44:35 -07:00
Jacquerel
89538067db Remove totally unused blob curse (#89154)
## About The Pull Request

We have a mob called `simple_animal/hostile/curseblob` which was used
only for the `necropolis_curse` status effect.
From the git history, this seems to have been added in a PR merged eight
years ago where the PR author came up with a cool set of curses to apply
to cursed objects and PRed it to the game as a concept to be used later.
Subsequently, nobody used it.

Well, to be more accurate, _two_ things apply the necropolis curse
debuff right now but they only collectively use three of the four
possibilities.
The fourth, which spawns a mob with weird behaviour, is unused and so
rather than spend my time bringing it up to standard I just removed it.
Because this is dead code.

To be quite honest I am not totally certain that `necropolis_curse`
should be a single status effect either and it would plausibly be better
off being two different status effects for the two different sources it
is currently invoked (helbital overdose, and being sacrificed by a
heretic).

**Fun Fact!** 
Being sacrificed by a heretic doses you with 1 minute worth of
_Helgrasp_ which spawns a frightening hand to attack you once per
second, and also applies the Necropolis Curse which spawns a frightening
hand to attack you once per ten seconds. This means that if you have
anything in your mob which affects metabolic rate your sacrificial
experience may be somewhat different, as quite a lot of the danger
actually just comes from a chemical in your body.

One of these effects spawns the hands slightly further away than the
other, and you actually spend _2.5 minutes_ in the spooky hand room, so
in that second (longer) half you'll only be tormented by very occasional
spectral groping. Personally I would not do it this way I think.

However rather than removing and replacing it, which would probably have
some kind of aftereffect on the heretic sacrifice minigame that I would
rather make larger changes to, I just touched up some of the code to
avoid single-letter vars and to use a helper proc we already use in
other heretic-related places.

## Why It's Good For The Game

This wasn't maintained, isn't used, and was on our to-do mob conversion
list.

## Changelog

Not player facing
2025-01-21 18:38:47 -07:00
Jacquerel
c5396ab66c Basic Mob Zombies (#89153)
## About The Pull Request

Simple to Basic ruin zombies.
Zombies are about as simple as you can get so I am surprised they
weren't converted already.
I didn't make any particular changes, except canonising a commonly-used
map varedit into a subtype and made them groan occasionally.

It's a little weird that the default zombie wears a doctor's outfit but
no point changing it until/unless it actually causes a problem.

## Why It's Good For The Game

2025 year of no more simple animals.

## Changelog

🆑
refactor: NPC zombies found in ruins now use the basic mob framework.
Please make an issue report if they exhibit any unusual behaviour.
/🆑
2025-01-21 18:36:13 -07:00
Penelope Haze
8196190aa1 Removes a a at at be be of of and and have have (#89155)
## About The Pull Request
I just had to one-up https://github.com/tgstation/tgstation/pull/89127.

## Why It's Good For The Game
Removes a a at at be be of of and and have have

## Changelog
N/A
2025-01-22 08:09:57 +11:00
Jacquerel
c3f3e9e9b9 Fix flaky Ethereal test (#89123) 2025-01-21 20:06:30 +01:00
jimmyl
4b512f1239 makes mimics into basicmobs (#88910)
## About The Pull Request

mimics are basicmobs now
the only change not carried over worth mentioning is that all mimics are
a consistent speed because i cant imagine a gun or object with aimbot
going at you mach 2 would be very fun

mimic crates had some stuff changed compared to their simple animal
variant
they open and close their lid when attacking (unless locked) to be like
menacing or something like animals flash colors to ward off people
attempting to open a nonsentient hostile crate mimic will make it lock
itself (if it contains anything) and attack you

mimics are a really stupid naming for these because like
mimic crates pretend to be crates
anything else inheriting from mimics are just used to make objects alive



https://github.com/user-attachments/assets/34a733a4-45a3-409e-8a6a-b2a8c7540898



ranged mimics now use viscontents (they also keep trying to pointblank
people for some reason i think thats ok though unless its a wand of
fireball)
ranged mimic (any ranged weapon animated by a bolt of animation)


https://github.com/user-attachments/assets/c3f1d2f5-cfb8-46a9-a58c-255c53a034db



## Why It's Good For The Game
fixes #85668

## Changelog
🆑
refactor: mimics (bolt of animation, malf ai Machine Override, etc) are
basicmobs
fix: crate mimics may now be opened
/🆑

---------

Co-authored-by: Jacquerel <hnevard@gmail.com>
2025-01-19 21:29:49 +00:00
Andrew
e3933ba938 This year's medkit resprite (#89085) 2025-01-18 02:06:36 -05:00
tonty
e755854af2 Nearsighted severity sources (with unit test) + status_effect/grouped minor rework (#88591)
# About The Pull Request
## Nearsighted Sources
Nearsighted now associates/tracks severity applied by each source.
Previously, nearsighted only used a single variable which had to be
shared by every source, which caused problems for things like scarred
eyes which needed independent behaviour.

This implementation allows sources with different severity levels to
coexist without needing workarounds

There are now two different severity types for nearsightedness:
* Correctable: Can be mitigated with vision correction (like glasses)
* Absolute: Cannot be mitigated from any source, used for scarred eyes

Which can allow nearsighted sources to not be affected by vision
correction.
Also, since there is no more technical conflict between the two quirks,
I've made it so that nearsighted and scarred eye can be selected
together (as a QOL change)

There is also a new unit test for this new behaviour
(nearsighted_effect) that checks application and removal
## status_effect/grouped minor rework
Grouped status effects now have `source_added()` and `source_removed()`
procs, which are called whenever a source is added or removed from the
effect

I did this because the previous implementation was somewhat unwieldy. 
Inherited status effects would recieve the _currently existing_ effect
through merge_with_existing, and require them to modify the existing
effect's properties, which is odd and not intuitive to work with (the
proc's `src` was not the existing effect)
It not being called for every source also made users repeat code in
`on_creation()` and `merge_with_existing()` for every source added.

This new interface should prevent repetition and be generally more
intuitive to work with.

# Changelog

🆑
refactor: Nearsighted has been reworked to track severity applied from
each source, as well as allow "non-correctable" nearsightedness (for
things like scarred eyes).
qol: The above being possible now means that you can select the
Nearsighted and Scarred eye quirks together
fix: Any bug that would occur from becoming nearsighted with a scarred
eye should be fixed now
code: status_effect/grouped merging code has been improved (i hope)
/🆑
2025-01-15 14:29:38 +01:00
Jacquerel
28e4c83d54 Deprioritise phobias in two sources of random trauma (#88958) 2025-01-11 22:35:27 +01:00
SmArtKar
3499727a6d Implements datumized embedding handlers in place of element-component-datum triad (#88511)
## About The Pull Request

This PR completely rewrites our embedding system in favor of embedding
datum handlers which acts as containers for all embedding-related data
and logic.

Currently embedding logic relies on an element-component-datum triad,
where elements on the items handle embedding logic, singleton datums
store embedding data and components (which get assigned to ***mobs*** in
whom the item embedded) handle pain and the item being ripped out. How
do we access all the procs? By using comsigs as procs, which is really
bad. This code was written back in 2020 when DCS was hot stuff but in
hindsight this implementation was a mistake, as it heavily restricts
custom embedding behaviors unless you're willing to constantly run
GetComponent (bad, ugly, incarnation of evil)

This PR rewrites all that logic to be handled by lazyloaded
``/datum/embedding``, which is stored similarly to current
``/datum/embed_data``. Upon being requested, it is initialized and
assigned to a parent from whom all the logic is handled, from being
embedded to pain and having the item ripped out. On projectiles this
only handles one proc, after which it copies itself down to the shrapnel
item instead and runs the chain further from there.
Ideally, most embedding-related logic now should be handled purely
datum-side - in most cases items should not be hooking up to themselves
like they did before (unless said logic is for when the item is made
sticky or smth) and instead the code should be handled by the embedding
datum (see sholean grapes implementation in this PR). This should allow
us to do fancy stuff like syringe guns embedding syringes into targets
and injecting them that way, and fix some bugs along the way.

Closes #88115
Closes #87946

Also fixed a bug with scars not displaying when examined closely from
#86506 because i was in the area anyways
2025-01-02 23:18:27 +00:00
MrMelbert
4b77c6f7c0 Decouples "Is this affected by a mop" from layer var (#88465)
## About The Pull Request

Rather than checking for object layer if we can clean something, has a
trait which accomplishes this

This better allows us to pick and choose what objects we want to clean
when mopping

Note: I didn't apply the trait to everything it previously affected
Currently, it cleans stuff like pipes and plumbing, which I deemed not
necessary to carry over since they can't get dirty anyways
I can re-add this if desired though

Fixes #88445
Fixes #88150

## Changelog

🆑 Melbert
fix: Gibs get bulk cleaned if you clean the turf again
refactor: Changed how things determine "I can be bulk cleaned if I clean
the turf underneath me", let me know if you notice anything not getting
bulk cleaned or weird things getting bulk cleaned
/🆑
2024-12-18 00:50:08 +01:00
SyncIt21
d1b842356e More maintenance for turbine (#88254)
## About The Pull Request
**1. Fixes**
 - Fixes #88231. This is a 2 part fix as in
- For the UI side we first convert energy to power in the back end via
`energy_to_power()` proc & then use `formatPower()` proc in the client
side UI to display the correct SI units instead of always using KW
- The turbine now uses `SSMachines` subsytem for processing instead of
`SSAir`. This is because energy which is
[power x delta time] requires `seconds_per_tick` which isn't supplied by
`process_atmos()` so for correct conversion we have to switch over to
the machine subsystem
 
![Screenshot
(452)](https://github.com/user-attachments/assets/94fc207b-37d4-4f10-a984-b5d15e0644c6)


**2. Refactor**
- Merged procs like `power_on()` & `power_off()` both into
`toggle_power()` proc
  - Converted `attackby()` attack chain into `item_interaction()`
- `ui_data()` now won't update the UI if it encounters invalid data &
sends very little data if it's not connected to the turbine to reduce
bandwidth
  - Removes redundant vars, autodoc procs & much more

## Changelog
🆑
fix: Turbine converts energy to power correctly & shows correct reading
with multitool
refactor: turbine code has been overall improved. report bugs on github
/🆑
2024-12-15 04:27:37 +01:00
Ghom
6c11961d4f Improving the fish unit tests a little (#88397) 2024-12-10 18:55:34 +01:00
Ghom
ee96509686 fixing runtime errors when removing a brain with skillchips. (#88178)
## About The Pull Request
The organs code changes bundled with the organ fishing PR have broken a
few things, while unveiling a bunch of other problems that flew under
the radar. This concern the first category actually. Anyway, I've also
included a unit test to ensure this won't be an inssue in the future.

## Why It's Good For The Game
Fixing some errors.
2024-12-03 18:10:46 -06:00
MrMelbert
3c40876f15 Fix itchy skillchip status effect "Curse of Mundanity", adds unit test for effects set to "Curse of Mundanity" (and missing IDs) (#88240)
## About The Pull Request

Fixes a lot of status effects having the default alert, adds a unit test
to check that status effects don't forget to change it

I chose a test rather than just making the default "no alert" because I
think people making status effects should think about whether it should
have an alert

Also I added a test for effects which did not set an ID because that's
kind of important, I applied the same mindset here to account for
abstract types but admittedly less sold on this one.

## Changelog

🆑 Melbert
fix: You should be afflicted by the "Curse of Mundanity" far, far less
/🆑
2024-11-29 15:41:37 +01:00
Ghom
1dff5f6de3 Aquariums are now potential fishing spots. (#88243)
## About The Pull Request
You can now fish from aquariums if you wish to. This includes some
backend changes to make it possible for the fish table from
get_fish_table() to contain instances, and all that it entails up to
spawn_reward(), which is a requirement for the gimmick to respect the
various traits and other variables of the already instantiated fish
rather than read from cached properties.

## Why It's Good For The Game
The fish progress score/index had only little nasty flaw that has been
nagging me since day one: Not all fish species can be caught. Skipping
McGill, which is a peculiar case that for cheevo purposes should be
considered a standard goldfish, there is the one, unsignificant yet rare
purple sludgefish which can only be gotten as a rare evolution of the
generic sludgefish. Talk about petty, but this may be a long-term nit I
prefer to handle right now.

Also why not? The 'unmarine mastodon' is near impossible to get unless
you somehow find a oil well which is locked behind a specific ruin.

## Changelog

🆑
fix: Aquariums are now potential fishing spots.
/🆑
2024-11-29 03:33:18 +00:00
Runi-c
8b9da265ba Digitigrade code refactor and shoes + explorer suit (Using GAGS and zero sprite bloat) (#88096)
## About The Pull Request
Refactors and extends the existing [digitigrade clothing
system](https://github.com/tgstation/tgstation/pull/85406) to also
support oversuits and shoes (only enabled for sneakers, specific boots,
and shaft miner's explorer suit). All digitigrade-specific clothes are
generated by GAGS by color sampling the base sprite and applying it to a
greyscale template.


![image](https://github.com/user-attachments/assets/c4ce5996-9373-4d76-a0e5-a6b094dd10b4)

More up to date boots:

![image](https://github.com/user-attachments/assets/8ead8056-25a3-42dd-9fde-e838e2a810b9)


![image](https://github.com/user-attachments/assets/783a1201-8a77-45a0-af85-8a63b41b63a8)


Credit to MrMelbert for prototype code and Junkgle for new sprites

## Why It's Good For The Game
Looks good, doesn't introduce maintainability issues or sprite bloat

## Changelog
🆑
add: digitigrade lizards can wear certain shoes and suits
image: added digitigrade shoes & oversuit templates
refactor: improved digi clothing generator code
/🆑

---------

Co-authored-by: MrMelbert <kmelbert4@gmail.com>
Co-authored-by: Roryl-c <5150427+Roryl-c@users.noreply.github.com>
2024-11-28 16:17:18 +01:00
MrMelbert
34d35c6048 Adds a bunch of interaction related unit tests (#88210)
## About The Pull Request

I made these a year ago and meant to PR them but never got around to it

Basically just adds a bunch of unit tests for a bunch of specific attack
chain interactions that are prone to breaking due to snowflake

Increasing coverage of attack chain is good so people who are working on
it don't have to worry about the 1000 edge cases breaking

- Blocking (both unarmed and armed)
- Cuffs
- Eyestab
- Flashes (combat mode, non combat mode, with flash protection)
- Help intent
- Pistol whip
- Butchering with a bayonet 
- Damp rag smothering
- Droppers
- EMP flashlights
- Holofans
- Door attack hand redirector
- Tool usage on Cyborgs
- Punching Cyborgs
- Ability to bash tables
- Ability to bash any structure
- Ability to use tools on machinery
- Kinetic Crusher projectile
- Spraycans (capping, making graffiti) 
- Loading a syringe gun
2024-11-27 11:38:43 -07:00
SmArtKar
fc61d427bf Converts pills and patches into interact_with_atom (#88157)
## About The Pull Request

Title. Code maintenance, code sanity and because overriding attack()
like this is bad

## Changelog
🆑
code: Converted pills and patches into interact_with_atom
/🆑
2024-11-25 23:21:26 +01:00
carlarctg
6d384051ed carpenter hammer fits on belt slot (#88109)
## About The Pull Request

bro its a hammer

(speaking of, i feel like it should fit on the toolbelt & be a crowbar.
but that's basically 1:1 the preexisting claw hammer, idk)

## Why It's Good For The Game

bro it's a hammer.

## Changelog

🆑
qol: carpenter hammer fits on belt slot
code: renames belt_icon_state to inside_belt_icon_state for
intelligibiility
/🆑
2024-11-25 00:03:06 +01:00