Compare commits

...
Author SHA1 Message Date
Janet Blackquill fc2d05f548 ser/de 2026-06-20 06:10:53 -05:00
Janet Blackquill 4c7f99296c and that's a wrap 2026-06-20 06:10:53 -05:00
pre-commit-ci[bot] df1e97986a [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-06-20 06:10:53 -05:00
Janet Blackquill 88203bb6b2 and that's a wrap 2026-06-20 06:10:53 -05:00
Janet Blackquill 158a114804 nuke me harder 2026-06-20 06:10:53 -05:00
Janet Blackquill d438aec056 she rise up until i don't have a round end condition yet 2026-06-20 06:10:53 -05:00
Delta-V bot 3134e91fa5 Automatic changelog update 2026-06-20 12:46:22 +02:00
3ac30b7b7b [new item] Hitman card (#5896)
* Created Hitman_Case_catalog.yml

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

credit:stormyatt. thanks for the help those on discord and the host briefcase

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

credit: stormyatt with help from the discord sever and the hos briefcase pr

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* 16/24 items filled

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* more added

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* top three filled

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman, full disguise kit

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* 27/30

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* 28/30

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* found the doorjack!

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* spyCrewMonitor is cool

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* found you!

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* hitman: icons

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* Created Hitman_Case.yml

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* Create Hitman_Briefcase.rsi

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* Delete Resources/Textures/_DV/Objects/Tools/Hitman_Briefcase.rsi

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* almost made hitman card

* many modifactions to make it work.

* i need to get around to fixing my repo after this

* hope this works. reverting by hand

Signed-off-by: storm! <253825839+stormyatt@users.noreply.github.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* as requested

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* less dependies, pretty sure only needed ones now

* review 2. card space addition

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>
Signed-off-by: storm! <253825839+stormyatt@users.noreply.github.com>
Co-authored-by: stormyatt <stormyatt@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-20 12:46:02 +02:00
Delta-V bot 4daea082bc Automatic changelog update 2026-06-20 00:07:10 +02:00
Vanessa 6a37e1268e SRN Fixes (#6045)
* Fixed SRNs getting borg AA on their borgs

* SRNs can print batteries
2026-06-19 18:06:50 -04:00
Delta-V bot 331a25c7d3 Automatic changelog update 2026-06-19 23:54:07 +02:00
Vanessaandpre-commit-ci[bot] b5121e10e9 Increase Syndicate Hardsuit Aura by 15% (#6060)
* Various syndicate hardsuit sprite upgrades for overlay.

* Added (missing) overlays for Feroxi and Reptiles.

* added base bluekie light

* Added stealthsuit variant.

* Fixed duplicate yaml entry

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix missing entry in meta.json for syndie medic

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-19 17:53:47 -04:00
Delta-V bot 9584a7b0ae Automatic changelog update 2026-06-19 23:43:04 +02:00
Vanessaandpre-commit-ci[bot] f9880c148b Cloned zombie players no longer get mauled by cats (#6053)
* Moved DeltaV modifications of ZombieSystem to a partial class. Fixed factions and pacifist trait on zombie cloning. Added survival objective to cloned II.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-19 17:42:45 -04:00
Delta-V bot 25ef15f162 Automatic changelog update 2026-06-19 21:26:41 +02:00
Theo 997a6e31e6 Felinid SinkClaws action (#5996)
action and sprites
2026-06-19 14:26:22 -05:00
Delta-V bot 5a342570a4 Automatic changelog update 2026-06-19 20:35:52 +02:00
Proxy also works :3 97bb68b2a6 kill cult metashield (#6026) 2026-06-19 13:35:33 -05:00
Delta-V bot ac9f8852b3 Automatic changelog update 2026-06-19 20:12:19 +02:00
DisposableCrewmember42andneomoth 8c8f4b4f2c tweak: better screenshake (#6059)
* tweak: explosion shake directional, distance fall-off

partial port of ss14Starlight/space-station-14#3707 by neomoth:
0b6282eb267ef1efc0b2bcd78a39e53a776f1c79

Co-authored-by: neomoth <69372252+neomoth@users.noreply.github.com>

* tweak: melee shake depends on damage/wielding

partial port of ss14Starlight/space-station-14#3707 by neomoth:
0b6282eb267ef1efc0b2bcd78a39e53a776f1c79

Co-authored-by: neomoth <69372252+neomoth@users.noreply.github.com>

* tweak: explosion kick falloff

* chore: remove debug log

* feat: melee shake has heavy/light variants instead of only showing for high blunt/wielded

* refactor: use MathF instead of Math

* tweak: more noticeable camera kick falloff

* tweak: generally dampen explosion kick a little more, fall off slower

* docs: explain camera kick falloff

* docs: remove commented upstream code per review

* docs: document screenshake falloff too, clarify distance

---------

Co-authored-by: neomoth <69372252+neomoth@users.noreply.github.com>
2026-06-19 13:11:59 -05:00
Delta-V bot 8eeb5f6523 Automatic changelog update 2026-06-19 20:00:05 +02:00
Theo 45432aa3bb Kobolds exist again (#5968)
copy paste ops
2026-06-19 17:59:45 +00:00
Delta-V bot b9153f0f13 Automatic changelog update 2026-06-19 19:53:03 +02:00
Theo e3d3fe72f0 remove damage examine from bomb pen (#6010)
remove hit damage
2026-06-19 17:52:43 +00:00
Delta-V bot 0a65236363 Automatic changelog update 2026-06-19 19:49:19 +02:00
Halo3moth afe6021455 remove chameleon gears metashield (#6000)
Update 2_Metagaming.xml
2026-06-19 13:48:59 -04:00
Delta-V bot e5db02c736 Automatic changelog update 2026-06-19 18:16:18 +02:00
Theo cbc5f819c4 Security radio recolor (#6016)
* change

* less saturated
2026-06-19 11:15:58 -05:00
Delta-V bot 339b3fb32c Automatic changelog update 2026-06-19 18:06:08 +02:00
AstraandVanessa e96faec07d Allow purified salts in belts/medkits (#6062)
* Allow purified salts in medical belts

* Medkits too why not

* Update Resources/Prototypes/Entities/Objects/Specific/Medical/medkits.yml

Signed-off-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>

---------

Signed-off-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
Co-authored-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
2026-06-19 16:05:48 +00:00
Delta-V bot a1bbf142a4 Automatic changelog update 2026-06-19 17:52:56 +02:00
DisposableCrewmember42andPieter-Jan Briers e47a0bf455 feat: chat follow links for ghosts (upstream port) (#6063)
* Ghosts have follow buttons in chat (#44284)

* Fix ghost follow buttons for station entity (#44289)

---------

Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2026-06-19 10:52:36 -05:00
Delta-V bot 72f3edd378 Automatic changelog update 2026-06-19 17:49:17 +02:00
freezer dog 030deb6f27 SV-213 QoL stuff (and a tiny bit more) (#6065)
wwoof
2026-06-19 10:48:57 -05:00
Vanessaandpathetic meowmeow 4397017c5a Added ESEffectSparks to excluded list on integration tests (#6061)
* Added ESEffectSparks to excluded list on integration tests

* Update Content.IntegrationTests/Tests/EntityTest.cs

Co-authored-by: pathetic meowmeow <uhhadd@gmail.com>
Signed-off-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>

---------

Signed-off-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
Co-authored-by: pathetic meowmeow <uhhadd@gmail.com>
2026-06-18 20:32:39 -04:00
Delta-V bot 0f19340d41 Automatic changelog update 2026-06-18 18:37:52 +02:00
Stxcking 3c28ee8d20 Tweak: Broken Station Maps can be Deconstructed (#6005)
mhm
2026-06-18 11:37:32 -05:00
Delta-V bot 11cc04dd87 Automatic changelog update 2026-06-18 18:35:12 +02:00
Sugarcane f87ed28744 Bluesec in Guidebook (#6013) 2026-06-18 11:34:52 -05:00
Delta-V bot 62c76332f5 Automatic changelog update 2026-06-18 18:22:35 +02:00
pathetic meowmeow 34c212e4fb Fax machines? That are ready roundstart? Perish the thought. (#6058) 2026-06-18 11:22:15 -05:00
Radezolid 353290e55b Mostly locker entityTables cleanup (#5982)
* Remove our changes to dressers.yml

* Engineering

* Heads

* Science

* Security

* Append our tables with upstream's, apply suggestion and small comment cleanup
2026-06-17 15:55:26 -04:00
Delta-V bot 0cbe9c01fb Automatic changelog update 2026-06-17 17:32:53 +02:00
Vanessa d88938887b Fixed biomasser dividing by zero (#6042)
Fixed biomasser dividing by 0.
2026-06-17 17:32:34 +02:00
Delta-V bot 1656a91c5e Automatic changelog update 2026-06-17 16:08:07 +02:00
Proxy also works :3 c70cbcb9f5 bne (#6050) 2026-06-17 09:07:47 -05:00
Delta-V bot 3e22d89d1e Automatic changelog update 2026-06-17 15:56:46 +02:00
TNE a790954f06 Prevent zombies/non-humanoids/non-borgs from using jetpacks (#5776)
Prevent zombies from using jetpacks

Introduces CanComplexInteract check from ActionBlockerSystem alongside a translation string
When Zombifying: Removes AutomaticJetpackUserComponent, calls SharedJetpackSystem.SetEnable(..., false, ...)
2026-06-17 15:56:26 +02:00
Delta-V bot 0676186fe5 Automatic changelog update 2026-06-17 15:36:21 +02:00
Theo db6d1e3970 Uplink pt 1 touchup (#5991)
* buffs

* damage change on knuckledusters
2026-06-17 08:36:01 -05:00
fd20b74b8f Update mapping spawners (#5857)
* Update mapping spawners

* more casing

* Clothing and towels

* minor fixes

* Finalize clothing

* Begin Items

* Final updates

* Fixes

* save button

* `n`

* Add pitbull to animal spawner

* Add random satchels

* Glowsticks

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/animals.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/boardgames.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/boardgames.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/books.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/machineparts.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/schoolgirl.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/seeds.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/towels.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Mobs/NPCs/misc.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Mobs/NPCs/misc.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Update Resources/Prototypes/_DV/Entities/Markers/Spawners/Random/mobs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>

* Review changes

---------

Signed-off-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>
Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
2026-06-16 23:54:22 -03:00
Delta-V bot d016838687 Automatic changelog update 2026-06-17 03:07:15 +02:00
Vanessa 160aa17052 Pitbull Fixes (#6046)
pitbull fixes
2026-06-16 22:06:55 -03:00
Delta-V bot 2b6729fa64 Automatic changelog update 2026-06-16 22:02:38 +02:00
Field Commandandpre-commit-ci[bot] 3439340530 Updated to ghost bar syndicate prison (#6006)
* Updated to ghost bar syndicate prison

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Some last minute fixes

* Update to prison and sprites

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-16 15:02:18 -05:00
Delta-V bot 28c2223a8a Automatic changelog update 2026-06-16 19:43:30 +02:00
CarolandVanessa 1b47c246c9 Added dynamic cost to Ratkings OnRaiseArmy ability (#6017)
* added dynamic cost to Ratkings OnRaiseArmy ability

* Update Content.Server/RatKing/RatKingSystem.cs

Co-authored-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
Signed-off-by: Carol <292806487+CarolCuchara@users.noreply.github.com>

* switched summary to one line

* added using directive for Linq

---------

Signed-off-by: Carol <292806487+CarolCuchara@users.noreply.github.com>
Co-authored-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
2026-06-16 12:43:10 -05:00
Delta-V bot 8141512cc4 Automatic changelog update 2026-06-16 19:09:52 +02:00
DisposableCrewmember42 fd986fec6e feat: Effigy-driven Colossus (mid-round Colossus rework) (#5565)
* feat: effigy-driven colossus

* feat: impl final stage, tweaks, randomization, fixes

* fix: actually broadcast first effigy audio

* style: add some newlines

* feat: notify player about updated target location in chat

* tweak: effigy always grows

* feat: make alwaysGrow show on anom scanner

* tweak: raise minimumPlayers to 35

* refactor: move FTL additions to _DV

* refactor: break out buffs into comps, add event

also added missing docs and made effigies heal colossi fully, as
specified in the PR body. I accidentally left it at 50% damage taken.

* docs: add effigy comp docs
2026-06-16 13:09:32 -04:00
Delta-V bot dd2a6e1c28 Automatic changelog update 2026-06-16 16:16:28 +02:00
TNEandDisposableCrewmember42 6c7c9de253 fix: don't show SSD examine on dead people/ghost role (#6012)
fix: don't display examine text on dead people or untaken ghost roles

Co-authored-by: DisposableCrewmember42 <disposablecrewmember42@proton.me>
2026-06-16 09:16:08 -05:00
Delta-V bot 2b96bb79f8 Automatic changelog update 2026-06-15 19:27:20 +02:00
CarolandVanessa c1239ef7bf Remove headset from pockets when player get zombified (#6030)
* Remove radio form pocket when secdogs get zombified

* Update Content.Server/Zombies/ZombieSystem.Transform.cs

Co-authored-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
Signed-off-by: Carol <292806487+CarolCuchara@users.noreply.github.com>

---------

Signed-off-by: Carol <292806487+CarolCuchara@users.noreply.github.com>
Co-authored-by: Vanessa <908648+ShepardToTheStars@users.noreply.github.com>
2026-06-15 12:27:00 -05:00
Delta-V bot 62b6401e48 Automatic changelog update 2026-06-15 18:46:55 +02:00
freezer dog f79a599c65 fixing machine pistol magazine issues and clearing gun chambers (#5819)
* kill... slaughter...

* ok why not im gonna clear chambers too

* ok maybe thats all the chambers clear

* time to find out i screwed up everythin xd

* whoops i killed the chambers....

---------

Signed-off-by: freezer dog <iamabanana372456@gmail.com>
2026-06-15 13:46:35 -03:00
Delta-V bot 9acd3f2ecb Automatic changelog update 2026-06-15 18:06:32 +02:00
Delta-V bot 47215d7876 Automatic changelog update 2026-06-15 18:02:26 +02:00
fe53298d27 Delta-V: Wrath of the Pitbulls (#5915)
* DIRECTION KNOWS BEST

DIRECTION KNOWS BEST GLORY TO DELTA-V

* MORE

More names

* It begins

Im not sorry

* Pitbull changes

They fear me because of what I can do.

* They will fuck you up if you Hit them

* Update pitbull.yml

* The infamous pitbull faction

* Update ai_factions.yml

* Update ai_factions.yml

Staff Requested changes

* Update pitbull.yml

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* sprites added!

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* event addition part 1

* Pitbull Crate

* Event work part 2

* obvious

* bullshit fix part 1

* Bullshit fix part 2

* bullshit fixes part 3

* i hate it here

* removes bullshit 5137268

* shortened timer to catch crew off guard

* crash fix 1 i think

* Update cargo_livestock.yml

* They no longer maul II

* they are angry.

* they cant maul you now.

* Update pitbull.ftl

* Update pitbull.yml

* Update events.yml

* Update interaction-popup-component.ftl

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update events.yml

* Update pests.yml

* Update pitbull.yml

* Update events.yml

* Update pitbull.yml

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update pitbull.yml

* 1984 pitbull faction

* Inshallah this will work

* More names

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update pitbull_names.yml

* Update pitbull.ftl

* Update pitbull_names.yml

* Increased amount of mice and hopefully enables higher chance of ventbulls to spawn

* DIRECTION KNOWS BEST

DIRECTION KNOWS BEST
DIRECTION KNOWS BEST
DIRECTION KNOWS BEST
DIRECTION KNOWS BEST
DIRECTION KNOWS BEST

Signed-off-by: Solaris <63768197+StarboundSolaris@users.noreply.github.com>

* DIRECTION KNOWS BEST

DIRECTION KNOWS BEST

Signed-off-by: Solaris <63768197+StarboundSolaris@users.noreply.github.com>

* Refactor inheritence for pitbulls

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* forgot a file

* Makes it so the crate spawns the named versions

* Ensures they have random names.

* Update pitbull.yml

* Prep for mapped pitbull

* Adds Pibble

* Returns id to previous version

* Update pitbull.yml

* Update events.yml

---------

Signed-off-by: Solaris <63768197+StarboundSolaris@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Solaris <63768197+Solaris7518@users.noreply.github.com>
Co-authored-by: Vanessa <vanessalouwagie@gmail.com>
2026-06-15 11:02:06 -05:00
Theo 1aee2519df Kill Poncho Meta (#6001)
numbers
2026-06-15 10:51:38 -05:00
Delta-V bot e8cd052c31 Automatic changelog update 2026-06-15 17:10:19 +02:00
Carol a27fa291e7 Fix: Beer googles not stopping glasses from spilling when throw (#6031)
* fixed beer googles not keeping glasses form spilling on throw

* fixed beer googles not keeping glasses form spilling on throw
2026-06-15 10:09:59 -05:00
Delta-V bot 7e6f66a651 Automatic changelog update 2026-06-15 17:05:49 +02:00
pathetic meowmeow 08c27979a1 Interaction particles pass (#6033) 2026-06-15 10:05:29 -05:00
Delta-V bot b49a94100c Automatic changelog update 2026-06-14 20:30:54 +02:00
Carol cfa24eb20c Added a range check for pager linking (#6032) 2026-06-14 14:30:34 -04:00
Delta-V bot 1787683435 Automatic changelog update 2026-06-14 10:13:44 +02:00
Stop-Signs 389fbf99e1 Reduce WT550 SMG fire-rate (#5581)
* the PR

* comments

* hunt showdown queue times

* comment

* .desc
2026-06-14 08:13:24 +00:00
Delta-V bot 74c7bf0a05 Automatic changelog update 2026-06-14 06:13:17 +02:00
Carol 6764276a47 Changed secborgs fibers to blue (#6025)
changed secborgs fibers to blue
2026-06-14 04:12:57 +00:00
github-actions[bot]andDeltaV-Bot 03934d3fbd Update Credits (#6028)
Co-authored-by: DeltaV-Bot <github@deltav.gay>
2026-06-14 04:59:28 +02:00
SumTwo 468150c817 Adding the Logistics Beret as a loadout option for Cargo Technicians (#6015)
* Step One: Add Hat

Signed-off-by: SumTwo <its.a.joke1000@gmail.com>

* Step Two: Add Hat

Signed-off-by: SumTwo <its.a.joke1000@gmail.com>

* Step Three: Im Stupid

Signed-off-by: SumTwo <its.a.joke1000@gmail.com>

* Step Four: Im Stupid

Signed-off-by: SumTwo <its.a.joke1000@gmail.com>

* Step Five: Obey CR

Signed-off-by: SumTwo <its.a.joke1000@gmail.com>

---------

Signed-off-by: SumTwo <its.a.joke1000@gmail.com>
2026-06-13 21:07:20 -03:00
Delta-V bot 310ac0809b Automatic changelog update 2026-06-13 22:03:35 +02:00
7b71611dc9 [antag variant]Hitman midround variant (#5848)
* Created Hitman_Case_catalog.yml

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

credit:stormyatt. thanks for the help those on discord and the host briefcase

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

credit: stormyatt with help from the discord sever and the hos briefcase pr

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* 16/24 items filled

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* more added

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* top three filled

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman, full disguise kit

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* 27/30

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* 28/30

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* found the doorjack!

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* spyCrewMonitor is cool

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* found you!

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* for hitman

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* hitman: icons

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* Created Hitman_Case.yml

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* Create Hitman_Briefcase.rsi

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* Delete Resources/Textures/_DV/Objects/Tools/Hitman_Briefcase.rsi

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fixing it all

* I dont get it either but last of the changes which our just righting things

* Hitman_Case_catalog.yml be like that

* goodbye dupe

* renaming a file and removing a duplicate

* attributions changed to repect the caps

* as requested, name changes and useless line removal

* forgot to control S here

* names changed to try and be both simple and actualy describe the goal

* doing review changes and a small change to prototype order to make sense

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* how did i get where i moved this wrong?

* recharging radio jammer to radio jammer.

* added hitman midround stuff

* made the professional not cause errors and have a ghost warp point

* enter at the ends of these files

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* updated the professional to professional

* decal adds

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fixes and stuff

* gave hitmans headset traffic and freelance comms

* all review changes made

* Apply suggestion from @Radezolid

caps my foe

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: storm! <253825839+stormyatt@users.noreply.github.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* nevermind i distrust this

* Update Resources/Prototypes/_DV/Catalog/Fills/Lockers/hitman_locker.yml

Signed-off-by: Radezolid <snappednexus@gmail.com>

---------

Signed-off-by: stormyatt <dratticuscrabs@gmail.com>
Signed-off-by: storm! <253825839+stormyatt@users.noreply.github.com>
Signed-off-by: Radezolid <snappednexus@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: stormyatt <stormyatt@users.noreply.github.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
2026-06-13 20:03:15 +00:00
Delta-V bot f2153d66c3 Automatic changelog update 2026-06-13 21:29:23 +02:00
Theo b6833cbbcf Remove Fractured Form (#6011)
* remove from the table

* full remove
2026-06-13 14:29:04 -05:00
Delta-V bot 4e2bd0c244 Automatic changelog update 2026-06-13 04:29:23 +02:00
bf0abd7ffa Add SRT Hardsuit and Antelope + Remove DS mentions (#6003)
* Added Chameleon Armor

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* nerfvest

* Lowered Price

* Changed Jackdaw and Atrides fire rates

* Changed battery on Pulse Rifle, upped fire rate

* lowered pulse rifle recharge rate

* Added SRT Hardsuit

* Added Antelope

* Revert "lowered pulse rifle recharge rate"

This reverts commit 73f348c3e7.

* Revert "Changed battery on Pulse Rifle, upped fire rate"

This reverts commit d6f408620d.

* Revert "Changed Jackdaw and Atrides fire rates"

This reverts commit 0779c08d44.

* Revert "Lowered Price"

This reverts commit d798cd92e9.

* Revert "Merge branch 'toastdrip' of https://github.com/einknusprigestoast/Delta-v into toastdrip"

This reverts commit ca038e3699, reversing
changes made to f74f3e506d.

* Revert "nerfvest"

This reverts commit f74f3e506d.

* Revert "Added Chameleon Armor"

This reverts commit b57fa738f3.

* Removed Edge from Mateba

* whoops, forgot comment

* Removed DS mention + Added NV to ERT + Added Thermal Vision to DS

* removed deathsquad mentions on the jumpsuit

* removed deathsquafd mentions on the backpack

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Unfucked my parenting

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* non-localisation maintainer requests

* Added FTLs

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* One point, one singular point

* AHHHH

* Fix comments

Signed-off-by: Radezolid <snappednexus@gmail.com>

---------

Signed-off-by: Radezolid <snappednexus@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
2026-06-12 23:29:03 -03:00
Delta-V bot c4d65da8ed Automatic changelog update 2026-06-12 19:16:19 +02:00
Stxcking 6dac24f03a Shoukou / Shoko Map Update - BlueSec (#5940)
* first

sobs

* second

* review fixes
2026-06-12 12:15:59 -05:00
Delta-V bot 9550a7d53d Automatic changelog update 2026-06-11 03:28:51 +02:00
VelcroboyandVelcroboy d826a15ff2 Map Edits: Arena (#6009)
* Map Edits: Arena

* Link lightswitch

* Remove duplicate suit storage

* reveiw edits

---------

Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
2026-06-10 20:28:31 -05:00
Delta-V bot 23a9a75703 Automatic changelog update 2026-06-10 20:23:59 +02:00
Vape 79a0000547 Xeno Rework - Pull sprites and audio from RMC (#5891)
* Additions

* Changes per direction

* Update xeno.yml

* Requested Changes
2026-06-10 18:21:13 +00:00
Delta-V bot 71badde1a0 Automatic changelog update 2026-06-09 20:48:54 +02:00
Theo 5ab49cd46b Reduce meat spike build time (#5999) 2026-06-09 14:48:35 -04:00
Delta-V bot 0398c527a1 Automatic changelog update 2026-06-09 20:10:21 +02:00
Cepelinas1 cdafd4c257 More Tips + slight tweaks to weapon names (#6004)
* first

* typo

* figured it out :)

* what reviewers wanted
2026-06-09 15:10:01 -03:00
Delta-V bot 8dc06f010a Automatic changelog update 2026-06-09 15:45:46 +02:00
Theo fee62b449f shadow cat tweaks (#5977)
* add and remove

* remove comment

* oh yeah and this one
2026-06-09 13:45:26 +00:00
Delta-V bot c0d20b3d79 Automatic changelog update 2026-06-08 23:57:59 +02:00
snowywinters b2944fba52 Edge update (#5983)
* Update edge.yml

* Removed surgeon
2026-06-08 16:57:39 -05:00
2e39916957 Admeme gun changes (#5971)
* Added Chameleon Armor

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* nerfvest

* Lowered Price

* Changed Jackdaw and Atrides fire rates

* Changed battery on Pulse Rifle, upped fire rate

* lowered pulse rifle recharge rate

* Update Resources/Prototypes/_DV/Entities/Objects/Weapons/Guns/Rifles/rifles.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: einknusprigestoast <90181825+einknusprigestoast@users.noreply.github.com>

* Update Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: einknusprigestoast <90181825+einknusprigestoast@users.noreply.github.com>

* Update Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: einknusprigestoast <90181825+einknusprigestoast@users.noreply.github.com>

* Update Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml

Co-authored-by: Radezolid <snappednexus@gmail.com>
Signed-off-by: einknusprigestoast <90181825+einknusprigestoast@users.noreply.github.com>

---------

Signed-off-by: einknusprigestoast <90181825+einknusprigestoast@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
2026-06-08 17:35:29 -03:00
Delta-V bot 874bbf4fd2 Automatic changelog update 2026-06-08 21:50:51 +02:00
VelcroboyandVelcroboy e1ff1ea820 Map Edits: Tortuga (#5965)
* Map Edits: Tortuga

* Final commits

* Robo-Proto

* Service jobs

* reveiw fixes

* Jimbo's birthday present

---------

Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
2026-06-08 21:50:31 +02:00
Delta-V bot 79a4a15403 Automatic changelog update 2026-06-08 21:36:22 +02:00
Vape 0bb2b6ee7b Updates to Submarine.yml (#5760)
* Commit#1

* Update submarine.yml

* ATTEMPT#2

* CASE SENSITIVITIY

* Committing Changes

* Bluesec

* Review updakes
2026-06-08 12:36:01 -07:00
Delta-V bot 18d9325b60 Automatic changelog update 2026-06-08 19:23:43 +02:00
Field Command f07648bc24 Ghost Bar: Syndicate Prison (#5578)
* Ghost Bar: Syndicate Prison

* Copy-paste is evil...

* formatting fix

* IPC no more

* update

* Fix
2026-06-08 12:23:24 -05:00
Delta-V bot f5da329b98 Automatic changelog update 2026-06-08 07:30:14 +02:00
ConstantlyConfused ad6581f2d3 Make the nuclear fab announce when it recieves new recipes (#5985)
make the nuclear fabiractor announce researches
2026-06-08 02:29:55 -03:00
Delta-V bot 430fef2a10 Automatic changelog update 2026-06-08 06:35:40 +02:00
Theo 6970cb9d28 Add cooldown to ninja emp (#5967)
* add 10 second cooldown

* 5 seconds instead
2026-06-08 00:35:20 -04:00
Delta-V bot ea2b8df2cc Automatic changelog update 2026-06-07 22:49:09 +02:00
Theo b87b113736 cult simplemobs deal blunt damage (#5962)
add blunt damage
2026-06-07 20:48:49 +00:00
Delta-V bot f087b2895e Automatic changelog update 2026-06-07 21:46:37 +02:00
MD360andRadezolid 0a14310574 Remove duplicate towels (#5964)
* duplicate begone

* white too

* Fix comment

Signed-off-by: Radezolid <snappednexus@gmail.com>

* Fix of the comment-fix

Signed-off-by: Radezolid <snappednexus@gmail.com>

---------

Signed-off-by: Radezolid <snappednexus@gmail.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
2026-06-07 19:46:18 +00:00
Delta-V bot d9c2f26438 Automatic changelog update 2026-06-07 21:34:18 +02:00
Stxcking a4f11c63dc Fix: Holoflares not Hurting Skia (#5976)
net
2026-06-07 16:33:58 -03:00
Delta-V bot 4ff05277fa Automatic changelog update 2026-06-07 21:05:35 +02:00
Stxcking a33e12e85e Fix: Glowsticks can now be use for glow in the dark stars! (#5970)
yipe
2026-06-07 16:05:16 -03:00
Delta-V bot 62e9ebc216 Automatic changelog update 2026-06-07 20:13:32 +02:00
biddygelson 25b69a3f9e Academy 1.9.0 BLU+ (#5972)
* * Added Poppy to Eng break room.
* Replaced all faxes with department variants. Note Justice was used over Lawyer; faxes added to Dorms, Chem, Botany, Chef, Bar. MimeLaw.
* Replaced Emergency EVAs with Epistemics EVAs in Artefact.
* Replaced RED-Sec with BLU-Sec; Sec, Brig, and Evac.
* Added Anti-Anom to solars.

* * replaced RED with BLU sec in viro security
* removed condenser in chem
* added condenser in atmos front
* added APC to atmos burn chambers
2026-06-07 20:13:12 +02:00
Field Command 7ed7dbcbb1 Maps: Timer be gone! (#5980)
✔
2026-06-07 18:05:08 +00:00
Delta-V bot fcdf1cbbf4 Automatic changelog update 2026-06-07 18:23:16 +02:00
SirrRequiem 9f786a7c1c Terra 6: Everything is Blue (#5956)
* Terra 6: Everything is Blue

* Curtains and carpets now match
2026-06-07 18:22:57 +02:00
416 changed files with 129508 additions and 65702 deletions
+1 -1
View File
@@ -269,7 +269,7 @@ Sentencing modifiers are to be applied by the sentencing officer, judge, or arbi
| style="border: 1px solid black;" | [[File:SL_BreakingAndEntering.png]]
! style="border: 1px solid black;" | {{anchor|Breaking and Entering}}Breaking and Entering
| style="border: 1px solid black;" | 5 minutes
| style="border: 1px solid black;" | To break and enter into a high security area where one is not authorised nor invited, with intent to commit a crime within.
| style="border: 1px solid black;" | To break and enter into an area where one is not authorised nor invited.
|-
| style="border: 1px solid black;" | 203
| style="border: 1px solid black;" | [[File:SL_Rioting.png]]
@@ -237,11 +237,12 @@ internal sealed class AdminNameOverlay : Overlay
}
// DeltaV - SSD Time START
if (_entityManager.TryGetComponent<SSDIndicatorComponent>(entity, out var ssdIndicator) && ssdIndicator.IsSSD)
if (_entityManager.TryGetComponent<SSDIndicatorComponent>(entity, out var ssdIndicator)
&& ssdIndicator.SsdSince is {} ssdSince)
{
color = Color.MediumPurple;
color.A = alpha;
var ssdText = Loc.GetString("admin-overlay-ssd-time", ("time", (_timing.CurTime - ssdIndicator.SsdSince).ToString("%hh':'mm':'ss")));
var ssdText = Loc.GetString("admin-overlay-ssd-time", ("time", (_timing.CurTime - ssdSince).ToString("%hh':'mm':'ss")));
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, ssdText, uiScale, color);
currentOffset += lineoffset;
}
@@ -20,6 +20,7 @@
<CheckBox Name="ShowLoocAboveHeadCheckBox" Text="{Loc 'ui-options-show-looc-on-head'}" />
<CheckBox Name="FancySpeechBubblesCheckBox" Text="{Loc 'ui-options-fancy-speech'}" />
<CheckBox Name="FancyNameBackgroundsCheckBox" Text="{Loc 'ui-options-fancy-name-background'}" />
<CheckBox Name="ChatFollowButton" Text="{Loc 'ui-options-chat-follow-button'}" />
<Label Text="{Loc 'ui-options-general-cursor'}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="ShowHeldItemCheckBox" Text="{Loc 'ui-options-show-held-item'}" />
@@ -63,6 +63,7 @@ public sealed partial class MiscTab : Control
Control.AddOptionCheckBox(CCVars.ChatEnableFancyBubbles, FancySpeechBubblesCheckBox);
Control.AddOptionCheckBox(CCVars.ChatFancyNameBackground, FancyNameBackgroundsCheckBox);
Control.AddOptionCheckBox(CCVars.StaticStorageUI, StaticStorageUI);
Control.AddOptionCheckBox(CCVars.InterfaceChatFollowButton, ChatFollowButton);
Control.Initialize();
}
@@ -1,6 +0,0 @@
using Content.Shared._DV.Psionics.Systems.PsionicPowers;
namespace Content.Client._DV.Psionics.Systems.PsionicPowers;
// This does nothing here. The code is all in the shared/server version.
public sealed class FracturedFormPowerSystem : SharedFracturedFormPowerSystem;
@@ -20,7 +20,11 @@ public sealed class StellarInteractionParticleSystem : EntitySystem
private const string AnimateKey = "particle-animation";
private static readonly EntProtoId InteractionParticleId = "StellarInteractionParticle";
private static readonly Dictionary<StellarInteractionParticleType, EntProtoId> InteractionParticleIds = new ()
{
{ StellarInteractionParticleType.Use, "StellarInteractionParticleUse" },
{ StellarInteractionParticleType.Pull, "StellarInteractionParticlePull" },
};
public override void Initialize()
{
@@ -38,6 +42,11 @@ public sealed class StellarInteractionParticleSystem : EntitySystem
if (!Exists(performer) || !Exists(target))
return;
if (ev.Type == StellarInteractionParticleType.Pull)
{
(performer, target) = (target, performer);
}
var performerXform = Transform(performer);
var targetXform = Transform(target);
if (performerXform.MapID == MapId.Nullspace || targetXform.MapID == MapId.Nullspace)
@@ -47,7 +56,7 @@ public sealed class StellarInteractionParticleSystem : EntitySystem
return;
var performerTargetDelta = targetXform.LocalPosition - performerXform.LocalPosition;
var particle = Spawn(InteractionParticleId, performerXform.Coordinates);
var particle = Spawn(InteractionParticleIds[ev.Type], performerXform.Coordinates);
if (used is { } usedEntity && Exists(usedEntity) && TryComp<SpriteComponent>(usedEntity, out var usedSprite))
{
@@ -58,10 +67,16 @@ public sealed class StellarInteractionParticleSystem : EntitySystem
}
var spriteColor = Comp<SpriteComponent>(particle).Color;
_animation.Play(particle, GetAnimation(performerTargetDelta, spriteColor), AnimateKey);
var animation = ev.Type switch
{
StellarInteractionParticleType.Use => GetUseAnimation(performerTargetDelta, spriteColor),
StellarInteractionParticleType.Pull => GetPullAnimation(performerTargetDelta, spriteColor),
_ => throw new ArgumentOutOfRangeException(nameof(ev), $"Interaction particle event has unknown particle type {ev.Type}"),
};
_animation.Play(particle, animation, AnimateKey);
}
private Animation GetAnimation(Vector2 endOffset, Color color)
private Animation GetUseAnimation(Vector2 endOffset, Color color)
{
var startRotation = _random.NextAngle(Angle.FromDegrees(-40), Angle.FromDegrees(40));
var endRotation = Angle.Zero;
@@ -126,4 +141,44 @@ public sealed class StellarInteractionParticleSystem : EntitySystem
},
};
}
private Animation GetPullAnimation(Vector2 endOffset, Color color)
{
var rotationLength = TimeSpan.FromMilliseconds(8f * (1000f / 12f));
var startOffset = new Vector2();
var offsetLength = TimeSpan.FromMilliseconds(4f * (1000f / 12f));
var endColor = color.WithAlpha(0f);
return new Animation
{
Length = rotationLength,
AnimationTracks =
{
new AnimationTrackComponentProperty()
{
ComponentType = typeof(SpriteComponent),
Property = nameof(SpriteComponent.Offset),
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(startOffset, 0f),
new AnimationTrackProperty.KeyFrame(endOffset, (float)rotationLength.TotalSeconds, Easings.InOutCirc),
},
},
new AnimationTrackComponentProperty()
{
ComponentType = typeof(SpriteComponent),
Property = nameof(SpriteComponent.Color),
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(color, 0f),
new AnimationTrackProperty.KeyFrame(color, (float)offsetLength.TotalSeconds),
new AnimationTrackProperty.KeyFrame(endColor, (float)rotationLength.TotalSeconds, Easings.InOutCirc),
},
},
},
};
}
}
@@ -245,6 +245,7 @@ namespace Content.IntegrationTests.Tests
"TimedDespawnDetailed", // DeltaV
// makes an announcement on mapInit.
"AnnounceOnSpawn",
"ESTimedDespawn" // DeltaV
};
Assert.That(server.CfgMan.GetCVar(CVars.NetPVS), Is.False);
@@ -262,6 +262,32 @@ public sealed partial class AdminVerbSystem
Message = string.Join(": ", ntAgent, Loc.GetString("admin-verb-text-make-NTAgent")),
};
args.Verbs.Add(agent);
args.Verbs.Add(new ()
{
Text = Loc.GetString("admin-verb-make-HeadInsurgent.text"),
Category = VerbCategory.Antag,
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Interface/Misc/job_icons.rsi"), "HeadRevolutionary"),
Act = () =>
{
_antag.ForceMakeAntag<NTAgentRuleComponent>(targetPlayer, "UprisingRule", "HeadInsurgent");
},
Impact = LogImpact.High,
Message = Loc.GetString("admin-verb-make-HeadInsurgent.message"),
});
args.Verbs.Add(new ()
{
Text = Loc.GetString("admin-verb-make-HeadLoyalist.text"),
Category = VerbCategory.Antag,
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Interface/Misc/job_icons.rsi"), "Nanotrasen"),
Act = () =>
{
_antag.ForceMakeAntag<NTAgentRuleComponent>(targetPlayer, "UprisingRule", "HeadLoyalist");
},
Impact = LogImpact.High,
Message = Loc.GetString("admin-verb-make-HeadLoyalist.message"),
});
// End DeltaV Additions
// start DeltaV Additions - add hitman
var hitmanName = Loc.GetString("admin-verb-make-hitman");
+17 -4
View File
@@ -87,7 +87,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
if (anomaly.Comp.CurrentBehavior is not null)
RemoveBehavior(anomaly, anomaly.Comp.CurrentBehavior.Value);
EndAnomaly(anomaly, spawnCore: false);
EndAnomaly(anomaly, spawnCore: false, forced: true);
}
private void OnStartCollide(Entity<AnomalyComponent> anomaly, ref StartCollideEvent args)
@@ -143,7 +143,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
return 0;
var multiplier = 1f;
if (component.Stability > component.GrowthThreshold)
if (component.AlwaysGrow || component.Stability > component.GrowthThreshold) // DeltaV - Add AlwaysGrow
multiplier = component.GrowingPointMultiplier; //more points for unstable
//penalty of up to 50% based on health
@@ -253,7 +253,11 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
else
{
string stateLoc;
if (anomalyComp.Stability < anomalyComp.DecayThreshold)
// DeltaV - Colossus Additions START
if (anomalyComp.AlwaysGrow)
stateLoc = Loc.GetString("anomaly-scanner-stability-high");
// DeltaV - Colossus Additions END
else if (anomalyComp.Stability < anomalyComp.DecayThreshold) // DeltaV - Add else
stateLoc = Loc.GetString("anomaly-scanner-stability-low");
else if (anomalyComp.Stability > anomalyComp.GrowthThreshold)
stateLoc = Loc.GetString("anomaly-scanner-stability-high");
@@ -345,6 +349,15 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
msg.AddMarkupOrThrow(Loc.GetString("anomaly-behavior-unknown"));
else
{
// DeltaV - Colossus Additions START
if (anomalyComp.AlwaysGrow)
{
msg.AddMarkupOrThrow("- " + Loc.GetString("anomaly-behavior-always-grow"));
if (anomalyComp.CurrentBehavior != null)
msg.PushNewline();
}
// DeltaV - Colossus Additions END
if (anomalyComp.CurrentBehavior != null)
{
var behavior = _prototype.Index(anomalyComp.CurrentBehavior.Value);
@@ -354,7 +367,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
var mod = Math.Floor((behavior.EarnPointModifier) * 100);
msg.AddMarkupOrThrow("- " + Loc.GetString("anomaly-behavior-point", ("mod", mod)));
}
else
else if(!anomalyComp.AlwaysGrow) // DeltaV - Add condition, previously regular else
{
msg.AddMarkupOrThrow(Loc.GetString("anomaly-behavior-balanced"));
}
@@ -23,7 +23,8 @@ public sealed partial class AntagSelectionSystem
/// </summary>
public bool TryGetNextAvailableDefinition(Entity<AntagSelectionComponent> ent,
[NotNullWhen(true)] out AntagSelectionDefinition? definition,
int? players = null)
int? players = null,
string? preferredRole = null) // DeltaV - preferrec roles
{
definition = null;
@@ -39,6 +40,11 @@ public sealed partial class AntagSelectionSystem
// It needs to track selected minds for each definition independently.
foreach (var def in ent.Comp.Definitions)
{
// Begin DeltaV - preferred roles
if (preferredRole is not null && !def.PrefRoles.Contains(preferredRole))
continue;
// End DeltaV - preferred roles
var target = GetTargetAntagCount(ent, null, def);
if (mindCount < target)
@@ -336,11 +342,11 @@ public sealed partial class AntagSelectionSystem
/// This technically is a gamerule-ent-less way to make an entity an antag.
/// You should almost never be using this.
/// </summary>
public void ForceMakeAntag<T>(ICommonSession? player, string defaultRule) where T : Component
public void ForceMakeAntag<T>(ICommonSession? player, string defaultRule, string? preferredRole = null) where T : Component // DeltaV - preferred antag roles
{
var rule = ForceGetGameRuleEnt<T>(defaultRule);
if (!TryGetNextAvailableDefinition(rule, out var def))
if (!TryGetNextAvailableDefinition(rule, out var def, preferredRole: preferredRole)) // DeltaV - preferred antag roles
def = rule.Comp.Definitions.Last();
MakeAntag(rule, player, def.Value);
}
+49 -2
View File
@@ -5,6 +5,7 @@ using Content.Server.Administration.Logs;
using Content.Server.Administration.Managers;
using Content.Server.Administration.Systems;
using Content.Server.Discord.DiscordLink;
using Content.Server.Ghost;
using Content.Server.Players.RateLimiting;
using Content.Server.Preferences.Managers;
using Content.Shared.Administration;
@@ -15,6 +16,7 @@ using Content.Shared.Mind;
using Content.Shared.Players; // DeltaV - OOC muting
using Content.Shared.Players.RateLimiting;
using Robust.Shared.Configuration;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Replays;
@@ -47,6 +49,7 @@ internal sealed partial class ChatManager : IChatManager
[Dependency] private readonly ISharedPlayerManager _player = default!;
[Dependency] private readonly DiscordChatLink _discordLink = default!;
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly ILocalizationManager _localizationManager = default!;
private ISawmill _sawmill = default!;
@@ -342,12 +345,35 @@ internal sealed partial class ChatManager : IChatManager
#region Utility
private bool IsValidWarpDestination(EntityUid source)
{
if (!source.Valid)
return false;
if (!_entityManager.TryGetComponent(source, out TransformComponent? transform))
return false;
return transform.MapID != MapId.Nullspace;
}
public string PrependFollowButtonIfAppropriate(string wrappedMessage, EntityUid source, INetChannel recipient)
{
if (IsValidWarpDestination(source) && ShouldShowFollowButton(recipient))
{
var btnText = _localizationManager.GetString("chat-manager-follow-button");
return $"[cmdlink=\"{btnText}\" command=\"{GhostFollowEntityCommand.CommandName} {_entityManager.GetNetEntity(source)}\" /] " + wrappedMessage;
}
return wrappedMessage;
}
public void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, INetChannel client, Color? colorOverride = null, bool recordReplay = false, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
{
var user = author == null ? null : EnsurePlayer(author);
var netSource = _entityManager.GetNetEntity(source);
user?.AddEntity(netSource);
wrappedMessage = PrependFollowButtonIfAppropriate(wrappedMessage, source, client);
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
_netManager.ServerSendMessage(new MsgChatMessage() { Message = msg }, client);
@@ -370,8 +396,12 @@ internal sealed partial class ChatManager : IChatManager
var netSource = _entityManager.GetNetEntity(source);
user?.AddEntity(netSource);
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
_netManager.ServerSendToMany(new MsgChatMessage() { Message = msg }, clients);
foreach (var client in clients)
{
var customWrapMessage = PrependFollowButtonIfAppropriate(wrappedMessage, source, client);
var msg = new ChatMessage(channel, message, customWrapMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
_netManager.ServerSendMessage(new MsgChatMessage { Message = msg }, client);
}
if (!recordReplay)
return;
@@ -379,6 +409,7 @@ internal sealed partial class ChatManager : IChatManager
if ((channel & ChatChannel.AdminRelated) == 0 ||
_configurationManager.GetCVar(CCVars.ReplayRecordAdminChat))
{
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
_replay.RecordServerMessage(msg);
}
}
@@ -439,6 +470,22 @@ internal sealed partial class ChatManager : IChatManager
}
#endregion
private bool ShouldShowFollowButton(INetChannel recipient)
{
if (!_player.TryGetSessionByChannel(recipient, out var session))
return false;
if (_entityManager.TrySystem(out GhostSystem? ghost))
{
if (!ghost.CanGhostWarp(session, out _))
{
return false;
}
}
return _netConfigManager.GetClientCVar(recipient, CCVars.InterfaceChatFollowButton);
}
}
public enum OOCChatType : byte
@@ -49,5 +49,7 @@ namespace Content.Server.Chat.Managers
/// <param name="player">The player sending a chat message.</param>
/// <returns>False if the player has violated rate limits and should be blocked from sending further messages.</returns>
RateLimitStatus HandleRateLimit(ICommonSession player);
string PrependFollowButtonIfAppropriate(string wrappedMessage, EntityUid source, INetChannel recipient);
}
}
@@ -382,11 +382,6 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
var visualEnt = CreateExplosionVisualEntity(pos, queued.Proto.ID, spaceMatrix, spaceData, gridData.Values, iterationIntensity);
// camera shake
// ES START
// CameraShake(iterationIntensity.Count * 4f, pos, queued.TotalIntensity);
// ES END
//For whatever bloody reason, sound system requires ENTITY coordinates.
var mapEntityCoords = _transformSystem.ToCoordinates(_map.GetMap(pos.MapId), pos);
@@ -416,12 +411,7 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
? queued.Proto.SmallSoundFar
: queued.Proto.SoundFar;
// ES START
var farTranslationShake = iterationIntensity.Count < queued.Proto.SmallSoundIterationThreshold
? new ESScreenshakeParameters() { Trauma = 0.4f, DecayRate = 0.2f, Frequency = 0.014f }
: new ESScreenshakeParameters() { Trauma = 0.6f, DecayRate = 0.05f, Frequency = 0.014f };
_shake.Screenshake(filter, farTranslationShake, null);
// ES END
CameraShake(iterationIntensity, pos, queued); // Starlight
_audio.PlayGlobal(farSound, farFilter, true, farSound.Params);
@@ -444,8 +434,13 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
_damageableSystem);
}
private void CameraShake(float range, MapCoordinates epicenter, float totalIntensity)
private void CameraShake(List<float> rangeList, MapCoordinates epicenter, QueuedExplosion queued) // Starlight - replace range with rangeList, totalIntensity with queued
{
// Starlight BEGIN
var range = rangeList.Count * 4f;
var totalIntensity = queued.TotalIntensity * 10f;
// Starlight END
var players = Filter.Empty();
players.AddInRange(epicenter, range, _playerManager, EntityManager);
@@ -463,7 +458,40 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
var distance = delta.Length();
var effect = 5 * MathF.Pow(totalIntensity, 0.5f) * (1 - distance / range);
if (effect > 0.01f)
_recoilSystem.KickCamera(uid, -delta.Normalized() * effect);
{
// DeltaV - Camera kick falloff START
// _recoilSystem.KickCamera(uid, -delta.Normalized() * effect);
// Exponential decay: N(t) = N₀ ⋅ e^(-λ ⋅ t)
// In this case, N = effect and we aren't decaying over time but with increasing distance from the epicenter,
// so t = distance / range. Higher values of λ lead to faster decay, lower values to slower decay.
//
// severity is a fixed factor used to decrease the overall severity of the camera kick,
// as the values were so high by default that decay was only becoming really noticeable near range.
//
// these changes are made here instead of directly assigning to the effect variable
// above to maintain the same overall effect range as before.
const float severity = 0.033f;
const float lambda = 4f;
_recoilSystem.KickCamera(uid, -delta.Normalized() * effect * severity * MathF.Exp(-lambda * (distance / range)));
// DeltaV END
// Starlight START
var shakeParams = rangeList.Count < queued.Proto.SmallSoundIterationThreshold
? new ESScreenshakeParameters() { Trauma = 0.4f, DecayRate = 0.2f, Frequency = 0.014f }
: new ESScreenshakeParameters() { Trauma = 0.6f, DecayRate = 0.05f, Frequency = 0.014f };
// DeltaV - Screenshake falloff START
// Linear falloff with increasing distance from epicenter,
// capped at certain values to avoid diminishing the effect completely near range.
shakeParams.DecayRate *= MathF.Min(1 + distance / range, 1.75f);
shakeParams.Frequency *= MathF.Max(1 - distance / range, 0.33f);
shakeParams.Trauma *= MathF.Max(1 - distance / range, 0.33f);
// DeltaV END
_shake.Screenshake(players, shakeParams, null);
// Starlight END
}
}
}
}
+7 -1
View File
@@ -12,6 +12,7 @@ using Content.Shared.Database;
using Content.Shared.DeviceNetwork;
using Content.Shared.DeviceNetwork.Components;
using Content.Shared.DeviceNetwork.Events;
using Content.Shared.DeviceNetwork.Systems; // DeltaV - map init ordering
using Content.Shared.Emag.Systems;
using Content.Shared.Fax;
using Content.Shared.Fax.Components;
@@ -64,7 +65,7 @@ public sealed class FaxSystem : EntitySystem
// Hooks
SubscribeLocalEvent<FaxMachineComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<FaxMachineComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<FaxMachineComponent, MapInitEvent>(OnMapInit, after: [typeof(SharedDeviceNetworkSystem)]); // DeltaV - map init order, we need address assigned first
SubscribeLocalEvent<FaxMachineComponent, ComponentRemove>(OnComponentRemove);
SubscribeLocalEvent<FaxMachineComponent, EntInsertedIntoContainerMessage>(OnItemSlotChanged);
@@ -301,6 +302,11 @@ public sealed class FaxSystem : EntitySystem
if (!args.Data.TryGetValue(FaxConstants.FaxPaperNameData, out string? name) ||
!args.Data.TryGetValue(FaxConstants.FaxPaperContentData, out string? content))
return;
// Begin DeltaV - we removed the power requirement from device network but we still don't want
// unpowered faxes to happen
if (TryComp<ApcPowerReceiverComponent>(uid, out var receiver) && !receiver.Powered)
return;
// End DeltaV
args.Data.TryGetValue(FaxConstants.FaxPaperLabelData, out string? label);
args.Data.TryGetValue(FaxConstants.FaxPaperStampStateData, out string? stampState);
@@ -35,17 +35,17 @@ public sealed partial class PuddleSystem
if (!entity.Comp.SpillWhenThrown || Openable.IsClosed(entity.Owner))
return;
// DeltaV - Beer Goggles Safe Throw
if ( args.User is { } user && _safeSolutionThrower.GetSafeThrow(user))
{
_physics.SetAngularVelocity(entity, 0);
Transform(entity).LocalRotation = Angle.Zero;
return;
}
// END DeltaV
if (TrySplashSpillAt(entity.Owner, Transform(entity).Coordinates, out _, out var solution) && args.User != null)
{
// DeltaV - Beer Goggles Safe Throw
if (_safeSolutionThrower.GetSafeThrow(args.User.Value))
{
_physics.SetAngularVelocity(entity, 0);
Transform(entity).LocalRotation = Angle.Zero;
return;
}
// END DeltaV
AdminLogger.Add(LogType.Landed,
$"{ToPrettyString(entity.Owner):entity} spilled a solution {SharedSolutionContainerSystem.ToPrettyString(solution):solution} on landing");
}
@@ -0,0 +1,26 @@
using Content.Shared.Administration;
using Robust.Shared.Console;
namespace Content.Server.Ghost;
[AnyCommand]
internal sealed partial class GhostFollowEntityCommand : LocalizedEntityCommands
{
public const string CommandName = "ghost_follow_entity";
[Dependency] private GhostSystem _ghost = null!;
public override string Command => CommandName;
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1 || shell.Player is not { } player)
return;
var target = args[0];
if (!NetEntity.TryParse(target, out var targetEnt))
return;
_ghost.GhostWarpRequest(player, targetEnt);
}
}
+35 -20
View File
@@ -299,10 +299,22 @@ namespace Content.Server.Ghost
#region Warp
public bool CanGhostWarp(ICommonSession session, out EntityUid entity)
{
if (session.AttachedEntity is not { Valid: true } sessionEntity
|| !_ghostQuery.HasComp(sessionEntity))
{
entity = default;
return false;
}
entity = sessionEntity;
return true;
}
private void OnGhostWarpsRequest(GhostWarpsRequestEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession.AttachedEntity is not {Valid: true} entity
|| !_ghostQuery.HasComp(entity))
if (!CanGhostWarp(args.SenderSession, out var entity))
{
Log.Warning($"User {args.SenderSession.Name} sent a {nameof(GhostWarpsRequestEvent)} without being a ghost.");
return;
@@ -312,30 +324,33 @@ namespace Content.Server.Ghost
RaiseNetworkEvent(response, args.SenderSession.Channel);
}
public void GhostWarpRequest(ICommonSession player, NetEntity target)
{
if (!CanGhostWarp(player, out var attached))
{
Log.Warning($"User {player.Name} tried to warp to {target} without being a ghost.");
return;
}
var realTarget = GetEntity(target);
if (!Exists(realTarget))
{
Log.Warning($"User {player.Name} tried to warp to an invalid entity id: {target}");
return;
}
WarpTo(attached, realTarget);
}
private void OnGhostWarpToTargetRequest(GhostWarpToTargetRequestEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession.AttachedEntity is not {Valid: true} attached
|| !_ghostQuery.HasComp(attached))
{
Log.Warning($"User {args.SenderSession.Name} tried to warp to {msg.Target} without being a ghost.");
return;
}
var target = GetEntity(msg.Target);
if (!Exists(target))
{
Log.Warning($"User {args.SenderSession.Name} tried to warp to an invalid entity id: {msg.Target}");
return;
}
WarpTo(attached, target);
GhostWarpRequest(args.SenderSession, msg.Target);
}
private void OnGhostnadoRequest(GhostnadoRequestEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession.AttachedEntity is not {} uid
|| !_ghostQuery.HasComp(uid))
if (CanGhostWarp(args.SenderSession, out var uid))
{
Log.Warning($"User {args.SenderSession.Name} tried to ghostnado without being a ghost.");
return;
@@ -211,7 +211,7 @@ namespace Content.Server.Medical.BiomassReclaimer
_solution.ResolveSolution(toProcess, stream.BloodSolutionName, ref stream.BloodSolution, out var solution))
{
component.BloodReagents = solution.Clone();
component.BloodReagents.ScaleSolution(50 / component.BloodReagents.Volume);
//component.BloodReagents.ScaleSolution(50 / component.BloodReagents.Volume); // Delta V - This doesn't need to be here. It just always makes the solution ~50u but also might divide by 0. Just use the current blood level so more blood = more mess.
}
if (TryComp<ButcherableComponent>(toProcess, out var butcherableComponent))
{
+2 -2
View File
@@ -475,7 +475,7 @@ public sealed class NukeSystem : EntitySystem
/// <summary>
/// Force a nuclear bomb to start a countdown timer
/// </summary>
public void ArmBomb(EntityUid uid, NukeComponent? component = null)
public void ArmBomb(EntityUid uid, NukeComponent? component = null, string? announcementId = null) // DeltaV - custom announcements
{
if (!Resolve(uid, ref component))
return;
@@ -500,7 +500,7 @@ public sealed class NukeSystem : EntitySystem
_selectedNukeSong = _audio.ResolveSound(component.ArmMusic);
// warn a crew
var announcement = Loc.GetString("nuke-component-announcement-armed",
var announcement = Loc.GetString(announcementId ?? "nuke-component-announcement-armed", // DeltaV - custom announcements
("time", (int) component.RemainingTime),
("location", FormattedMessage.RemoveMarkupOrThrow(_navMap.GetNearestBeaconString((uid, nukeXform)))));
var sender = Loc.GetString("nuke-component-announcement-sender");
@@ -1,5 +1,7 @@
using Content.Server.Administration.Logs;
using Content.Server.Chat.Managers;
using Content.Server.Chat.Systems;
using Content.Server.Ghost;
using Content.Server.Power.Components;
using Content.Shared._DV.Chat;
using Content.Shared.Chat;
@@ -28,6 +30,8 @@ public sealed class RadioSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly GhostSystem _ghost = default!;
// set used to prevent radio feedback loops.
private readonly HashSet<string> _messages = new();
@@ -55,8 +59,25 @@ public sealed class RadioSystem : EntitySystem
private void OnIntrinsicReceive(EntityUid uid, IntrinsicRadioReceiverComponent component, ref RadioReceiveEvent args)
{
if (TryComp(uid, out ActorComponent? actor))
_netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel);
if (!TryComp(uid, out ActorComponent? actor))
return;
var msg = args.ChatMsg;
if (_ghost.CanGhostWarp(actor.PlayerSession, out _))
{
msg = new MsgChatMessage
{
Message = new ChatMessage(args.ChatMsg.Message)
{
WrappedMessage = _chatManager.PrependFollowButtonIfAppropriate(
args.ChatMsg.Message.WrappedMessage,
args.MessageSource,
actor.PlayerSession.Channel),
},
};
}
_netMan.ServerSendMessage(msg, actor.PlayerSession.Channel);
}
// DeltaV
+24 -2
View File
@@ -1,3 +1,4 @@
using System.Linq; // DeltaV
using System.Numerics;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Chat.Systems;
@@ -8,6 +9,8 @@ using Content.Server.Popups;
using Content.Shared.Atmos;
using Content.Shared.Chat;
using Content.Shared.Dataset;
using Content.Shared.Mobs; // DeltaV
using Content.Shared.Mobs.Components; // DeltaV
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Pointing;
@@ -47,14 +50,33 @@ namespace Content.Server.RatKing
if (!TryComp<HungerComponent>(uid, out var hunger))
return;
// DeltaV - modify cost of Raise Army based on the amount of alive servants
// Check on how many servants are alive to calculate the cost of a new servant
var aliveServants = component.Servants.Count(servant
=> TryComp<MobStateComponent>(servant, out var mobState) && mobState.CurrentState == MobState.Alive);
// calculate the cost multiplier
var multiplier = aliveServants switch
{
< 5 => 1.0f, // 1-5 servants: 10 hunger
< 10 => 1.5f, // 6-10 servants: 15 hunger
< 15 => 2.5f, // 11-15 servants: 25 hunger
< 20 => 5.0f, // 16-20 servants: 50 hunger
< 25 => 10.0f, // 21-25 servants: 100 hunger
_ => 15.0f, // Above 25 servants: 150 hunger
};
var hungerPerArmyUseAdjusted = component.HungerPerArmyUse * multiplier;
//make sure the hunger doesn't go into the negatives
if (_hunger.GetHunger(hunger) < component.HungerPerArmyUse)
if (_hunger.GetHunger(hunger) < hungerPerArmyUseAdjusted)
{
_popup.PopupEntity(Loc.GetString("rat-king-too-hungry"), uid, uid);
return;
}
args.Handled = true;
_hunger.ModifyHunger(uid, -component.HungerPerArmyUse, hunger);
_hunger.ModifyHunger(uid, - hungerPerArmyUseAdjusted, hunger);
// DeltaV - end to the modified cost of Raise Army
var servant = Spawn(component.ArmyMobSpawnId, Transform(uid).Coordinates);
var comp = EnsureComp<RatKingServantComponent>(servant);
comp.King = uid;
@@ -0,0 +1,84 @@
using Content.Server.Revolutionary.Components;
using Content.Shared._DV.Uprising;
using Content.Shared.Cuffs.Components;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Objectives.Components;
using Content.Shared.Roles;
using Content.Shared.Station;
namespace Content.Server.Uprising;
public sealed class CommandStatusObjectiveSystem : EntitySystem
{
[Dependency] private readonly SharedRoleSystem _role = default!;
[Dependency] private readonly SharedStationSystem _station = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CommandStatusObjectiveComponent, ObjectiveGetProgressEvent>(OnGetProgress);
}
private bool CheckIncapacitated(EntityUid uid)
{
if (TryComp<CuffableComponent>(uid, out var cuffed) && cuffed.CuffedHandCount > 0)
return true;
if (!TryComp<MobStateComponent>(uid, out var state))
return true;
if (state.CurrentState is MobState.Dead or MobState.Invalid)
return true;
if (_station.GetOwningStation(uid) == null)
return true;
return false;
}
private void OnGetProgress(Entity<CommandStatusObjectiveComponent> ent, ref ObjectiveGetProgressEvent args)
{
var total = 0;
var counted = 0;
var query = AllEntityQuery<MindContainerComponent, CommandStaffComponent>();
while (query.MoveNext(out var uid, out var mind, out _))
{
if (mind.Mind is not { } mindUid)
continue;
total++;
var converted = false;
foreach (var role in ent.Comp.ConvertedRoles)
{
if (!EntityManager.ComponentFactory.TryGetRegistration(role, out var roleReg))
{
Log.Error($"Role component not found for CrewConversionObjective: {role}");
continue;
}
if (!_role.MindHasRole(mindUid, roleReg.Type, out _))
continue;
converted = true;
break;
}
var incapacitated = CheckIncapacitated(uid);
if (converted && !incapacitated || !converted && ent.Comp.ShouldUnconvertedBeIncapacitated && incapacitated)
{
counted++;
}
}
if (total == 0)
return;
args.Progress = (float)counted / (float)total;
}
}
@@ -1,4 +1,3 @@
using Content.Server._DV.Psionics.Systems;
using Content.Server.Administration.Managers;
using Content.Server.Atmos.Components;
using Content.Server.Body.Components;
@@ -14,7 +13,6 @@ using Content.Server.NPC.HTN;
using Content.Server.NPC.Systems;
using Content.Server.StationEvents.Components;
using Content.Server.Speech.Components;
using Content.Shared._DV.Psionics.Components; // DeltaV
using Content.Shared.Body.Components;
using Content.Shared.CombatMode;
using Content.Shared.CombatMode.Pacification;
@@ -27,7 +25,6 @@ using Content.Shared.Mobs.Components;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.NPC.Components; // DeltaV
using Content.Shared.NPC.Systems;
using Content.Shared.Nutrition.AnimalHusbandry;
using Content.Shared.Nutrition.Components;
@@ -72,7 +69,6 @@ public sealed partial class ZombieSystem
[Dependency] private readonly NPCSystem _npc = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly ISharedPlayerManager _player = default!;
[Dependency] private readonly PsionicSystem _psionic = default!; // DeltaV
private static readonly ProtoId<TagPrototype> InvalidForGlobalSpawnSpellTag = "InvalidForGlobalSpawnSpell";
private static readonly ProtoId<TagPrototype> CannotSuicideTag = "CannotSuicide";
@@ -134,6 +130,9 @@ public sealed partial class ZombieSystem
//you're a real zombie now, son.
var zombiecomp = AddComp<ZombieComponent>(target);
// DeltaV - Save factions, psionics, etc. before modifications are made.
PreserveEntityComponentState((target, zombiecomp));
//we need to basically remove all of these because zombies shouldn't
//get diseases, breath, be thirst, be hungry, die in space, get double sentience, have offspring or be paraplegic.
RemComp<RespiratorComponent>(target);
@@ -146,12 +145,6 @@ public sealed partial class ZombieSystem
RemComp<ComplexInteractionComponent>(target);
RemComp<SentienceTargetComponent>(target);
// DeltaV Start - Prevent Psionic Zombies
RemComp<PotentialPsionicComponent>(target);
if (HasComp<PsionicComponent>(target))
_psionic.MindBreakEntity(target, false, true);
// DeltaV End - Prevent Psionic Zombies
//funny voice
var accentType = "zombie";
if (TryComp<ZombieAccentOverrideComponent>(target, out var accent))
@@ -245,6 +238,9 @@ public sealed partial class ZombieSystem
//Should prevent instances of zombies using comms for information they shouldnt be able to have.
_inventory.TryUnequip(target, "ears", true, true);
// DeltaV - Extra zombification removals, etc.
ZombifyEntityDV((target, zombiecomp), mobState);
//popup
_popup.PopupEntity(Loc.GetString("zombie-transform", ("target", target)), target, PopupType.LargeCaution);
@@ -261,7 +257,6 @@ public sealed partial class ZombieSystem
_faction.ClearFactions(target, dirty: false);
_faction.AddFaction(target, ZombieFaction);
EnsureComp<NoFriendlyFireComponent>(target); // DeltaV - prevent shitters biting other zombies
//gives it the funny "Zombie ___" name.
_nameMod.RefreshNameModifiers(target);
+3 -1
View File
@@ -78,6 +78,8 @@ namespace Content.Server.Zombies
SubscribeLocalEvent<IncurableZombieComponent, MapInitEvent>(OnPendingMapInit);
SubscribeLocalEvent<ZombifyOnDeathComponent, MobStateChangedEvent>(OnDamageChanged);
InitializeDV(); // DeltaV - Additional Subscriptions for ZombieComponent
}
private void OnBeforeRemoveAnomalyOnDeath(Entity<PendingZombieComponent> ent, ref BeforeRemoveAnomalyOnDeathEvent args)
@@ -325,7 +327,7 @@ namespace Content.Server.Zombies
// Remove the role when getting cloned, getting gibbed and borged, or leaving the body via any other method.
private void OnMindRemoved(Entity<ZombieComponent> ent, ref MindRemovedMessage args)
{
_role.MindRemoveRole<ZombieRoleComponent>((args.Mind.Owner, args.Mind.Comp));
_role.MindRemoveRole<ZombieRoleComponent>((args.Mind.Owner, args.Mind.Comp));
}
}
}
@@ -0,0 +1,63 @@
using Content.Server._DV.CosmicCult.Components;
using Content.Shared._DV.CosmicCult.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Weapons.Melee;
using Robust.Shared.Prototypes;
namespace Content.Server._DV.CosmicCult.Abilities.Colossus;
public sealed class CosmicColossusBuffsSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damage = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MultiplyAttackRateOnSupercriticalComponent, CosmicColossusEffigySupercriticalEvent>(HandleAttackRate);
SubscribeLocalEvent<FlatAttackBonusOnSupercriticalComponent, CosmicColossusEffigySupercriticalEvent>(HandleDamageBonus);
SubscribeLocalEvent<MultiplyCorruptingSpeedOnSupercriticalComponent, CosmicColossusEffigySupercriticalEvent>(HandleCorruptingSpeed);
SubscribeLocalEvent<HealOnSupercriticalComponent, CosmicColossusEffigySupercriticalEvent>(HandleHeal);
}
private void HandleAttackRate(Entity<MultiplyAttackRateOnSupercriticalComponent> ent,
ref CosmicColossusEffigySupercriticalEvent args)
{
if (TryComp<MeleeWeaponComponent>(ent, out var weapon))
{
weapon.AttackRate *= ent.Comp.Multiplier;
}
}
private void HandleDamageBonus(Entity<FlatAttackBonusOnSupercriticalComponent> ent,
ref CosmicColossusEffigySupercriticalEvent args)
{
if (!TryComp<CosmicColossusComponent>(ent, out var colossusComp))
return;
colossusComp.BonusDamage +=
new DamageSpecifier(_proto.Index(ent.Comp.BonusDamageType), ent.Comp.BonusDamage);
}
private void HandleCorruptingSpeed(Entity<MultiplyCorruptingSpeedOnSupercriticalComponent> ent,
ref CosmicColossusEffigySupercriticalEvent args)
{
if (TryComp<CosmicCorruptingComponent>(ent, out var corrupting))
{
corrupting.CorruptionSpeed *= ent.Comp.Multiplier;
}
}
private void HandleHeal(Entity<HealOnSupercriticalComponent> ent, ref CosmicColossusEffigySupercriticalEvent args)
{
if (TryComp<DamageableComponent>(ent, out var damageable))
{
_damage.TryChangeDamage(ent.Owner,
-damageable.Damage * Math.Abs(ent.Comp.DamageFractionHealed), // just in case someone sets a negative value in YML
true);
}
}
}
@@ -0,0 +1,8 @@
using Content.Server._DV.CosmicCult.Components;
namespace Content.Server._DV.CosmicCult.Abilities.Colossus;
[ByRefEvent]
public readonly record struct CosmicColossusEffigySupercriticalEvent(
Entity<CosmicEffigyComponent> Effigy
);
@@ -1,15 +1,24 @@
using System.Numerics;
using Content.Server._DV.CosmicCult.Abilities.Colossus;
using Content.Server._DV.CosmicCult.Components;
using Content.Server.Actions;
using Content.Server.Chat.Managers;
using Content.Server.Objectives.Components;
using Content.Server.Objectives.Systems;
using Content.Server.Popups;
using Content.Shared._DV.CosmicCult;
using Content.Shared._DV.CosmicCult.Components;
using Content.Shared.Anomaly.Components;
using Content.Shared.Maps;
using Content.Shared.Mind;
using Content.Shared.Popups;
using Content.Shared.Warps;
using Robust.Server.Audio;
using Robust.Server.Player;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Player;
using Robust.Shared.Timing;
namespace Content.Server._DV.CosmicCult.Abilities;
@@ -23,12 +32,93 @@ public sealed class CosmicEffigySystem : EntitySystem
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly CosmicCultObjectiveSystem _cultObjective = default!;
[Dependency] private readonly IGameTiming _time = default!;
[Dependency] private readonly IChatManager _chat = default!;
[Dependency] private readonly IPlayerManager _player = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CosmicColossusComponent, EventCosmicColossusEffigy>(OnColossusEffigy);
SubscribeLocalEvent<CosmicEffigyComponent, AnomalySupercriticalEvent>(OnSupercritical);
SubscribeLocalEvent<CosmicEffigyComponent, AnomalyShutdownEvent>(OnAnomShutdown);
}
private void OnAnomShutdown(Entity<CosmicEffigyComponent> ent, ref AnomalyShutdownEvent args)
{
if (args.Forced || args.Supercritical || !Exists(ent.Comp.Colossus) || !TryComp<CosmicColossusComponent>(ent.Comp.Colossus, out var colossusComp))
return;
colossusComp.DeathTimer = _time.CurTime;
colossusComp.Timed = true;
}
private void OnSupercritical(Entity<CosmicEffigyComponent> ent, ref AnomalySupercriticalEvent args)
{
if (!Exists(ent.Comp.Colossus)
|| !TryComp<CosmicColossusComponent>(ent.Comp.Colossus, out var colossusComp)
|| !_mind.TryGetMind(ent.Comp.Colossus.Value, out _, out var mind))
return;
var colossus = ent.Comp.Colossus.Value;
var ev = new CosmicColossusEffigySupercriticalEvent(ent);
RaiseLocalEvent(colossus, ref ev);
var transform = Transform(ent.Comp.Colossus.Value);
Spawn(colossusComp.BuffVfx, transform.Coordinates);
if (colossusComp.CompletedEffigies == 0)
{
_audio.PlayStatic(colossusComp.ReawakenSfx,
Filter.BroadcastMap(transform.MapID),
transform.Coordinates,
true);
}
else
{
_audio.PlayPvs(colossusComp.ReawakenSfx, ent);
}
colossusComp.CompletedEffigies += 1;
if (colossusComp.CompletedEffigies >= colossusComp.MaxEffigies)
{
colossusComp.Timed = false;
_popup.PopupEntity(Loc.GetString("colossus-buff-final-popup"), colossus, PopupType.Large);
return;
}
_popup.PopupEntity(Loc.GetString("colossus-buff-popup"), colossus, PopupType.Large);
var objIndex = mind.Objectives.FindIndex(HasComp<CosmicEffigyConditionComponent>);
if (objIndex == -1 ||
!TryComp<CosmicEffigyConditionComponent>(mind.Objectives[objIndex], out var conditionComp))
{
Log.Error($"Failed to find effigy objective on {ToPrettyString(colossus)}!");
return;
}
var objective = mind.Objectives[objIndex];
if (_cultObjective.RandomizeEffigyTarget(objective, conditionComp, setDescription: true) is not {} nextTarget)
{
Log.Error("Failed to randomize effigy objective location!");
return;
}
if (mind.UserId is { } userId)
{
_chat.DispatchServerMessage(_player.GetSessionById(userId), Loc.GetString("colossus-next-target", ("location", nextTarget)));
}
_codeCondition.SetCompleted(objective, false);
colossusComp.EffigyPlaceActionEntity = _actions.AddAction(colossus, colossusComp.EffigyPlaceAction);
colossusComp.DeathTimer = _time.CurTime + colossusComp.DeathWaitEffigy;
colossusComp.Timed = true;
}
private void OnColossusEffigy(Entity<CosmicColossusComponent> ent, ref EventCosmicColossusEffigy args)
@@ -38,8 +128,16 @@ public sealed class CosmicEffigySystem : EntitySystem
_actions.RemoveAction(ent.Owner, ent.Comp.EffigyPlaceActionEntity);
_codeCondition.SetCompleted(ent.Owner, ent.Comp.EffigyObjective);
Spawn(ent.Comp.EffigyPrototype, pos);
var effigy = Spawn(ent.Comp.EffigyPrototype, pos);
ent.Comp.Timed = false;
if (!TryComp<CosmicEffigyComponent>(effigy, out var effigyComp))
{
Log.Error("Colossus tried to place Effigy prototype missing CosmicEffigyComponent!");
return;
}
effigyComp.Colossus = ent.Owner;
}
private bool VerifyPlacement(Entity<CosmicColossusComponent> ent, out EntityCoordinates outPos)
@@ -0,0 +1,56 @@
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Server._DV.CosmicCult.Components;
/// <summary>
/// The owning colossus's attack rate will be multiplied by
/// the given multiplier once its effigy goes supercritical.
/// Component meant to be applied to Cosmic Colossus.
/// </summary>
[RegisterComponent]
public sealed partial class MultiplyAttackRateOnSupercriticalComponent : Component
{
[DataField]
public float Multiplier = 1.1f;
}
/// <summary>
/// The owning colossus's corrupting speed will be multiplied by
/// the given multiplier once its effigy goes supercritical.
/// Component meant to be applied to Cosmic Colossus.
/// </summary>
[RegisterComponent]
public sealed partial class MultiplyCorruptingSpeedOnSupercriticalComponent : Component
{
[DataField]
public float Multiplier = 0.9f;
}
/// <summary>
/// The owning colossus will receive a flat bonus to
/// its melee attack damage once its effigy goes supercritical.
/// Component meant to be applied to Cosmic Colossus.
/// </summary>
[RegisterComponent]
public sealed partial class FlatAttackBonusOnSupercriticalComponent : Component
{
[DataField]
public FixedPoint2 BonusDamage = 10;
[DataField]
public ProtoId<DamageTypePrototype> BonusDamageType = "Blunt";
}
/// <summary>
/// The owning colossus will be healed for `-CurrentDamage * Abs(DamageFractionHealed)` damage
/// once its effigy goes supercritical.
/// Component meant to be applied to Cosmic Colossus.
/// </summary>
[RegisterComponent]
public sealed partial class HealOnSupercriticalComponent : Component
{
[DataField]
public float DamageFractionHealed = 1.0f;
}
@@ -1,3 +1,4 @@
using Content.Server._DV.CosmicCult.Abilities.Colossus;
using Content.Server._DV.CosmicCult.EntitySystems;
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
@@ -5,7 +6,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server._DV.CosmicCult.Components;
[RegisterComponent, Access(typeof(CosmicCorruptingSystem))]
[RegisterComponent, Access(typeof(CosmicCorruptingSystem), typeof(CosmicColossusBuffsSystem))]
[AutoGenerateComponentPause]
public sealed partial class CosmicCorruptingComponent : Component
{
@@ -0,0 +1,19 @@
using Content.Server._DV.CosmicCult.Abilities;
using Content.Server._DV.CosmicCult.EntitySystems;
namespace Content.Server._DV.CosmicCult.Components;
/// <summary>
/// Component for cosmic effigy anomalies, spawned by Cosmic Colossi.
/// </summary>
/// <seelso cref="CosmicEffigySystem"/>.
/// <seelso cref="CosmicColossusSystem"/>.
[RegisterComponent]
public sealed partial class CosmicEffigyComponent : Component
{
/// <summary>
/// The colossus that placed this effigy.
/// </summary>
[DataField]
public EntityUid? Colossus;
}
@@ -35,6 +35,12 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem
if (args.Cancelled || !_roles.MindHasRole<CosmicColossusRoleComponent>(args.MindId))
return;
if (RandomizeEffigyTarget(uid, comp) is null)
args.Cancelled = true;
}
public string? RandomizeEffigyTarget(EntityUid uid, CosmicEffigyConditionComponent comp, bool setDescription = false)
{
var warps = new List<EntityUid>();
var query = EntityQueryEnumerator<WarpPointComponent>();
var effigyBlacklist = comp.Blacklist;
@@ -51,10 +57,22 @@ public sealed class CosmicCultObjectiveSystem : EntitySystem
if (warps.Count <= 0)
{
args.Cancelled = true;
return;
return null;
}
comp.EffigyTarget = _random.Pick(warps);
var newWarp = _random.Pick(warps);
var warpComp = Comp<WarpPointComponent>(newWarp);
comp.EffigyTarget = newWarp;
if (setDescription)
{
_metaData.SetEntityDescription(uid,
warpComp.Location != null
? Loc.GetString("objective-condition-effigy", ("location", warpComp.Location))
: Loc.GetString("objective-condition-effigy-no-target"));
}
return warpComp.Location;
}
private void OnEffigyAfterAssign(EntityUid uid, CosmicEffigyConditionComponent comp, ref ObjectiveAfterAssignEvent args)
@@ -13,6 +13,7 @@ using Content.Shared.Popups;
using Content.Shared.Station.Components;
using Content.Shared.Throwing;
using Content.Shared.Warps;
using Content.Shared.Weapons.Melee.Events;
using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Physics.Components;
@@ -41,6 +42,7 @@ public sealed class CosmicColossusSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<CosmicColossusComponent, ComponentInit>(OnSpawn);
SubscribeLocalEvent<CosmicColossusComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<CosmicColossusComponent, MeleeHitEvent>(OnMeleeHit);
}
public override void Update(float frameTime)
@@ -82,7 +84,7 @@ public sealed class CosmicColossusSystem : EntitySystem
private void OnSpawn(Entity<CosmicColossusComponent> ent, ref ComponentInit args) // I WANT THIS BIG GUY HURLED TOWARDS THE STATION
{
ent.Comp.DeathTimer = _timing.CurTime + ent.Comp.DeathWait;
ent.Comp.DeathTimer = _timing.CurTime + ent.Comp.DeathWaitSpawn;
var station = _station.GetStationInMap(Transform(ent).MapID);
if (TryComp<StationDataComponent>(station, out var stationData))
{
@@ -115,4 +117,9 @@ public sealed class CosmicColossusSystem : EntitySystem
RemComp<WarpPointComponent>(ent);
RemComp<CosmicCorruptingComponent>(ent);
}
private void OnMeleeHit(Entity<CosmicColossusComponent> colossus, ref MeleeHitEvent args)
{
args.BonusDamage += colossus.Comp.BonusDamage;
}
}
@@ -1,212 +0,0 @@
using Content.Server.Cloning;
using Content.Server.Mind;
using Content.Server.Station.Systems;
using Content.Shared._DV.Psionics.Components;
using Content.Shared._DV.Psionics.Components.PsionicPowers;
using Content.Shared._DV.Psionics.Systems.PsionicPowers;
using Content.Shared._DV.Species;
using Content.Shared.Bed.Sleep;
using Content.Shared.Body.Components;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Mobs.Components;
using Content.Shared.Popups;
using Content.Shared.Preferences;
using Robust.Server.GameObjects;
using Robust.Server.GameStates;
using Robust.Server.Player;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server._DV.Psionics.Systems.PsionicPowers;
public sealed class FracturedFormPowerSystem : SharedFracturedFormPowerSystem
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly CloningSystem _cloning = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly PvsOverrideSystem _pvsOverride = default!;
// holy initialize performance? but better for it to happen once than the double dict lookup every tick!!
private EntityQuery<FracturedFormBodyComponent> _bodyQuery;
private EntityQuery<SleepingComponent> _sleepingQuery;
public override void Initialize()
{
base.Initialize();
_bodyQuery = GetEntityQuery<FracturedFormBodyComponent>();
_sleepingQuery = GetEntityQuery<SleepingComponent>();
}
protected override void OnPowerInit(Entity<FracturedFormPowerComponent> power, ref MapInitEvent args)
{
base.OnPowerInit(power, ref args);
// The next random swap is between 5 and 20 minutes.
var randomTime = Random.Next(power.Comp.NextSwapMinTime, power.Comp.NextSwapMaxTime);
power.Comp.NextSwap = Timing.CurTime + randomTime;
power.Comp.NextVoluntarySwap = Timing.CurTime + power.Comp.VoluntarySwapCooldown;
// Don't generate a new body if we're already part of a network.
if (HasComp<FracturedFormBodyComponent>(power))
return;
// Don't make bodies if there is no body. This is solely for test fails.
if (!HasComp<BodyComponent>(power))
return;
var bodyComp = AddComp<FracturedFormBodyComponent>(power);
bodyComp.ControllingForm = power.Owner;
power.Comp.Bodies.Add(power);
var body = GenerateForm(power);
// hide the SSD indicator.
if (SsdQuery.TryComp(body, out var ssdComp))
ssdComp.IsSSD = false;
}
private EntityUid GenerateForm(Entity<FracturedFormPowerComponent> original)
{
// Form:
// - Same appearance as original
// - Different apperance, still humanoid
// Equipment:
// - Same as original body
// - Nude and helpless
var xform = Transform(original);
var hasGear = Random.Prob(original.Comp.HasGearChance);
if (Random.Prob(original.Comp.DifferentSpeciesChance) || !_cloning.TryCloning(original, _transform.GetMapCoordinates(original), hasGear ? original.Comp.CopyClothed : original.Comp.CopyNaked, out var newBody)) // Slightly lower chance to copy the original body
{
// Either the dice rolled poorly, or the cloning failed. Either way, make a new body instead. (Or try to)
var validSpecies = new List<ProtoId<SpeciesPrototype>>();
var speciesPrototypes = _prototype.EnumeratePrototypes<SpeciesPrototype>();
foreach (var proto in speciesPrototypes)
{
var speciesEntityPrototype = _prototype.Index<EntityPrototype>(proto.Prototype);
// If they have the PotentialPsionicComponent, they can be psionic.
if (proto.RoundStart && speciesEntityPrototype.TryGetComponent<PotentialPsionicComponent>(out _, Factory) && !SpeciesHiderSystem.IsHidden(proto.ID))
validSpecies.Add(proto.ID);
}
var species = Random.Pick(validSpecies);
var character = HumanoidCharacterProfile.RandomWithSpecies(species);
newBody = _stationSpawning.SpawnPlayerMob(xform.Coordinates, hasGear ? original.Comp.VisitorJob : original.Comp.NakedJob, character, _station.GetOwningStation(original.Owner));
if (newBody is not { } bodyV || Deleted(bodyV))
{
Log.Error($"Failed to create a new body for {ToPrettyString(original)}. This is a bug.");
return EntityUid.Invalid;
}
}
if (newBody is not { } body || Deleted(body))
return default!;
var bodyComp = AddComp<FracturedFormBodyComponent>(body);
original.Comp.Bodies.Add(body);
bodyComp.ControllingForm = original.Owner;
if (_player.TryGetSessionByEntity(original, out var session))
_pvsOverride.AddSessionOverride(body, session);
Dirty(original);
return body;
}
private bool TryGetValidBody(Entity<FracturedFormPowerComponent> psionic, out EntityUid validBody)
{
foreach (var body in psionic.Comp.Bodies)
{
if (!IsValidBody(psionic, body))
continue;
validBody = body;
return true;
}
validBody = default;
return false;
}
private void Swap(Entity<FracturedFormPowerComponent> psionic)
{
if (!TryGetValidBody(psionic, out var targetBody))
return;
_audio.PlayPvs(psionic.Comp.SwapSound, psionic);
// Transfer mind if present
if (MindContainerQuery.TryComp(psionic, out var mindContainer) && mindContainer.Mind.HasValue)
_mind.TransferTo(mindContainer.Mind.Value, targetBody);
// Wake up the new body
Sleeping.TryWaking(targetBody);
// Remove the action.
Action.RemoveAction(psionic.Comp.ActionEntity);
// Create new component on target and copy data
var duplicate = EnsureComp<FracturedFormPowerComponent>(targetBody);
duplicate.Bodies = psionic.Comp.Bodies;
// Update all body references
foreach (var body in duplicate.Bodies)
{
if (_bodyQuery.TryComp(body, out var bodyComp))
bodyComp.ControllingForm = targetBody;
}
if (_player.TryGetSessionByEntity(targetBody, out var session))
{
_pvsOverride.AddSessionOverride(psionic, session);
_pvsOverride.RemoveSessionOverride(targetBody, session);
}
RemCompDeferred<FracturedFormPowerComponent>(psionic);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
List<Entity<FracturedFormPowerComponent>> swapTargets = [];
var entities = EntityQueryEnumerator<FracturedFormPowerComponent, MobStateComponent>();
while (entities.MoveNext(out var uid, out var comp, out var mobState))
{
// Check sleep warning
if (!comp.SleepWarned && Timing.CurTime > comp.NextSwap - comp.WarningTimeBeforeSleep)
{
comp.SleepWarned = true;
Popup.PopupEntity(Loc.GetString("psionic-power-fractured-form-sleepy"), uid, uid, PopupType.LargeCaution);
Chat.TryEmoteWithChat(uid, "Yawn");
}
// Swap check
if ((_sleepingQuery.HasComp(uid) || MobState.IsIncapacitated(uid, mobState)) && Timing.CurTime > comp.NextVoluntarySwap
|| Timing.CurTime > comp.NextSwap)
swapTargets.Add((uid, comp));
}
foreach (var target in swapTargets)
{
Swap(target);
}
// Process bodies
var bodies = EntityQueryEnumerator<FracturedFormBodyComponent, MobStateComponent>();
while (bodies.MoveNext(out var uid, out var comp, out var mobState))
{
// Put to sleep if no sleeping component and no mind
if (!_sleepingQuery.HasComp(uid) && !_mind.GetMind(uid).HasValue && !FracturedQuery.HasComp(uid))
Sleeping.TrySleeping((uid, mobState));
// Cleanup invalid bodies
if (!comp.ControllingForm.IsValid()
|| Deleted(comp.ControllingForm)
|| !FracturedQuery.HasComp(comp.ControllingForm))
{
RemCompDeferred<FracturedFormBodyComponent>(uid);
}
}
}
}
@@ -0,0 +1,8 @@
namespace Content.Server._DV.Uprising;
[RegisterComponent, Access(typeof(UprisingRuleSystem))]
public sealed partial class UprisingConsoleComponent : Component
{
[DataField]
public TimeSpan Delay = TimeSpan.FromSeconds(5);
}
@@ -0,0 +1,54 @@
using Content.Shared._DV.Roles;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server._DV.Uprising;
[RegisterComponent, Access(typeof(UprisingRuleSystem)), AutoGenerateComponentPause]
public sealed partial class UprisingRuleComponent : Component
{
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan? NukeAnnouncementAt;
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan? NukeTimeAt;
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan? FirstWarningAt;
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan? ImpendingWarningAt;
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan? FinalWarningAt;
[DataField]
public TimeSpan NukeAnnouncementDelay = TimeSpan.FromMinutes(30);
[DataField]
public TimeSpan NukeTimeDelay = TimeSpan.FromMinutes(90);
[DataField]
public TimeSpan FirstWarning = TimeSpan.FromMinutes(30);
[DataField]
public TimeSpan ImpendingWarning = TimeSpan.FromMinutes(15);
[DataField]
public TimeSpan FinalWarning = TimeSpan.FromMinutes(5);
[DataField]
public float NukeDuration = 60f;
[DataField]
public (UprisingSide, TimeSpan)? SideWinsAt;
[DataField]
public UprisingSide? SideWon;
[DataField]
public Dictionary<UprisingSide, TimeSpan> SideTimes = new()
{
{ UprisingSide.Insurgent , TimeSpan.FromMinutes(3) },
{ UprisingSide.Loyalist , TimeSpan.FromMinutes(3) },
};
}
@@ -0,0 +1,341 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Antag;
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.Nuke;
using Content.Server.Pinpointer;
using Content.Server.Roles;
using Content.Shared._DV.Roles;
using Content.Shared._DV.Uprising;
using Content.Shared.Chat;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.DoAfter;
using Content.Shared.GameTicking.Components;
using Content.Shared.Mind;
using Content.Shared.Objectives.Components;
using Content.Shared.Objectives.Systems;
using Content.Shared.Roles;
using Content.Shared.Verbs;
using Robust.Shared.Player;
using Robust.Shared.Utility;
namespace Content.Server._DV.Uprising;
public sealed class UprisingRuleSystem : GameRuleSystem<UprisingRuleComponent>
{
[Dependency] private readonly SharedChatSystem _chat = default!;
[Dependency] private readonly NukeSystem _nuke = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly NavMapSystem _navMap = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly SharedObjectivesSystem _objectives = default!;
[Dependency] private readonly SharedRoleSystem _role = default!;
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[Dependency] private readonly ISharedPlayerManager _player = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LoyalistRoleComponent, GetBriefingEvent>(OnGetLoyalistBriefing);
SubscribeLocalEvent<InsurgentRoleComponent, GetBriefingEvent>(OnGetInsurgentBriefing);
SubscribeLocalEvent<UprisingVictoryObjectiveComponent, ObjectiveGetProgressEvent>(OnUprisingVictoryProgress);
SubscribeLocalEvent<UprisingConsoleComponent, GetVerbsEvent<AlternativeVerb>>(OnGetConsoleVerbs);
SubscribeLocalEvent<UprisingConsoleComponent, UprisingArmDoAfter>(OnArm);
SubscribeLocalEvent<UprisingConsoleComponent, UprisingDisarmDoAfter>(OnDisarm);
}
private void OnUprisingVictoryProgress(Entity<UprisingVictoryObjectiveComponent> ent, ref ObjectiveGetProgressEvent args)
{
if (GetRule() is not { } rule)
return;
if (rule.Comp1.SideWinsAt is var (side, _) && ent.Comp.Side == side)
args.Progress = 0.5f;
else if (rule.Comp1.SideWon == ent.Comp.Side)
args.Progress = 1f;
else
args.Progress = 0f;
}
protected override void Started(EntityUid uid, UprisingRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
component.NukeAnnouncementAt = Timing.CurTime + component.NukeAnnouncementDelay;
component.NukeTimeAt = Timing.CurTime + component.NukeTimeDelay;
component.FirstWarningAt = component.NukeTimeAt - component.FirstWarning;
component.ImpendingWarningAt = component.NukeTimeAt - component.ImpendingWarning;
component.FinalWarningAt = component.NukeTimeAt - component.FinalWarning;
}
protected override void ActiveTick(EntityUid uid, UprisingRuleComponent component, GameRuleComponent gameRule, float frameTime)
{
base.ActiveTick(uid, component, gameRule, frameTime);
if (component.NukeAnnouncementAt is { } nukeAnnouncement && nukeAnnouncement <= Timing.CurTime)
{
var time = component.NukeTimeAt.HasValue ? component.NukeTimeAt.Value - Timing.CurTime : component.NukeTimeDelay;
_chat.DispatchGlobalAnnouncement(Loc.GetString("uprising-announcement-nuke-announcement", ("time", (int)Math.Round(time.TotalMinutes))), colorOverride: Color.Gold);
component.NukeAnnouncementAt = null;
}
if (component.FirstWarningAt is { } firstWarning && firstWarning <= Timing.CurTime)
{
var time = component.NukeTimeAt.HasValue ? component.NukeTimeAt.Value - Timing.CurTime : component.FirstWarning;
_chat.DispatchGlobalAnnouncement(Loc.GetString("uprising-announcement-first-warning", ("time", (int)Math.Round(time.TotalMinutes))), colorOverride: Color.Gold);
component.FirstWarningAt = null;
}
if (component.ImpendingWarningAt is { } impendingWarning && impendingWarning <= Timing.CurTime)
{
var time = component.NukeTimeAt.HasValue ? component.NukeTimeAt.Value - Timing.CurTime : component.ImpendingWarning;
_chat.DispatchGlobalAnnouncement(Loc.GetString("uprising-announcement-impending-warning", ("time", (int)Math.Round(time.TotalMinutes))), colorOverride: Color.Gold);
component.ImpendingWarningAt = null;
}
if (component.FinalWarningAt is { } finalWarning && finalWarning <= Timing.CurTime)
{
var time = component.NukeTimeAt.HasValue ? component.NukeTimeAt.Value - Timing.CurTime : component.FinalWarning;
_chat.DispatchGlobalAnnouncement(Loc.GetString("uprising-announcement-final-warning", ("time", (int)Math.Round(time.TotalMinutes))), colorOverride: Color.Gold);
component.FinalWarningAt = null;
}
if (component.NukeTimeAt is { } nukeTime && nukeTime <= Timing.CurTime)
{
component.NukeTimeAt = null;
var query = EntityQueryEnumerator<NukeComponent>();
while (query.MoveNext(out var bombUid, out var bomb))
{
_nuke.SetRemainingTime(bombUid, component.NukeDuration, bomb);
_itemSlots.SetLock(bombUid, bomb.DiskSlot, false);
_itemSlots.TryEject(bombUid, bomb.DiskSlot, null, out _, true);
_itemSlots.SetLock(bombUid, bomb.DiskSlot, true);
_nuke.ArmBomb(bombUid, bomb, "uprising-announcement-nuke-armed");
}
}
if (component.SideWinsAt is var (winningSide, winningTime) && winningTime <= Timing.CurTime)
{
component.SideWinsAt = null;
var query = EntityQueryEnumerator<NukeComponent>();
while (query.MoveNext(out var bombUid, out var bomb))
{
_nuke.DisarmBomb(bombUid, bomb);
}
component.SideWon = winningSide;
_chat.DispatchGlobalAnnouncement(
Loc.GetString($"uprising-announcement-victory-announcement-{winningSide}"),
Loc.GetString($"uprising-announcement-victory-announcement-{winningSide}.sender"),
colorOverride: Color.FromXaml(Loc.GetString($"uprising-announcement-victory-announcement-{winningSide}.color")));
GameTicker.EndRound();
}
}
protected override void AppendRoundEndText(EntityUid uid,
UprisingRuleComponent component,
GameRuleComponent gameRule,
ref RoundEndTextAppendEvent args)
{
if (component.SideWinsAt is var (partialSide, _))
{
args.AddLine(Loc.GetString($"uprising-outcome-{partialSide}-partial"));
}
else if (component.SideWon is { } winningSide)
{
args.AddLine(Loc.GetString($"uprising-outcome-{winningSide}-full"));
}
else
{
args.AddLine(Loc.GetString("uprising-outcome-none"));
}
args.AddLine(Loc.GetString("uprising-leads"));
var antags = _antag.GetAntagIdentifiers(uid);
var leads = new HashSet<EntityUid>();
foreach (var (mind, sessionData, name) in antags)
{
leads.Add(mind);
if (_role.MindHasRole<UprisingRoleComponent>(mind, out var it))
args.AddLine(Loc.GetString($"uprising-leads-user.{it.Value.Comp2.Side}", ("name", name), ("user", sessionData.UserName)));
else
args.AddLine(Loc.GetString("uprising-leads-user.Unknown", ("name", name), ("user", sessionData.UserName)));
}
args.AddLine(string.Empty);
var lines = new Dictionary<UprisingSide, List<string>>();
foreach (var value in Enum.GetValues<UprisingSide>())
{
lines[value] = new();
}
var minds = EntityQueryEnumerator<MindComponent>();
while (minds.MoveNext(out var mindUid, out var mindComponent))
{
if (leads.Contains(mindUid))
continue;
if (!_role.MindHasRole<UprisingRoleComponent>((mindUid, mindComponent), out var role) || mindComponent.OriginalOwnerUserId is not { } owner)
continue;
if (!_player.TryGetPlayerData(owner, out var data))
continue;
lines[role.Value.Comp2.Side].Add(Loc.GetString($"uprising-members-user", ("name", mindComponent.CharacterName ?? string.Empty), ("user", data.UserName)));
}
foreach (var value in Enum.GetValues<UprisingSide>())
{
args.AddLine(Loc.GetString($"uprising-members.{value}"));
foreach (var line in lines[value])
{
args.AddLine(line);
}
args.AddLine(string.Empty);
}
}
private void OnGetLoyalistBriefing(Entity<LoyalistRoleComponent> ent, ref GetBriefingEvent args)
{
args.Append(Loc.GetString("antag-Loyalist.briefing"));
}
private void OnGetInsurgentBriefing(Entity<InsurgentRoleComponent> ent, ref GetBriefingEvent args)
{
args.Append(Loc.GetString("antag-Insurgent.briefing"));
}
private Entity<UprisingRuleComponent, GameRuleComponent>? GetRule()
{
var enumerator = QueryActiveRules();
while (enumerator.MoveNext(out var uid, out _, out var uprising, out var gamerule))
{
return (uid, uprising, gamerule);
}
return null;
}
private void StartWinning(UprisingSide side, EntityUid console)
{
if (GetRule() is not { } rule)
return;
var location = _navMap.GetNearestBeaconString(console);
var announcement = Loc.GetString($"uprising-announcement-start-victory-announcement-{side}",
("time", (int) Math.Round(rule.Comp1.SideTimes[side].TotalSeconds)),
("location", FormattedMessage.RemoveMarkupOrThrow(location)));
_chat.DispatchGlobalAnnouncement(
announcement,
Loc.GetString($"uprising-announcement-start-victory-announcement-{side}.sender"),
colorOverride: Color.FromXaml(Loc.GetString($"uprising-announcement-start-victory-announcement-{side}.color")));
rule.Comp1.SideWinsAt = (side, Timing.CurTime + rule.Comp1.SideTimes[side]);
}
private void StopWinning()
{
if (GetRule() is not { } rule || rule.Comp1.SideWinsAt is not var (side, time))
return;
rule.Comp1.SideTimes[side] = Timing.CurTime - time;
_chat.DispatchGlobalAnnouncement(
Loc.GetString($"uprising-announcement-interrupted-victory-announcement-{side}"),
Loc.GetString($"uprising-announcement-interrupted-victory-announcement-{side}.sender"),
colorOverride: Color.FromXaml(Loc.GetString($"uprising-announcement-interrupted-victory-announcement-{side}.color")));
rule.Comp1.SideWinsAt = null;
}
private void OnGetConsoleVerbs(Entity<UprisingConsoleComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
{
if (GetRule() is not { } rule)
return;
var user = args.User;
if (rule.Comp1.SideWinsAt is var (disarmSide, _))
{
args.Verbs.Add(new ()
{
Act = () => StartDisarming(ent, user),
Text = Loc.GetString($"uprising-disarm-verb.{disarmSide}"),
});
return;
}
if (!CheckCanArm(args.User, out var armSide))
return;
args.Verbs.Add(new()
{
Act = () => StartArming(ent, user),
Text = Loc.GetString($"uprising-arm-verb.{armSide}"),
});
}
private bool CheckCanArm(EntityUid user, [NotNullWhen(true)] out UprisingSide? side)
{
side = null;
if (_mind.GetMind(user) is not { } mind || !TryComp<MindComponent>(mind, out var mindComp))
return false;
if (!_role.MindHasRole<UprisingRoleComponent>(mind, out var uprisingRole))
return false;
foreach (var objective in mindComp.Objectives)
{
if (!HasComp<UprisingArmRequiredObjectiveComponent>(objective))
continue;
if (_objectives.GetProgress(objective, (mind, mindComp)) is not >= 1)
return false;
}
side = uprisingRole.Value.Comp2.Side;
return true;
}
private void StartDisarming(Entity<UprisingConsoleComponent> ent, EntityUid user)
{
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
user,
ent.Comp.Delay,
new UprisingDisarmDoAfter(),
ent.Owner));
}
private void StartArming(Entity<UprisingConsoleComponent> ent, EntityUid user)
{
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
user,
ent.Comp.Delay,
new UprisingArmDoAfter(),
ent.Owner));
}
private void OnArm(Entity<UprisingConsoleComponent> ent, ref UprisingArmDoAfter args)
{
if (args.Handled || args.Cancelled || !CheckCanArm(args.User, out var side))
return;
StartWinning(side.Value, ent);
}
private void OnDisarm(Entity<UprisingConsoleComponent> ent, ref UprisingDisarmDoAfter args)
{
if (args.Handled || args.Cancelled)
return;
StopWinning();
}
}
+124
View File
@@ -0,0 +1,124 @@
using Content.Server._DV.Psionics.Systems;
using Content.Server.Antag;
using Content.Shared._DV.Movement.Components;
using Content.Shared._DV.Psionics.Components;
using Content.Shared.CharacterInfo;
using Content.Shared.Cloning.Events;
using Content.Shared.CombatMode.Pacification;
using Content.Shared.Mobs.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.NPC.Components;
using Content.Shared.Radio.Components;
using Content.Shared.Roles.Components;
using Content.Shared.Zombies;
using Robust.Shared.Prototypes;
namespace Content.Server.Zombies;
public sealed partial class ZombieSystem
{
//private static readonly string MindRoleInitialInfected = "MindRoleInitialInfected";
private static readonly EntProtoId InitialInfectedFailureSurviveObjective = "InitialInfectedFailureSurviveObjective";
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[Dependency] private readonly PsionicSystem _psionic = default!; // DeltaV
[Dependency] private readonly SharedJetpackSystem _jetpack = default!; // DeltaV - Prevent Jetpacks on Zombies
private void InitializeDV()
{
// This needs to be done before CloneEvent or else the proper attributes won't be restored or modified on
// the new entity.
SubscribeLocalEvent<ZombieComponent, CloningAttemptEvent>(OnBeforeUnzombify);
SubscribeLocalEvent<InitialInfectedComponent, CloningEvent>(OnInitialInfectedCloning);
}
/// <summary>
/// DeltaV - Extra things we want to ensure, remove, or take care of when someone is zombified.
/// </summary>
private void ZombifyEntityDV(Entity<ZombieComponent> ent, MobStateComponent? mobState = null)
{
// Remove innate radio
RemComp<ActiveRadioComponent>(ent); // If the zombie has an innate radio, get rid of it.
// Remove headsets in pockets
for (var i = 1; i <= 4; i++) // Arachnids have 4 pockets
{
if (_inventory.TryGetSlotEntity(ent, $"pocket{i}", out var headset) && HasComp<HeadsetComponent>(headset))
_inventory.TryUnequip(ent, $"pocket{i}", true, true);
}
// Prevent Psionic Zombies
RemComp<PotentialPsionicComponent>(ent);
_psionic.MindBreakEntity(ent.Owner, false, true);
// Prevent Jetpacks on Zombies
if (TryComp<JetpackUserComponent>(ent, out var jetpackUser))
{
if (TryComp<JetpackComponent>(jetpackUser.Jetpack, out var jetpack))
_jetpack.SetEnabled(jetpackUser.Jetpack, jetpack, false, ent);
}
RemComp<AutomaticJetpackUserComponent>(ent);
// Prevent shitters biting other zombies
EnsureComp<NoFriendlyFireComponent>(ent);
}
/// <summary>
/// DeltaV - We need to save some extra things to the ZombieComponent so we can restore them when
/// they are about to be cloned.
/// </summary>
/// <param name="ent"></param>
private void PreserveEntityComponentState(Entity<ZombieComponent> ent)
{
SaveFactionsBeforeZombification(ent);
// Zombification removes pacifism but lets track if they have it so the pacifist players will be... pacified.
ent.Comp.WasPacisfistBeforeZombification = HasComp<PacifiedComponent>(ent);
}
private void SaveFactionsBeforeZombification(Entity<ZombieComponent> ent)
{
if (!TryComp<NpcFactionMemberComponent>(ent, out var faction))
return;
ent.Comp.FactionsBeforeZombification.AddRange(faction.Factions);
}
/// <summary>
/// DeltaV - Restores certain components to their previous state that the upstream unzombify doesn't handle.
/// We need to do this before CloningEvent so the cloned body will have the updated components BEFORE cloning happens.
/// </summary>
/// <param name="ent"></param>
/// <param name="args"></param>
private void OnBeforeUnzombify(Entity<ZombieComponent> ent, ref CloningAttemptEvent args)
{
// Restore factions
_faction.ClearFactions(ent.Owner); // Should only be zombie, but might as well clear the whole list in case.
ent.Comp.FactionsBeforeZombification.ForEach(previousFaction => _faction.AddFaction(ent.Owner, previousFaction));
// Restore pacifism
if (ent.Comp.WasPacisfistBeforeZombification)
EnsureComp<PacifiedComponent>(ent);
}
/// <summary>
/// DeltaV - Adds a survival objective to Initial Infected who are cloned. Chances are that the crew has recovered, so
/// bioterrorism time is probably over.
/// </summary>
/// <param name="ent"></param>
/// <param name="args"></param>
private void OnInitialInfectedCloning(Entity<InitialInfectedComponent> ent, ref CloningEvent args)
{
// Change II objectives so they no longer have infect objectives. Now, they'll have survival objectives. Live to infect another day. :)
_mind.TryGetMind(ent.Owner, out var mindId, out var mindContainer);
// If we can't find the mind, oh well. We tried.
if (mindContainer is not { } mind)
return;
if (_role.MindHasRole<InitialInfectedRoleComponent>(mindId))
_mind.TryAddObjective(mindId, mind, InitialInfectedFailureSurviveObjective);
}
}
@@ -285,6 +285,11 @@ public sealed partial class AnomalyComponent : Component
[DataField]
public bool DeleteEntity = true;
// DeltaV - Colossus additions START
[DataField]
public bool AlwaysGrow;
// DeltaV - Colossus additions END
}
/// <summary>
@@ -308,7 +313,7 @@ public readonly record struct AnomalySupercriticalEvent(EntityUid Anomaly, float
/// <param name="Anomaly">The anomaly being shut down.</param>
/// <param name="Supercritical">Whether or not the anomaly shut down passively or via a supercritical event.</param>
[ByRefEvent]
public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Supercritical);
public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Supercritical, bool Forced); // DeltaV - Add Forced
/// <summary>
/// Event broadcast when an anomaly's severity is changed.
+13 -4
View File
@@ -84,7 +84,7 @@ public abstract partial class SharedAnomalySystem : EntitySystem // DeltaV - Mad
Log.Info($"Performing anomaly pulse. Entity: {ToPrettyString(uid)}");
// if we are above the growth threshold, then grow before the pulse
if (component.Stability > component.GrowthThreshold)
if (component.AlwaysGrow || component.Stability > component.GrowthThreshold) // DeltaV - Add AlwaysGrow
{
ChangeAnomalySeverity(uid, GetSeverityIncreaseFromGrowth(component), component);
}
@@ -192,7 +192,8 @@ public abstract partial class SharedAnomalySystem : EntitySystem // DeltaV - Mad
/// <param name="supercritical">Whether or not the anomaly ended via supercritical event</param>
/// <param name="spawnCore">Create anomaly cores based on the result of completing an anomaly?</param>
/// <param name="logged">Whether or not the anomaly decaying/going supercritical is logged</param>
public void EndAnomaly(EntityUid uid, AnomalyComponent? component = null, bool supercritical = false, bool spawnCore = true, bool logged = false)
/// <param name="forced">Whether or not the anomaly shutdown was caused by component shutdown</param> // DeltaV - Add forced
public void EndAnomaly(EntityUid uid, AnomalyComponent? component = null, bool supercritical = false, bool spawnCore = true, bool logged = false, bool forced = false) // DeltaV - Add forced
{
if (logged)
{
@@ -207,7 +208,7 @@ public abstract partial class SharedAnomalySystem : EntitySystem // DeltaV - Mad
if (!Resolve(uid, ref component))
return;
var ev = new AnomalyShutdownEvent(uid, supercritical);
var ev = new AnomalyShutdownEvent(uid, supercritical, forced); // DeltaV - Add forced
RaiseLocalEvent(uid, ref ev, true);
if (Terminating(uid) || _net.IsClient)
@@ -345,7 +346,7 @@ public abstract partial class SharedAnomalySystem : EntitySystem // DeltaV - Mad
// if the stability is under the death threshold,
// update it every second to start killing it slowly.
if (anomaly.Stability < anomaly.DecayThreshold)
if (!anomaly.AlwaysGrow && anomaly.Stability < anomaly.DecayThreshold) // DeltaV - Add AlwaysGrow
{
ChangeAnomalyHealth(ent, anomaly.HealthChangePerSecond * frameTime, anomaly);
}
@@ -479,6 +480,14 @@ public abstract partial class SharedAnomalySystem : EntitySystem // DeltaV - Mad
if (!Resolve(ent, ref ent.Comp, logMissing: false))
return false;
// DeltaV - Colossus Additions START
if (ent.Comp.AlwaysGrow)
{
visual = AnomalyStabilityVisuals.Growing;
return true;
}
// DeltaV - Colossus Additions END
visual = AnomalyStabilityVisuals.Stable;
if (ent.Comp.Stability <= ent.Comp.DecayThreshold)
{
+6
View File
@@ -135,4 +135,10 @@ public sealed partial class CCVars
/// </summary>
public static readonly CVarDef<int> AdminOverlayStackMax =
CVarDef.Create("ui.admin_overlay_stack_max", 3, CVar.CLIENTONLY | CVar.ARCHIVE);
/// <summary>
/// If true, ghosts will see an "(F)" button next to chat messages, which can be used to follow the sender.
/// </summary>
public static readonly CVarDef<bool> InterfaceChatFollowButton =
CVarDef.Create("ui.chat_follow_button", true, CVar.CLIENT | CVar.REPLICATED | CVar.ARCHIVE);
}
+14
View File
@@ -53,6 +53,20 @@ namespace Content.Shared.Chat
AudioPath = audioPath;
AudioVolume = audioVolume;
}
public ChatMessage(ChatMessage copyFrom)
{
Channel = copyFrom.Channel;
Message = copyFrom.Message;
WrappedMessage = copyFrom.WrappedMessage;
SenderEntity = copyFrom.SenderEntity;
SenderKey = copyFrom.SenderKey;
HideChat = copyFrom.HideChat;
MessageColorOverride = copyFrom.MessageColorOverride;
AudioPath = copyFrom.AudioPath;
AudioVolume = copyFrom.AudioVolume;
Read = copyFrom.Read;
}
}
/// <summary>
@@ -30,6 +30,11 @@ public sealed class InteractUsingEvent : HandledEntityEventArgs
/// </summary>
public EntityCoordinates ClickLocation { get; }
/// <summary>
/// Stellar - set to false if this interaction shouldn't have an interaction particle
/// </summary>
public bool InteractionParticle = true;
public InteractUsingEvent(EntityUid user, EntityUid used, EntityUid target, EntityCoordinates clickLocation)
{
// Interact using should not have the same used and target.
@@ -31,6 +31,7 @@ using Content.Shared.UserInterface;
using Content.Shared.Verbs;
using Content.Shared.Wall;
using Content.Shared._Goobstation.DoAfter; // Goobstation
using Content.Shared.Inventory.VirtualItem; // Stellar - interaction particles
using JetBrains.Annotations;
using Robust.Shared.Containers;
using Robust.Shared.Input;
@@ -1073,8 +1074,8 @@ namespace Content.Shared.Interaction
var userInteractUsingEvent = new UserInteractUsingEvent(user, used, target, clickLocation);
RaiseLocalEvent(user, userInteractUsingEvent, true);
DoContactInteraction(user, used, null, true, interactUsingEvent); // Stellar - interaction particles
DoContactInteraction(user, target, used, true, interactUsingEvent); // Stellar - interaction particles
DoContactInteraction(user, used, null, true, interactUsingEvent, interactionParticles: interactUsingEvent.InteractionParticle); // Stellar - interaction particles
DoContactInteraction(user, target, used, true, interactUsingEvent, interactionParticles: interactUsingEvent.InteractionParticle); // Stellar - interaction particles
// Contact interactions are currently only used for forensics, so we don't raise used -> target
if (interactUsingEvent.Handled || userInteractUsingEvent.Handled)
return true;
@@ -1437,7 +1438,8 @@ namespace Content.Shared.Interaction
/// <param name="predicted">Whether this interaction is predicted. <see cref="uidA"/> is assumed to be the client entity.</param>
/// <param name="args">Optional handleable entity event to check.</param>
/// <param name="interactionParticles">Whether to spawn interaction particles on this contact.</param>
public void DoContactInteraction(EntityUid uidA, EntityUid? uidB, EntityUid? used, bool predicted, HandledEntityEventArgs? args = null, bool interactionParticles = true) // Stellar/ES - interaction particles
/// <param name="interactionParticleType">The type of interaction particle to spawn for this event.</param>
public void DoContactInteraction(EntityUid uidA, EntityUid? uidB, EntityUid? used, bool predicted, HandledEntityEventArgs? args = null, bool interactionParticles = true, StellarInteractionParticleType interactionParticleType = StellarInteractionParticleType.Use) // Stellar/ES - interaction particles
{
if (uidB == null || args?.Handled == false)
return;
@@ -1459,7 +1461,7 @@ namespace Content.Shared.Interaction
RaiseLocalEvent(uidB.Value, ev);
// Begin Stellar/ES Additions - Interaction particles
if (!interactionParticles)
if (!interactionParticles || HasComp<VirtualItemComponent>(uidB))
return;
if (_net.IsServer)
@@ -1468,11 +1470,11 @@ namespace Content.Shared.Interaction
? Filter.PvsExcept(uidA, entityManager: EntityManager)
: Filter.Pvs(uidA, entityManager: EntityManager);
RaiseNetworkEvent(new StellarInteractionParticleEvent(GetNetEntity(uidA), GetNetEntity(used), GetNetEntity(uidB.Value), false), filter);
RaiseNetworkEvent(new StellarInteractionParticleEvent(GetNetEntity(uidA), GetNetEntity(used), GetNetEntity(uidB.Value), false, interactionParticleType), filter);
}
else if (_gameTiming.IsFirstTimePredicted)
{
var evt = new StellarInteractionParticleEvent(GetNetEntity(uidA), GetNetEntity(used), GetNetEntity(uidB.Value), true);
var evt = new StellarInteractionParticleEvent(GetNetEntity(uidA), GetNetEntity(used), GetNetEntity(uidB.Value), true, interactionParticleType);
RaiseLocalEvent(evt);
}
// End Stellar/ES Additions - Interaction particles
+5
View File
@@ -122,6 +122,11 @@ public sealed class MindExamineSystem : EntitySystem
else
ent.Comp.State = MindState.None;
// DeltaV - SSD Recency START
var ev = new MindStateUpdatedEvent(ent.Comp.State);
RaiseLocalEvent(ent, ref ev);
// DeltaV END
Dirty(ent);
}
}
@@ -1,3 +1,4 @@
using Content.Shared._ST.Interaction; // Stellar - interaction particles
using Content.Shared.ActionBlocker;
using Content.Shared.Administration.Logs;
using Content.Shared.Alert;
@@ -545,7 +546,7 @@ public sealed class PullingSystem : EntitySystem
// Pulling confirmed
_interaction.DoContactInteraction(pullableUid, pullerUid, null, true); // Stellar - Interaction particles
_interaction.DoContactInteraction(pullerUid, pullableUid,null, true, interactionParticleType: StellarInteractionParticleType.Pull); // Stellar - Interaction particles
// Use net entity so it's consistent across client and server.
pullableComp.PullJointId = $"pull-joint-{GetNetEntity(pullableUid)}";
+3 -1
View File
@@ -18,11 +18,13 @@ public sealed partial class RatKingComponent : Component
[DataField("actionRaiseArmyEntity")]
public EntityUid? ActionRaiseArmyEntity;
// Delta-V - switched to a base cost modified by the amount of living servants
/// <summary>
/// The amount of hunger one use of Raise Army consumes
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("hungerPerArmyUse", required: true)]
public float HungerPerArmyUse = 25f;
public float HungerPerArmyUse = 10f;
// end DeltaV
/// <summary>
/// The entity prototype of the mob that Raise Army summons
@@ -50,11 +50,12 @@ public sealed partial class SSDIndicatorComponent : Component
// DeltaV - SSD Recency Additions START
/// <summary>
/// The time at which the Entity became SSD.
/// The time at which the player became SSD.
/// This will remain unset on SSD entities that never had minds attached, such as newly spawn ghost roles.
/// </summary>
[AutoNetworkedField, AutoPausedField]
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan SsdSince = TimeSpan.Zero;
public TimeSpan? SsdSince;
/// <summary>
/// The icon displayed next to the associated entity when it is recently SSD (stage 2).
@@ -1,6 +1,9 @@
using Content.Shared._DV.CCVars; // DeltaV - SSD Recency
using Content.Shared._DV.Mind; // DeltaV - SSD Recency
using Content.Shared.CCVar;
using Content.Shared.Examine; // DeltaV - SSD Recency
using Content.Shared.Mobs.Systems; // DeltaV - SSD Recency
using Content.Shared.Mind.Components; // DeltaV - SSD Recency
using Content.Shared.StatusEffectNew;
using Robust.Shared.Configuration;
using Robust.Shared.Player;
@@ -19,18 +22,20 @@ public sealed class SSDIndicatorSystem : EntitySystem
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
[Dependency] private readonly MobStateSystem _mobState = default!; // DeltaV - SSD Recency
private bool _icSsdSleep;
private float _icSsdSleepTime;
private TimeSpan _cryoableSsdSeconds; // DeltaV
private TimeSpan _recentSsdSeconds; // DeltaV
private TimeSpan _cryoableSsdSeconds; // DeltaV - SSD Recency
private TimeSpan _recentSsdSeconds; // DeltaV - SSD Recency
public override void Initialize()
{
SubscribeLocalEvent<SSDIndicatorComponent, PlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<SSDIndicatorComponent, PlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<SSDIndicatorComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<SSDIndicatorComponent, MindStateUpdatedEvent>(OnMindStateUpdated); // DeltaV - SSD Recency
_cfg.OnValueChanged(CCVars.ICSSDSleep, obj => _icSsdSleep = obj, true);
_cfg.OnValueChanged(CCVars.ICSSDSleepTime, obj => _icSsdSleepTime = obj, true);
@@ -43,12 +48,15 @@ public sealed class SSDIndicatorSystem : EntitySystem
// DeltaV - SSD Recency START
private void OnExamine(Entity<SSDIndicatorComponent> ent, ref ExaminedEvent args)
{
if (!ent.Comp.IsSSD)
if (ent.Comp.SsdSince is not { } ssdSince)
return;
if (_mobState.IsDead(ent))
return;
using (args.PushGroup(nameof(SSDIndicatorComponent)))
{
var timestamp = (_timing.CurTime - ent.Comp.SsdSince).ToString("%hh':'mm':'ss");
var timestamp = (_timing.CurTime - ssdSince).ToString("%hh':'mm':'ss");
args.PushMarkup(Loc.GetString("ssd-examine-duration", ("time", timestamp)));
args.PushMarkup(Loc.GetString($"ssd-examine-{GetStage(ent).ToString().ToLower()}"));
}
@@ -58,17 +66,28 @@ public sealed class SSDIndicatorSystem : EntitySystem
{
var curTime = _timing.CurTime;
if (ent.Comp.SsdSince + _cryoableSsdSeconds < curTime)
if (ent.Comp.SsdSince + _recentSsdSeconds >= curTime)
{
return SsdStage.Cryoable;
return SsdStage.VeryRecent;
}
if (ent.Comp.SsdSince + _recentSsdSeconds < curTime)
if (ent.Comp.SsdSince + _cryoableSsdSeconds >= curTime)
{
return SsdStage.Recent;
}
return SsdStage.VeryRecent;
return SsdStage.Cryoable;
}
public void OnMindStateUpdated(Entity<SSDIndicatorComponent> ent, ref MindStateUpdatedEvent args)
{
if (args.State is MindState.SSD or MindState.DeadSSD) {
if (ent.Comp.SsdSince is null)
ent.Comp.SsdSince = _timing.CurTime;
}
else
ent.Comp.SsdSince = null;
Dirty(ent, ent.Comp);
}
// DeltaV END
@@ -96,8 +115,6 @@ public sealed class SSDIndicatorSystem : EntitySystem
component.FallAsleepTime = _timing.CurTime + TimeSpan.FromSeconds(_icSsdSleepTime);
}
component.SsdSince = _timing.CurTime; // DeltaV - SSD Recency
Dirty(uid, component);
}
@@ -62,6 +62,7 @@ public abstract class SharedEmitSoundSystem : EntitySystem
if (_whitelistSystem.IsWhitelistFail(component.Blacklist, args.User))
{
TryEmitSound(uid, component, args.User);
args.InteractionParticle = true; // Stellar - interaction particles
}
}
@@ -106,6 +106,7 @@ public abstract partial class SharedStackSystem : EntitySystem
var localRotation = Transform(args.Used).LocalRotation;
_storage.PlayPickupAnimation(args.Used, popupPos, userCoords, localRotation, args.User);
args.InteractionParticle = false; // Stellar
}
/// <summary>
@@ -0,0 +1,14 @@
using Content.Shared.Actions;
using Content.Shared.Roles.Components;
using Robust.Shared.Prototypes;
namespace Content.Shared.Uprising;
public sealed partial class ConversionAcceptActionEvent : InstantActionEvent
{
[DataField(required: true)]
public EntProtoId MindRole;
[DataField(required: true)]
public EntProtoId<MindRoleComponent> RemoveMindRole;
}
@@ -0,0 +1,33 @@
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Roles;
using Robust.Shared.Network;
namespace Content.Shared.Uprising;
public sealed class ConversionAcceptActionSystem : EntitySystem
{
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly SharedRoleSystem _role = default!;
[Dependency] private readonly INetManager _net = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MindContainerComponent, ConversionAcceptActionEvent>(OnAcceptConversion);
}
private void OnAcceptConversion(Entity<MindContainerComponent> ent, ref ConversionAcceptActionEvent args)
{
if (_mind.GetMind(ent) is not { } mind)
return;
args.Handled = true;
if (_net.IsServer)
{
_role.MindAddRole(mind, args.MindRole);
_role.MindRemoveRole(mind, args.RemoveMindRole);
}
}
}
@@ -0,0 +1,13 @@
using Content.Shared.Actions;
using Robust.Shared.Prototypes;
namespace Content.Shared.Uprising;
public sealed partial class ConversionOfferActionEvent : EntityTargetActionEvent
{
[DataField(readOnly: true)]
public List<Type> IncompatibleMindRoleTypes;
[DataField]
public EntProtoId AcceptAction;
}
@@ -0,0 +1,35 @@
using Content.Shared.Actions;
using Content.Shared.Mind;
using Content.Shared.Roles;
using Content.Shared.Roles.Components;
namespace Content.Shared.Uprising;
public sealed class ConversionOfferActionSystem : EntitySystem
{
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly SharedRoleSystem _role = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MindRoleComponent, ConversionOfferActionEvent>(OnOffer);
}
private void OnOffer(Entity<MindRoleComponent> ent, ref ConversionOfferActionEvent args)
{
if (_mind.GetMind(args.Target) is not { } mind)
return;
foreach (var incompatible in args.IncompatibleMindRoleTypes)
{
if (_role.MindHasRole(mind, incompatible, out _))
return;
}
_actions.AddAction(args.Target, args.AcceptAction);
args.Handled = true;
}
}
@@ -52,6 +52,11 @@ public sealed class AfterActivatableUIOpenEvent(EntityUid user) : EntityEventArg
/// The player that opened the UI.
/// </summary>
public readonly EntityUid User = user;
/// <summary>
/// Stellar - if an interaction particle should be played for this event.
/// </summary>
public bool InteractionParticle;
}
/// <summary>
@@ -21,6 +21,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
public override void Initialize()
{
@@ -72,7 +73,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
args.Verbs.Add(new ActivationVerb
{
Act = () => InteractUI(args.User, uid, component),
Act = () => InteractUI(args.User, (uid, component)), // Stellar - interaction particles
Text = Loc.GetString(component.VerbText),
// TODO VERB ICON find a better icon
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/settings.svg.192dpi.png")),
@@ -86,7 +87,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
args.Verbs.Add(new Verb
{
Act = () => InteractUI(args.User, uid, component),
Act = () => InteractUI(args.User, (uid, component)), // Stellar - interaction particles
Text = Loc.GetString(component.VerbText),
// TODO VERB ICON find a better icon
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/settings.svg.192dpi.png")),
@@ -133,7 +134,8 @@ public sealed partial class ActivatableUISystem : EntitySystem
if (component.RequiredItems != null)
return;
args.Handled = InteractUI(args.User, uid, component);
var interactionParticle = false; // Stellar - interaction particles
args.Handled = InteractUI(args.User, uid, component, ref interactionParticle); // Stellar - interaction particles
}
private void OnActivate(EntityUid uid, ActivatableUIComponent component, ActivateInWorldEvent args)
@@ -147,7 +149,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
if (component.RequiredItems != null)
return;
args.Handled = InteractUI(args.User, uid, component);
args.Handled = InteractUI(args.User, uid, component, ref args.InteractionParticle); // Stellar - interaction particles
}
private void OnInteractUsing(EntityUid uid, ActivatableUIComponent component, InteractUsingEvent args)
@@ -164,7 +166,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
if (_whitelistSystem.IsWhitelistFail(component.RequiredItems, args.Used))
return;
args.Handled = InteractUI(args.User, uid, component);
args.Handled = InteractUI(args.User, uid, component, ref args.InteractionParticle); // Stellar - interaction particles
}
private void OnUIClose(EntityUid uid, ActivatableUIComponent component, BoundUIClosedEvent args)
@@ -180,13 +182,23 @@ public sealed partial class ActivatableUISystem : EntitySystem
SetCurrentSingleUser(uid, null, component);
}
private bool InteractUI(EntityUid user, EntityUid uiEntity, ActivatableUIComponent aui)
// Begin Stellar - interaction particles
private void InteractUI(EntityUid user, Entity<ActivatableUIComponent> ui)
{
var interactionParticle = false;
InteractUI(user, ui, ui, ref interactionParticle);
_interaction.DoContactInteraction(user, ui, null, true, interactionParticles: interactionParticle);
}
// End Stellar - interaction particles
private bool InteractUI(EntityUid user, EntityUid uiEntity, ActivatableUIComponent aui, ref bool interactionParticle) // Stellar - interaction particles
{
if (aui.Key == null || !_uiSystem.HasUi(uiEntity, aui.Key))
return false;
if (_uiSystem.IsUiOpen(uiEntity, aui.Key, user))
{
interactionParticle = false; // Stellar - interaction particles
_uiSystem.CloseUi(uiEntity, aui.Key, user);
return true;
}
@@ -243,6 +255,8 @@ public sealed partial class ActivatableUISystem : EntitySystem
var aae = new AfterActivatableUIOpenEvent(user);
RaiseLocalEvent(uiEntity, aae);
interactionParticle = aae.InteractionParticle; // Stellar
return true;
}
@@ -31,6 +31,7 @@ using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Weapons.Ranged.Systems;
using Content.Shared.Wieldable.Components; // Starlight | ES Screenshake
using Content.Shared.Zombies; // DeltaV - Buff Zombies
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
@@ -597,18 +598,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
if (damageResult.GetTotal() > FixedPoint2.Zero)
{
DoDamageEffect(targets, user, targetXform);
// ES START
// dog shit copy plaste but thats melee for you
var userShakeRotation = new ESScreenshakeParameters()
{ Trauma = 0.08f, DecayRate = 1.0f, Frequency = 0.009f };
var otherShakeTranslation = new ESScreenshakeParameters() { Trauma = 0.45f, DecayRate = 1.1f, Frequency = 0.04f };
_shake.Screenshake(user, null, userShakeRotation);
foreach (var shakeTarget in targets)
{
_shake.Screenshake(shakeTarget, otherShakeTranslation, null);
}
// ES END
DoScreenshake(meleeUid, damageResult, user, targets); // Starlight | ES Screenshake
}
}
@@ -774,21 +764,10 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
_meleeSound.PlayHitSound(target, user, GetHighestDamageSound(appliedDamage, _protoManager), hitEvent.HitSoundOverride, component);
}
// ES START
// dog shit copy plaste but thats melee for you
var userShakeRotation = new ESScreenshakeParameters()
{ Trauma = 0.08f, DecayRate = 1.0f, Frequency = 0.009f };
var otherShakeTranslation = new ESScreenshakeParameters() { Trauma = 0.45f, DecayRate = 1.1f, Frequency = 0.04f };
_shake.Screenshake(user, null, userShakeRotation);
foreach (var shakeTarget in targets)
{
_shake.Screenshake(shakeTarget, otherShakeTranslation, null);
}
// ES END
if (appliedDamage.GetTotal() > FixedPoint2.Zero)
{
DoDamageEffect(targets, user, Transform(targets[0]));
DoScreenshake(meleeUid, damage, user, targets); // Starlight | ES Screenshake
}
return true;
@@ -1104,4 +1083,55 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
}
}
}
//Starlight begin | ES Screenshake
private void DoScreenshake(EntityUid weapon, DamageSpecifier damage, EntityUid attacker, List<EntityUid> targets)
{
if(damage.GetTotal()>4) // only show to others if it hurts real bad // DeltaV - reduce from 8 to 4
{
var otherTranslation = new ESScreenshakeParameters
{
Trauma = 0.45f,
DecayRate = 1.1f,
Frequency = 0.04f,
};
foreach(var target in targets)
_shake.Screenshake(target, otherTranslation, null);
}
// only show to attacker if they put real oompf into it, or the weapon is just THAT strong
// var bluntRequirement = damage.DamageDict.TryGetValue(BluntDamageName, out var blunt) && blunt >= 20; // DeltaV - unused
var isWielding = TryComp<WieldableComponent>(weapon, out var wieldable) && wieldable.Wielded;
// DeltaV - unused
// if (!bluntRequirement && !wieldRequirement)
// return;
// DeltaV - heavy/light screenshake variants START
ESScreenshakeParameters userRotation;
if (damage.GetTotal() >= 15 || isWielding)
{
// heavy damage or two-handed
userRotation = new ESScreenshakeParameters
{
Trauma = 0.08f,
DecayRate = 1,
Frequency = 0.009f,
};
}
else
{
// light damage
userRotation = new ESScreenshakeParameters
{
Trauma = 0.06f,
DecayRate = 1,
Frequency = 0.0045f,
};
}
// DeltaV END
_shake.Screenshake(attacker, null, userRotation);
}
//Starlight end
}
@@ -0,0 +1,6 @@
using Robust.Shared.GameStates;
namespace Content.Shared._DV.Actions;
[RegisterComponent, NetworkedComponent]
public sealed partial class DeleteOnPerformedActionComponent : Component;
@@ -0,0 +1,18 @@
using Content.Shared.Actions.Events;
namespace Content.Shared._DV.Actions;
public sealed class DeleteOnPerformedActionSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DeleteOnPerformedActionComponent, ActionPerformedEvent>(OnActionPerformed);
}
private void OnActionPerformed(Entity<DeleteOnPerformedActionComponent> ent, ref ActionPerformedEvent args)
{
PredictedQueueDel(ent);
}
}
@@ -1,3 +1,5 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
@@ -36,6 +38,8 @@ public sealed partial class CosmicColossusComponent : Component
[DataField] public EntProtoId Attack1Vfx = "CosmicColossusAttack1Vfx";
[DataField] public EntProtoId BuffVfx = "ColossusBuffVfx";
[DataField] public EntProtoId TileDetonations = "MobTileDamageZone";
[DataField] public EntProtoId EffigyPrototype = "CosmicEffigy";
@@ -52,13 +56,23 @@ public sealed partial class CosmicColossusComponent : Component
[DataField] public TimeSpan HibernationWait = TimeSpan.FromSeconds(30);
[DataField] public TimeSpan DeathWait = TimeSpan.FromMinutes(15);
[DataField] public TimeSpan DeathWaitSpawn = TimeSpan.FromMinutes(15);
[DataField] public TimeSpan DeathWaitEffigy = TimeSpan.FromMinutes(10);
[DataField] public bool Attacking;
[DataField] public bool Hibernating;
[DataField] public bool Timed;
[DataField] public short CompletedEffigies;
[DataField] public short MaxEffigies = 3;
[DataField] public DamageSpecifier BonusDamage = new();
}
[Serializable, NetSerializable]
@@ -0,0 +1,6 @@
namespace Content.Shared._DV.Mind;
using Content.Shared.Mind.Components;
[ByRefEvent]
public record struct MindStateUpdatedEvent(MindState State);
@@ -1,3 +1,4 @@
using Content.Shared.ActionBlocker;
using Content.Shared._DV.Movement.Components;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Events;
@@ -7,12 +8,19 @@ namespace Content.Shared.Movement.Systems;
public abstract partial class SharedJetpackSystem
{
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
private void OnJetpackToggle(Entity<JetpackComponent> jetpack, ref ToggleJetpackEvent args)
{
if (args.Handled)
return;
if (!_actionBlocker.CanComplexInteract(args.Performer))
{
_popup.PopupClient(Loc.GetString("jetpack-too-complex"), jetpack, args.Performer);
return;
}
jetpack.Comp.AutomaticMode = !jetpack.Comp.AutomaticMode;
jetpack.Comp.AutomaticUser = args.Performer;
Dirty(jetpack);
+3
View File
@@ -42,6 +42,9 @@ public sealed class PagerSystem : EntitySystem
private void OnAfterInteract(Entity<PagerComponent> ent, ref AfterInteractEvent args)
{
if (!args.CanReach)
return;
if (args.Handled || !TryComp<DeviceNetworkComponent>(args.Target, out var targetNetwork) || !HasComp<PageSenderComponent>(args.Target))
return;
@@ -1,13 +0,0 @@
using Robust.Shared.GameStates;
namespace Content.Shared._DV.Psionics.Components.PsionicPowers;
[RegisterComponent, NetworkedComponent]
public sealed partial class FracturedFormBodyComponent : Component
{
/// <summary>
/// The entity uid of the form that is currently being controlled.
/// </summary>
[DataField]
public EntityUid ControllingForm { get; set; }
}
@@ -1,124 +0,0 @@
using Content.Shared.Cloning;
using Content.Shared.Roles;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._DV.Psionics.Components.PsionicPowers;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
public sealed partial class FracturedFormPowerComponent : BasePsionicPowerComponent
{
public override EntProtoId ActionProtoId { get; set; } = "ActionFracturedForm";
public override string PowerName { get; set; } = "psionic-power-name-fractured-form";
public override int MinGlimmerChanged { get; set; } = 5;
public override int MaxGlimmerChanged { get; set; } = 15;
/// <summary>
/// The chance for the clone to have the starting gear of the psionic.
/// </summary>
[DataField]
public float HasGearChance = 0.4f;
/// <summary>
/// The chance for the clone to have a different species than the psionic.
/// </summary>
[DataField]
public float DifferentSpeciesChance = 0.6f;
/// <summary>
/// These are settings for creating the second body.
/// </summary>
[DataField]
public ProtoId<CloningSettingsPrototype> CopyNaked = "CloningPod";
/// <summary>
/// These are settings for creating the second body.
/// </summary>
[DataField]
public ProtoId<CloningSettingsPrototype> CopyClothed = "Antag";
/// <summary>
/// These are settings for creating the second body.
/// </summary>
[DataField]
public ProtoId<JobPrototype> VisitorJob = "Passenger";
/// <summary>
/// These are settings for creating the second body.
/// </summary>
[DataField]
public ProtoId<JobPrototype>? NakedJob; // Scary null, but we explicitly want no job for naked spawns.
/// <summary>
/// The minimum time between forced swaps.
/// </summary>
[DataField]
public TimeSpan NextSwapMinTime = TimeSpan.FromMinutes(5);
/// <summary>
/// The maximum time between swaps.
/// </summary>
[DataField]
public TimeSpan NextSwapMaxTime = TimeSpan.FromMinutes(20);
/// <summary>
/// The current timer for when the next swap is forced.
/// </summary>
[DataField, AutoPausedField]
public TimeSpan NextSwap = TimeSpan.FromMinutes(5);
/// <summary>
/// The minimum time between voluntary swaps by sleeping.
/// </summary>
[DataField]
public TimeSpan VoluntarySwapCooldown = TimeSpan.FromSeconds(10);
/// <summary>
/// The minimum time between voluntary swaps by sleeping.
/// </summary>
[DataField, AutoPausedField]
public TimeSpan NextVoluntarySwap = TimeSpan.FromSeconds(10);
/// <summary>
/// The length of the DoAfter for swapping bodies.
/// </summary>
[DataField]
public float ManualSwapTime = 5f;
/// <summary>
/// The time the psionic needs to be asleep to swap bodies.
/// </summary>
[DataField]
public TimeSpan SwapTimeAsleep = TimeSpan.FromSeconds(3);
/// <summary>
/// The time length where the warning is sent before the forced swap.
/// </summary>
[DataField]
public TimeSpan WarningTimeBeforeSleep = TimeSpan.FromSeconds(5);
/// <summary>
/// A boolean check for when the person has been warned.
/// </summary>
[DataField]
public bool SleepWarned;
/// <summary>
/// The bodies that the psionic user can swap into.
/// </summary>
[DataField, AutoNetworkedField]
public List<EntityUid> Bodies { get; set; } = [];
/// <summary>
/// The sound that plays when the swap happens.
/// </summary>
[DataField]
public SoundSpecifier SwapSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg")
{
Params = AudioParams.Default.WithVariation(0.05f),
};
}
@@ -1,5 +0,0 @@
using Content.Shared.Actions;
namespace Content.Shared._DV.Psionics.Events.PowerActionEvents;
public sealed partial class FracturedFormPowerActionEvent : InstantActionEvent;
@@ -1,7 +0,0 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;
namespace Content.Shared._DV.Psionics.Events.PowerDoAfterEvents;
[Serializable, NetSerializable]
public sealed partial class FracturedFormDoAfterEvent : SimpleDoAfterEvent;
@@ -1,150 +0,0 @@
using Content.Shared._DV.Psionics.Components.PsionicPowers;
using Content.Shared._DV.Psionics.Events;
using Content.Shared._DV.Psionics.Events.PowerActionEvents;
using Content.Shared._DV.Psionics.Events.PowerDoAfterEvents;
using Content.Shared.Bed.Sleep;
using Content.Shared.Chat;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Popups;
using Content.Shared.SSDIndicator;
using Robust.Shared.Player;
namespace Content.Shared._DV.Psionics.Systems.PsionicPowers;
public abstract class SharedFracturedFormPowerSystem : BasePsionicPowerSystem<FracturedFormPowerComponent, FracturedFormPowerActionEvent>
{
[Dependency] protected readonly SharedChatSystem Chat = default!;
[Dependency] protected readonly MobStateSystem MobState = default!;
[Dependency] protected readonly SleepingSystem Sleeping = default!;
protected EntityQuery<FracturedFormPowerComponent> FracturedQuery;
private EntityQuery<ForcedSleepingStatusEffectComponent> _forcedSleepQuery;
protected EntityQuery<MindContainerComponent> MindContainerQuery;
private EntityQuery<MobStateComponent> _mobStateQuery;
protected EntityQuery<SSDIndicatorComponent> SsdQuery;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<FracturedFormPowerComponent, FracturedFormDoAfterEvent>(OnDoAfter);
SubscribeLocalEvent<FracturedFormBodyComponent, PlayerDetachedEvent>(OnPlayerDetached, after: [typeof(SSDIndicatorSystem)]);
SubscribeLocalEvent<FracturedFormBodyComponent, ExaminedEvent>(OnExamine);
FracturedQuery = GetEntityQuery<FracturedFormPowerComponent>();
_forcedSleepQuery = GetEntityQuery<ForcedSleepingStatusEffectComponent>();
MindContainerQuery = GetEntityQuery<MindContainerComponent>();
_mobStateQuery = GetEntityQuery<MobStateComponent>();
SsdQuery = GetEntityQuery<SSDIndicatorComponent>();
}
protected override void OnPowerUsed(Entity<FracturedFormPowerComponent> psionic, ref FracturedFormPowerActionEvent args)
{
if (!CanSwap(psionic))
{
Popup.PopupClient(Loc.GetString("psionic-power-fractured-form-nobodies"), psionic, args.Performer, PopupType.Large);
return;
}
Chat.TryEmoteWithChat(psionic.Owner, "Yawn");
Popup.PopupClient(Loc.GetString("psionic-power-fractured-form-sleepy"), psionic, args.Performer, PopupType.LargeCaution);
var doAfterArgs = new DoAfterArgs(EntityManager, args.Performer, psionic.Comp.ManualSwapTime, new FracturedFormDoAfterEvent(), psionic);
if (!DoAfter.TryStartDoAfter(doAfterArgs, out var doAfterId))
return;
psionic.Comp.SaveDoAfterId(doAfterId.Value);
Dirty(psionic);
AfterPowerUsed(psionic, args.Performer);
}
private void OnDoAfter(Entity<FracturedFormPowerComponent> psionic, ref FracturedFormDoAfterEvent args)
{
if (args.Cancelled || args.Handled)
return;
args.Handled = true;
psionic.Comp.RemoveSavedDoAfterId();
Dirty(psionic);
Sleeping.TrySleeping(psionic.Owner);
}
private void OnPlayerDetached(Entity<FracturedFormBodyComponent> body, ref PlayerDetachedEvent args)
{
if (!SsdQuery.TryComp(body, out var comp)
|| FracturedQuery.HasComp(body))
return;
comp.IsSSD = false;
}
private void OnExamine(Entity<FracturedFormBodyComponent> psionic, ref ExaminedEvent args)
{
if (HasComp<FracturedFormPowerComponent>(psionic))
return;
if (TryComp<FracturedFormPowerComponent>(args.Examiner, out var fracturedHost) && fracturedHost.Bodies.Contains(psionic.Owner))
args.PushMarkup($"[color=yellow]{Loc.GetString("psionic-power-fractured-form-examine-self", ("ent", psionic))}[/color]");
else
args.PushMarkup($"[color=yellow]{Loc.GetString("psionic-power-fractured-form-ssd", ("ent", psionic))}[/color]");
}
/// <summary>
/// We're overriding the dispelled method to introduce some special behavior.
/// </summary>
protected override void OnDispelled(Entity<FracturedFormPowerComponent> psionic, ref DispelledEvent args)
{
if (args.Handled)
return;
args.Handled = true;
// This resets the swap timer.
var randomTime = Random.Next(psionic.Comp.NextSwapMinTime, psionic.Comp.NextSwapMaxTime);
psionic.Comp.NextSwap = Timing.CurTime + randomTime;
if (psionic.Comp.GetDoAfterId() is not { } doAfterId)
{
Popup.PopupClient(Loc.GetString("psionic-power-fractured-form-dispelled"), psionic, PopupType.MediumCaution);
return;
}
DoAfter.Cancel(doAfterId);
Popup.PopupClient(Loc.GetString("psionic-dispelled"), psionic, PopupType.MediumCaution);
psionic.Comp.RemoveSavedDoAfterId();
}
protected bool IsValidBody(Entity<FracturedFormPowerComponent> psionic, EntityUid otherBody)
{
if (otherBody == psionic.Owner)
return false;
if (!psionic.Comp.Bodies.Contains(otherBody))
return false;
if (!MindContainerQuery.TryComp(otherBody, out var cmind))
return false;
if (cmind.HasMind)
return false;
if (_forcedSleepQuery.HasComp(otherBody))
return false;
if (!_mobStateQuery.TryComp(otherBody, out var mobState))
return false;
if (MobState.IsIncapacitated(otherBody, mobState))
return false;
return true;
}
public bool CanSwap(Entity<FracturedFormPowerComponent> psionic)
{
foreach (var body in psionic.Comp.Bodies)
{
if (IsValidBody(psionic, body))
return true;
}
return false;
}
}
@@ -0,0 +1,36 @@
using Content.Shared.Actions;
using Content.Shared.Mind;
using Robust.Shared.Containers;
using Robust.Shared.Network;
namespace Content.Shared._DV.Roles;
public sealed class ActionGrantRoleSystem : EntitySystem
{
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ActionGrantRoleComponent, EntGotInsertedIntoContainerMessage>(OnGotInserted);
SubscribeLocalEvent<ActionGrantRoleComponent, EntGotRemovedFromContainerMessage>(OnGotRemoved);
}
private void OnGotInserted(Entity<ActionGrantRoleComponent> ent, ref EntGotInsertedIntoContainerMessage args)
{
if (_net.IsClient || !TryComp<MindComponent>(args.Container.Owner, out var mind) || mind.CurrentEntity is not { } mindContainer)
return;
_actions.GrantContainedActions(mindContainer, ent.Owner);
}
private void OnGotRemoved(Entity<ActionGrantRoleComponent> ent, ref EntGotRemovedFromContainerMessage args)
{
if (_net.IsClient || !TryComp<MindComponent>(args.Container.Owner, out var mind) || mind.CurrentEntity is not { } mindContainer)
return;
_actions.RemoveProvidedActions(mindContainer, ent.Owner);
}
}
@@ -0,0 +1,6 @@
using Robust.Shared.GameStates;
namespace Content.Shared._DV.Roles;
[RegisterComponent, NetworkedComponent]
public sealed partial class ActionGrantRoleComponent : Component;
@@ -0,0 +1,6 @@
using Content.Shared.Roles.Components;
namespace Content.Shared._DV.Roles;
[RegisterComponent]
public sealed partial class InsurgentRoleComponent : BaseMindRoleComponent;
@@ -0,0 +1,6 @@
using Content.Shared.Roles.Components;
namespace Content.Shared._DV.Roles;
[RegisterComponent]
public sealed partial class LoyalistRoleComponent : BaseMindRoleComponent;
@@ -0,0 +1,12 @@
using Content.Shared.Objectives.Components;
using Content.Shared.Roles.Components;
using Robust.Shared.Prototypes;
namespace Content.Shared._DV.Roles;
[RegisterComponent]
public sealed partial class ObjectiveRoleComponent : BaseMindRoleComponent
{
[DataField(required: true)]
public List<EntProtoId<ObjectiveComponent>> Objectives;
}
@@ -0,0 +1,6 @@
using Content.Shared.Roles.Components;
namespace Content.Shared._DV.Roles;
[RegisterComponent]
public sealed partial class UprisingInconvertibleRoleComponent : BaseMindRoleComponent;
@@ -0,0 +1,16 @@
using Content.Shared.Roles.Components;
namespace Content.Shared._DV.Roles;
[RegisterComponent]
public sealed partial class UprisingRoleComponent : BaseMindRoleComponent
{
[DataField(required: true)]
public UprisingSide Side;
}
public enum UprisingSide : byte
{
Insurgent,
Loyalist,
}
@@ -0,0 +1,60 @@
using Content.Shared.Mind;
using Robust.Shared.Containers;
using Robust.Shared.Network;
namespace Content.Shared._DV.Roles;
public sealed class ObjectiveRoleSystem : EntitySystem
{
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ObjectiveRoleComponent, EntGotInsertedIntoContainerMessage>(OnInsertedIntoMind);
SubscribeLocalEvent<ObjectiveRoleComponent, ComponentShutdown>(OnShutdown);
}
private void OnInsertedIntoMind(Entity<ObjectiveRoleComponent> ent, ref EntGotInsertedIntoContainerMessage args)
{
if (_net.IsClient)
return;
if (!TryComp<MindComponent>(args.Container.Owner, out var mind))
return;
foreach (var objective in ent.Comp.Objectives)
{
_mind.TryAddObjective(args.Container.Owner, mind, objective);
}
}
private void OnShutdown(Entity<ObjectiveRoleComponent> ent, ref ComponentShutdown args)
{
if (_net.IsClient)
return;
if (!_container.TryGetContainingContainer(ent.Owner, out var container) ||
!TryComp<MindComponent>(container.Owner, out var mind))
return;
var indices = new List<int>();
for (var i = mind.Objectives.Count; i >= 0; i--)
{
var objective = mind.Objectives[i];
if (MetaData(objective).EntityPrototype?.ID is { } id && ent.Comp.Objectives.Contains(id))
{
indices.Add(i);
}
}
foreach (var index in indices)
{
_mind.TryRemoveObjective(container.Owner, mind, index);
}
}
}
@@ -0,0 +1,10 @@
using Content.Shared.Trigger.Components.Effects;
using Robust.Shared.GameStates;
namespace Content.Shared._DV.Trigger.Components.Effects;
/// <summary>
/// is used for implants and such so the right paramters can be passed
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class CreateHitmanCardOnTriggerComponent : BaseXOnTriggerComponent;
@@ -0,0 +1,30 @@
using Content.Shared._DV.Trigger.Components.Effects;
using Content.Shared.Trigger;
using Content.Shared.Hands.EntitySystems;
namespace Content.Shared._DV.Trigger.Systems;
public sealed class CreateHitmanCardOnTriggerSystem : EntitySystem
{
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CreateHitmanCardOnTriggerComponent, TriggerEvent>(OnTrigger);
}
//just spawns a card on the given target. uses predicated or spawn next to based on if. as trigger effect doesnt seem to have predicted on it ill just check if this is sever first and if not assume its predicted.
private void OnTrigger(Entity<CreateHitmanCardOnTriggerComponent> ent, ref TriggerEvent args)
{
if (args.Handled || args.User is not { } user)
return;
var mapCoords = _transform.GetMapCoordinates(ent);
var card = EntityManager.PredictedSpawn("HitmanBusinessCard", mapCoords);
_hands.TryPickupAnyHand(user, card);
args.Handled = true;
}
}
@@ -0,0 +1,14 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic;
namespace Content.Shared._DV.Uprising;
[RegisterComponent]
public sealed partial class CommandStatusObjectiveComponent : Component
{
[DataField(required: true, customTypeSerializer: typeof(CustomHashSetSerializer<string, ComponentNameSerializer>))]
public HashSet<string> ConvertedRoles;
[DataField]
public bool ShouldUnconvertedBeIncapacitated;
}
@@ -0,0 +1,19 @@
using Content.Shared.NPC.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic;
namespace Content.Shared._DV.Uprising;
[RegisterComponent]
public sealed partial class CrewConversionObjectiveComponent : Component
{
[DataField(required: true, customTypeSerializer: typeof(CustomHashSetSerializer<string, ComponentNameSerializer>))]
public HashSet<string> ConvertedRoles;
[DataField(required: true)]
public HashSet<ProtoId<NpcFactionPrototype>> ConversionSourceFactions;
[DataField(required: true)]
public float TargetFraction;
}
@@ -0,0 +1,58 @@
using Content.Shared.Mind.Components;
using Content.Shared.NPC.Components;
using Content.Shared.NPC.Systems;
using Content.Shared.Objectives.Components;
using Content.Shared.Roles;
namespace Content.Shared._DV.Uprising;
public sealed class CrewConversionObjectiveSystem : EntitySystem
{
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
[Dependency] private readonly SharedRoleSystem _role = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CrewConversionObjectiveComponent, ObjectiveGetProgressEvent>(OnGetProgress);
}
private void OnGetProgress(Entity<CrewConversionObjectiveComponent> ent, ref ObjectiveGetProgressEvent args)
{
var total = 0;
var counted = 0;
var query = AllEntityQuery<MindContainerComponent, NpcFactionMemberComponent>();
while (query.MoveNext(out var uid, out var mind, out var faction))
{
if (mind.Mind is not { } mindUid)
continue;
if (!_npcFaction.IsMemberOfAny((uid, faction), ent.Comp.ConversionSourceFactions))
continue;
total++;
foreach (var role in ent.Comp.ConvertedRoles)
{
if (!EntityManager.ComponentFactory.TryGetRegistration(role, out var roleReg))
{
Log.Error($"Role component not found for CrewConversionObjective: {role}");
continue;
}
if (!_role.MindHasRole(mindUid, roleReg.Type, out _))
continue;
counted++;
break;
}
}
if (total == 0)
return;
args.Progress = ((float)counted / (float)total) / ent.Comp.TargetFraction;
}
}
@@ -0,0 +1,4 @@
namespace Content.Shared._DV.Uprising;
[RegisterComponent]
public sealed partial class UprisingArmRequiredObjectiveComponent : Component;
@@ -0,0 +1,10 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;
namespace Content.Shared._DV.Uprising;
[Serializable, NetSerializable]
public sealed partial class UprisingDisarmDoAfter : SimpleDoAfterEvent;
[Serializable, NetSerializable]
public sealed partial class UprisingArmDoAfter : SimpleDoAfterEvent;
@@ -0,0 +1,10 @@
using Content.Shared._DV.Roles;
namespace Content.Shared._DV.Uprising;
[RegisterComponent]
public sealed partial class UprisingVictoryObjectiveComponent : Component
{
[DataField(required: true)]
public UprisingSide Side;
}
@@ -0,0 +1,23 @@
using Content.Shared.NPC.Prototypes;
using Robust.Shared.Prototypes;
namespace Content.Shared.Zombies;
public sealed partial class ZombieComponent
{
/// <summary>
/// DeltaV - The list of factions that an entity is part of from before they were zombified.
/// The zombification process removes them, but cloning a zombie copies the NPCFactionMemberComponent
/// so they are still considered a zombie faction-wise, so we need to keep track of what they had right
/// before the factions are removed.
/// </summary>
[DataField]
public List<ProtoId<NpcFactionPrototype>> FactionsBeforeZombification = new();
/// <summary>
/// DeltaV - Tracks if the entity was a pacifist before turning into a zombie. Although, there are other
/// scenarios where the person might be pacified but those are usually temporary.
/// </summary>
public bool WasPacisfistBeforeZombification = false;
}
@@ -10,7 +10,7 @@ namespace Content.Shared._ST.Interaction;
/// Data for interaction particles
/// </summary>
[Serializable, NetSerializable]
public sealed class StellarInteractionParticleEvent(NetEntity performer, NetEntity? used, NetEntity target, bool isClientEvent) : EntityEventArgs
public sealed class StellarInteractionParticleEvent(NetEntity performer, NetEntity? used, NetEntity target, bool isClientEvent, StellarInteractionParticleType type) : EntityEventArgs
{
public NetEntity Performer = performer;
@@ -22,4 +22,13 @@ public sealed class StellarInteractionParticleEvent(NetEntity performer, NetEnti
/// Workaround for event subscription not working w/ the session overload
/// </summary>
public bool IsClientEvent = isClientEvent;
public StellarInteractionParticleType Type = type;
}
[Serializable, NetSerializable]
public enum StellarInteractionParticleType
{
Use,
Pull,
}
@@ -0,0 +1,29 @@
- files: ["alien_footstep_charge1.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from cmss13"
source: "https://github.com/cmss13-devs/cmss13/blob/183b50b774c6faef054b6f67f57ff40ecc15409f/sound/effects/alien_footstep_charge1.ogg"
- files: ["alien_footstep_charge2.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from cmss13"
source: "https://github.com/cmss13-devs/cmss13/blob/183b50b774c6faef054b6f67f57ff40ecc15409f/sound/effects/alien_footstep_charge2.ogg"
- files: ["alien_footstep_charge3.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from cmss13"
source: "https://github.com/cmss13-devs/cmss13/blob/183b50b774c6faef054b6f67f57ff40ecc15409f/sound/effects/alien_footstep_charge3.ogg"
- files: ["alien_footstep_large1.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from cmss13"
source: "https://github.com/cmss13-devs/cmss13/blob/183b50b774c6faef054b6f67f57ff40ecc15409f/sound/effects/alien_footstep_large1.ogg"
- files: ["alien_footstep_large2.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from cmss13"
source: "https://github.com/cmss13-devs/cmss13/blob/183b50b774c6faef054b6f67f57ff40ecc15409f/sound/effects/alien_footstep_large2.ogg"
- files: ["alien_footstep_large3.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from cmss13"
source: "https://github.com/cmss13-devs/cmss13/blob/183b50b774c6faef054b6f67f57ff40ecc15409f/sound/effects/alien_footstep_large3.ogg"
+18
View File
@@ -314,5 +314,23 @@ Entries:
id: 34
time: '2026-06-06T19:14:04.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5699
- author: FieldCommand
changes:
- message: 'Ghost bat: Syndicate Prison-themed ghost bar has been added and can
be spawned in by anyone with loadgrid permissions.'
type: Add
id: 35
time: '2026-06-08T17:23:24.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5578
- author: FieldCommand, Stxcking
changes:
- message: Nanoblod vending machin syndicate counter to nanomed pluss.
type: Add
- message: Made some small changes to ghost bar syndicatre prison. SyndieJuice now
has a new look to look more like its counterpart, Nanoblood.
type: Tweak
id: 36
time: '2026-06-16T20:02:18.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6006
Name: DeltaVAdmin
Order: 5
+453 -452
View File
@@ -1,456 +1,4 @@
Entries:
- author: verybigman311
changes:
- message: Lava Fountains are now an available decoration.
type: Add
- message: Drinking from fountains has become much easier.
type: Fix
id: 1885
time: '2025-11-30T16:44:24.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4792
- author: SirWarock
changes:
- message: Buffed the Advanced Truncheon to actually.. be better than the normal
Truncheon.
type: Tweak
id: 1886
time: '2025-11-30T16:46:38.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4736
- author: cmorley191
changes:
- message: psychokinetic scream now works with "psionic disturbance" arti trigger
type: Fix
id: 1887
time: '2025-11-30T17:00:04.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4816
- author: Coryler
changes:
- message: The minor mass mind swap glimmer event has been added. If glimmer is
above 750, it can mindswap up to 6 people temporarily.
type: Add
id: 1888
time: '2025-11-30T17:46:12.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4728
- author: TehFlaminTaco
changes:
- message: Fractured Form can now be mindbreaker'd without perma-sleeping
type: Fix
- message: Fractured Form will no-longer spawn an IPC body.
type: Tweak
id: 1889
time: '2025-11-30T18:00:34.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4582
- author: cmorley191
changes:
- message: Artifact node effects are sometimes hidden or unpredictable until after
you trigger them for the first time. Be careful!
type: Tweak
id: 1890
time: '2025-11-30T18:10:16.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4748
- author: ShepardToTheStars, slarticodefast
changes:
- message: Crawling speed now depends on the number of free hands you have.
type: Tweak
id: 1891
time: '2025-12-01T07:57:02.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4772
- author: Cepelinas1
changes:
- message: Possession charges no longer stack. The highest offending category is
now charged.
type: Tweak
id: 1892
time: '2025-12-01T13:33:46.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4808
- author: Apachit0
changes:
- message: Buffed the Makeshift Fishing rod
type: Tweak
id: 1893
time: '2025-12-01T21:20:35.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4827
- author: BunglesnortBoss
changes:
- message: Enabled Cyborg's to weld themselves! Takes a lot of time but at least
you can weld up those scratches!
type: Tweak
- message: Cyborg's power draw rate lowered! Still get the TEG up fast however!
type: Tweak
- message: Increased Weightless Acceleration, Should feel a bit faster for the Cyborg's
in space, Congrats Salvage!
type: Tweak
id: 1894
time: '2025-12-02T00:13:08.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4819
- author: Deltanedas, Bonktrauma
changes:
- message: Added Ovni Station.
type: Add
id: 1895
time: '2025-12-02T04:42:19.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4602
- author: Vapetastic-Gaming
changes:
- message: Patreon link in game has been updated
type: Tweak
id: 1896
time: '2025-12-02T14:20:38.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4833
- author: ShepardToTheStars
changes:
- message: Healing from breathing miasma with rat lungs no longer scales by quantity
of the gas in the air.
type: Tweak
id: 1897
time: '2025-12-02T22:26:27.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4836
- author: Eternally-Confused
changes:
- message: Aroace cloaks can now be found in the Pride-o-mat!
type: Add
- message: Pride-o-mat restocks now cost slightly more
type: Tweak
id: 1898
time: '2025-12-03T05:01:47.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4847
- author: Stxcking
changes:
- message: Syndicat Returns! with some tweaks
type: Add
id: 1899
time: '2025-12-03T05:32:01.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4731
- author: Proxysseia
changes:
- message: Larynx Implants are now purchaseable in the uplink for all species
type: Tweak
- message: Kanabou are now purchaseable in the uplink for all species
type: Tweak
- message: Samurai armors are now purchaseable in the uplink for all species
type: Tweak
id: 1900
time: '2025-12-03T07:07:52.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4759
- author: ShepardToTheStars
changes:
- message: Stasicillin should once again force the target to fall asleep if they
have over 11u.
type: Fix
id: 1901
time: '2025-12-03T16:08:27.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4823
- author: Stxcking
changes:
- message: Syndicat description fixed
type: Fix
id: 1902
time: '2025-12-03T20:25:52.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4854
- author: FieldCommand
changes:
- message: All ships from the shipyard cost 1000 more spesos due to inflation.
type: Tweak
id: 1903
time: '2025-12-03T22:34:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4858
- author: verybigman311
changes:
- message: Christmas lamps now display the correct rotation
type: Fix
id: 1904
time: '2025-12-04T03:26:40.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4865
- author: Woljif
changes:
- message: Gave the dragon a wide-sweep attack, more damage, and faster fireballs.
type: Tweak
id: 1905
time: '2025-12-04T08:27:37.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4781
- author: ShepardToTheStars, Niomi
changes:
- message: Borg ID chips from the exofab now have the same access as round-start
borgs.
type: Tweak
- message: SRNs can no longer print normal borg ID chips.
type: Tweak
- message: Syndicate borg ID chips now cost a bit less to make.
type: Tweak
- message: Agent IDs can no longer copy access from borg ID chips.
type: Tweak
- message: The new derelict borgs now have the intended borg access to the station!
type: Fix
- message: Derelict syndicate borgs don't have usual borg access, but has enough
to get into the station.
type: Tweak
- message: Derelict syndicate borgs can be unlocked by people with Robotics access
(so they can get their access updated).
type: Tweak
id: 1906
time: '2025-12-04T11:18:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4821
- author: Dorragon
changes:
- message: Space dragons welcome sharkminnows in their family
type: Add
id: 1907
time: '2025-12-04T13:27:57.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4826
- author: Nesoryo, Nikovnik, kotobdev
changes:
- message: Added alternative typing indicators for whispering, emoting, using the
radio, and (L)OOC-ing!
type: Add
id: 1908
time: '2025-12-04T16:59:08.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4679
- author: verybigman311
changes:
- message: Every single wieldable gun now has wielded sprites.
type: Add
- message: Wieldable guns that previously utilized upstream sprites, have been updated
with Delta-V sprites.
type: Add
- message: Mark-1 series rifles are now wieldable.
type: Tweak
- message: Touched up a few miscolored cocktail sprites.
type: Tweak
- message: Practice security weapons now have orange tips for safety purposes.
type: Tweak
- message: Practice laser carbines are now blue.
type: Tweak
- message: Practice disablers not having inhand sprites.
type: Fix
id: 1909
time: '2025-12-04T18:42:20.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4851
- author: verybigman311
changes:
- message: Frag Grenades now have shrapnel!
type: Add
id: 1910
time: '2025-12-04T22:28:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4856
- author: kontakt, ShepardToTheStars
changes:
- message: The ninja's spider clan charge can now be placed on walls and windows
again.
type: Fix
id: 1911
time: '2025-12-05T01:44:35.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4861
- author: ShepardToTheStars
changes:
- message: The nukie agent's visor can finally see silicon health.
type: Fix
id: 1912
time: '2025-12-05T01:58:46.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4864
- author: cmorley191
changes:
- message: Rock anom won't make unbreakable rocks anymore
type: Fix
id: 1913
time: '2025-12-05T02:04:53.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4873
- author: Stxcking
changes:
- message: Security, medical, and roboticist's loadouts now have prescription glasses
counterparts. (Security players make sure to save your option.)
type: Tweak
id: 1914
time: '2025-12-05T02:14:01.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4871
- author: verybigman311
changes:
- message: A large plethora of melee weapons now have the correct wideswing rotation.
type: Fix
- message: Drills and Saws now function similarly in combat to Mining Drills.
type: Tweak
- message: Electric and Bass guitars can now be used as weapons.
type: Tweak
- message: Numerous other tweaks have been made to melee weapons. Too many to list.
type: Tweak
id: 1915
time: '2025-12-05T02:37:20.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4806
- author: ShepardToTheStars
changes:
- message: Silvia, the CMO's pet, can now equip medhuds and PDAs! No more dragging
them around.
type: Add
- message: Silvia can no longer slip.
type: Fix
id: 1916
time: '2025-12-05T02:40:36.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4867
- author: HTMLSystem
changes:
- message: Chitnids will now use moth sprites for their glasses
type: Tweak
id: 1917
time: '2025-12-05T02:49:32.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4835
- author: Stxcking
changes:
- message: 'Fishing vendor: Exchange fish for fishing points!'
type: Add
- message: Fishing basket to easily store caught fish.
type: Add
id: 1918
time: '2025-12-05T02:58:57.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4862
- author: kotobdev
changes:
- message: Nukie commanders are now ~~threatened~~ *encouraged* to use the war declarator
properly.
type: Add
- message: Nukies now have 8 minutes to declare war, up from 6.
type: Tweak
id: 1919
time: '2025-12-05T04:48:30.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4876
- author: ShepardToTheStars, Jakumba
changes:
- message: Holofans are no longer infinite duration. They last 5 minutes but also
recharge over time. They can still be picked up.
type: Tweak
- message: All holoprojectors function the same way now. You can pick up janitor
holosigns, security holobarriers, and they all recharge over time.
type: Tweak
id: 1920
time: '2025-12-05T12:56:10.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4734
- author: PureBreadBagel, Cepelinas1
changes:
- message: Guidebook has got new entries! The guidebook now contains Entries relating
to Space Law, SOP, Commanding Officer, Security And Justice Regulations, Hearings
and all the entries you could ever need to enforce law and legality!
type: Add
- message: Security and Justice's reading materials got upgraded! Security 101 and
Space Law books now contain new entries! Such as Space Law, SOP, General Regulations,
Commanding Officer...etc!
type: Tweak
- message: The Medical Reference book contains the Medical Regulations now.
type: Tweak
- message: Fixed a guidebook entry relating to Organ Manipulation. It no longer
displays that replacing the heart cures rot, and that replacing the liver cures
poison.
type: Fix
id: 1921
time: '2025-12-05T17:56:38.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4857
- author: Eternally-Confused and Toby222
changes:
- message: Pride pins, scarves, and cloaks are now able to change into similar pieces
of pride clothing!
type: Tweak
id: 1922
time: '2025-12-07T07:09:34.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4845
- author: Proxysseia
changes:
- message: Removed Speedboots
type: Remove
id: 1923
time: '2025-12-07T09:47:14.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4883
- author: Halo3moth
changes:
- message: Feroxis can now thump! Sharks have tails too!
type: Tweak
id: 1924
time: '2025-12-07T11:45:45.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4877
- author: Stxcking
changes:
- message: Added chemical, surgeon, and paramedic wall lockers for mappers
type: Add
id: 1925
time: '2025-12-07T17:54:34.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4899
- author: beck-thompson
changes:
- message: Respawn timer now works when observing
type: Fix
id: 1926
time: '2025-12-07T18:02:52.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4895
- author: zelezniciar, ArtisticRoomba
changes:
- message: Atmospherics Delta-Pressure now has a short guidebook entry. You can
find it in Jobs > Engineering > Atmospherics > Atmospheric Upsets > Delta Pressure.
type: Add
id: 1927
time: '2025-12-08T00:03:47.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4906
- author: IAmNotGray
changes:
- message: 'Elegance: Who changed the thermostat on Elegance? The pool froze over,
dude!'
type: Tweak
id: 1928
time: '2025-12-08T05:30:18.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4903
- author: Velcroboy
changes:
- message: 'Hive: Added snow!'
type: Add
id: 1929
time: '2025-12-08T06:07:51.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4898
- author: verybigman311
changes:
- message: Tinted windows can now be reinforced.
type: Add
id: 1930
time: '2025-12-08T09:01:15.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4875
- author: SirSmith148
changes:
- message: Incorporated Glimmer within the new Xenoarchaeology system
type: Tweak
id: 1931
time: '2025-12-08T04:11:00.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4486
- author: ShepardToTheStars, gluesniffler
changes:
- message: Harpies can now take flight!
type: Add
id: 1932
time: '2025-12-08T13:58:53.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4888
- author: Dorragon
changes:
- message: Rat kings and xenos now see in the dark
type: Add
id: 1933
time: '2025-12-08T14:34:58.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4881
- author: BunglesnortBoss
changes:
- message: Salvage Cyborg's now have new laws! Give em' a read! Credit to AirlineFood
for the actual laws.
type: Tweak
id: 1934
time: '2025-12-08T14:37:23.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4866
- author: cmorley191
changes:
- message: '"Impossible" arti trigger combinations (like low+high pressure) will
no longer appear on artifacts.'
type: Tweak
id: 1935
time: '2025-12-08T14:47:08.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4740
- author: cmorley191
changes:
- message: The handheld Node Scanner tool has new artifact information available
type: Add
id: 1936
time: '2025-12-08T14:48:49.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/4814
- author: ShepardToTheStars
changes:
- message: All syndicate cyborg ghost roles now spawn with a neuroling rather than
@@ -4395,4 +3943,457 @@
id: 2385
time: '2026-06-06T19:14:04.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5699
- author: SirRequiem
changes:
- message: 'Terra: Sec is now properly blue!'
type: Tweak
- message: 'Terra: Medbay got a lil remodel'
type: Tweak
id: 2386
time: '2026-06-07T16:22:57.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5956
- author: biddygelson
changes:
- message: 'Academy: Department faxes and Poppy'
type: Add
- message: 'Academy: RED sec NO, BLU sec YES.'
type: Tweak
id: 2387
time: '2026-06-07T18:13:12.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5972
- author: Stxcking
changes:
- message: Glowsticks can now be use for glow in the dark stars wall decals!
type: Fix
id: 2388
time: '2026-06-07T19:05:16.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5970
- author: Stxcking
changes:
- message: Holoflares pellets' light actually hurt Skias.
type: Fix
id: 2389
time: '2026-06-07T19:33:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5976
- author: MantasDab360
changes:
- message: Removes duplicates of yellow and white towels in loadout.
type: Fix
id: 2390
time: '2026-06-07T19:46:18.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5964
- author: rebe83
changes:
- message: Entropic mobs now deal a small amount of blunt damage.
type: Tweak
id: 2391
time: '2026-06-07T20:48:50.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5962
- author: rebe83
changes:
- message: Ninja's EMP ability now has a 5 second cooldown
type: Tweak
id: 2392
time: '2026-06-08T04:35:21.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5967
- author: Eternally-Confused
changes:
- message: The nuclear fabricator now announces when it receives new recipes.
type: Tweak
id: 2393
time: '2026-06-08T05:29:56.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5985
- author: Vapetastic-Gaming
changes:
- message: Submarine has received nuclear power. Sub has also gained a VOX BOX and
a new janitor closet. Due to how the reactor was transported on station, the
station has been left a mess, enjoy.
type: Tweak
id: 2394
time: '2026-06-08T19:36:02.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5760
- author: Velcroboy
changes:
- message: Added an evac pod in north maints; and Poppy the engineering possum!
type: Add
- message: Security is blu; botany soil beds come prefilled now; and epi locker
area moved into the back.
type: Tweak
id: 2395
time: '2026-06-08T19:50:31.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5965
- author: rebe83
changes:
- message: Shadow cats can no longer attack. They can now pounce though.
type: Tweak
id: 2396
time: '2026-06-09T13:45:27.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5977
- author: Cepelinas1
changes:
- message: Added 22 new tips!
type: Add
- message: Added missing commas on certain weapon descriptions.
type: Tweak
- message: Added missing scope descriptions to Laser Cannons and Vulcans.
type: Tweak
id: 2397
time: '2026-06-09T18:10:02.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6004
- author: rebe83
changes:
- message: Meatspikes now take 5 seconds to build instead of 30. He's right behind
me, isn't he?
type: Tweak
id: 2398
time: '2026-06-09T18:48:35.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5999
- author: Vapetastic-Gaming
changes:
- message: Xenos are now much scarier, and should look familiar too !!
type: Tweak
id: 2399
time: '2026-06-10T18:21:14.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5891
- author: Velcroboy
changes:
- message: 'Arena: Security is bloo now; botany has filled soil beds; and evac pods
are larger'
type: Tweak
id: 2400
time: '2026-06-11T01:28:31.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6009
- author: einknusprigestoast
changes:
- message: Removed DeathSquad
type: Remove
id: 2401
time: '2026-06-13T02:29:04.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6003
- author: rebe83
changes:
- message: The psionic power Fractured Form was removed.
type: Remove
id: 2402
time: '2026-06-13T19:29:04.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6011
- author: stormyatt
changes:
- message: ghost role hitman variant
type: Add
id: 2403
time: '2026-06-13T20:03:15.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5848
- author: CarolCuchara
changes:
- message: Secborgs now leave blue fibers behind. Red is no more!
type: Fix
id: 2404
time: '2026-06-14T04:12:58.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6025
- author: Stop-Signs
changes:
- message: WT550 fire rate has been reduced by 0.5
type: Tweak
- message: WT550 Magazine size has been reduced 30->20
type: Tweak
- message: WT550 is slightly less accurate
type: Tweak
id: 2405
time: '2026-06-14T08:13:25.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5581
- author: CarolCuchara
changes:
- message: Pager linking now only works when in range of the fax or holopad!
type: Fix
id: 2406
time: '2026-06-14T18:30:35.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6032
- author: sowelipililimute
changes:
- message: Pulling now has a unique particle effect
type: Add
- message: Interaction particles now only spawn on UIs if the UIs have an associated
open sound
type: Tweak
- message: Interaction particles no longer spawn on closing a UI
type: Fix
id: 2407
time: '2026-06-15T15:05:30.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6033
- author: CarolCuchara
changes:
- message: Throwing glasses while wearing beer googles no longer spills the contents!
type: Fix
id: 2408
time: '2026-06-15T15:10:00.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6031
- author: StarboundSolaris
changes:
- message: Pitbulls and their genetically modified subspecies, Ventbulls, have been
re introduced to the Delta Sector!
type: Add
- message: NanoTrasen is now deploying Ventbulls into station ventilation systems
as a method of quick and inexpensive pest control! Don't be surprised if they
crawl out of a vent while chasing a horde of mice!
type: Add
- message: Departments may sometimes come equipped with a unique pitbull!
type: Add
- message: Pitbulls no longer maul couriers and felinids!
type: Tweak
- message: Pitbulls are now more tolerant to being pet!
type: Tweak
- message: Pitbulls now come with an even greater variety of ridiculous names!
type: Tweak
id: 2409
time: '2026-06-15T16:02:07.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5915
- author: rebe83
changes:
- message: Security ponchos now only help with temperature. It's just plastic after
all.
type: Tweak
- message: Gorlex ponchos now only offer modest protection. They just don't make
them like they used to.
type: Tweak
id: 2410
time: '2026-06-15T15:51:39.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6001
- author: keekee38
changes:
- message: NT no longer stores guns with loaded chambers
type: Tweak
id: 2411
time: '2026-06-15T16:46:35.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5819
- author: CarolCuchara
changes:
- message: Zombified crew and other entities like Laika will drop headsets which
are in their pockets. No more listening to survivor comms!
type: Fix
id: 2412
time: '2026-06-15T17:27:01.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6030
- author: JustTNE
changes:
- message: Don't display SSD duration when examining dead players or untaken ghost
roles
type: Fix
id: 2413
time: '2026-06-16T14:16:08.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6012
- author: DisposableCrewmember42
changes:
- message: The midround Entropic Colossus has been reworked! It will now be buffed
by effigies going supercritical and die when they decay. After the colossus
places three effigies, it can roam the station freely.
type: Add
id: 2414
time: '2026-06-16T17:09:33.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5565
- author: CarolCuchara
changes:
- message: Rat Kings raise army ability is now dynamically priced. The first servants
are cheaper, allowing for an easier early game and bounce back. Too many servants
will increase the price drastically, with giant swarms killing the performance
very hard to achieve!
type: Tweak
id: 2415
time: '2026-06-16T17:43:10.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6017
- author: ShepardToTheStars
changes:
- message: Pitbulls no longer fit under doors.
type: Fix
- message: Pitbulls will now retaliate if you hit them. Be nice!
type: Fix
id: 2416
time: '2026-06-17T01:06:56.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6046
- author: rebe83
changes:
- message: .25 caseless poison ammo now uses lexorin and is faster acting.
type: Tweak
- message: The estoc once again shoots in 3 round bursts, but still faster than
before.
type: Tweak
- message: Knuckledusters are now made of REAL plastitanium and deal 14 blunt per
hit. Nanotrasen noggins can be rattled in 4 punches.
type: Tweak
id: 2417
time: '2026-06-17T13:36:02.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5991
- author: JustTNE
changes:
- message: Zombies can no longer use jetpacks
type: Remove
- message: Pets can no longer use jetpacks
type: Remove
id: 2418
time: '2026-06-17T13:56:26.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5776
- author: Proxysseia
changes:
- message: Breaking and Entering now means what you think it does
type: Tweak
id: 2419
time: '2026-06-17T14:07:48.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6050
- author: ShepardToTheStars
changes:
- message: The biomasser is fixed and will now again properly biomass entities with
0% blood.
type: Fix
id: 2420
time: '2026-06-17T15:32:34.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6042
- author: sowelipililimute
changes:
- message: Fax machines no longer need to be refreshed before their first use.
type: Tweak
id: 2421
time: '2026-06-18T16:22:15.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6058
- author: LordSugarcane
changes:
- message: All references to Security in the guidebook are now properly blue!
type: Tweak
id: 2422
time: '2026-06-18T16:34:53.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6013
- author: Stxcking
changes:
- message: Broken Station Maps can be Deconstructed
type: Tweak
id: 2423
time: '2026-06-18T16:37:33.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6005
- author: keekee38
changes:
- message: SV-213 pistols now come standard with medium power cells
type: Tweak
id: 2424
time: '2026-06-19T15:48:58.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6065
- author: DisposableCrewmember42
changes:
- message: Ghosts will now see chat messages prepended with clickable follow links.
These can be turned off in the General settings. [upstream cherry-pick]
type: Add
id: 2425
time: '2026-06-19T15:52:36.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6063
- author: EmberAstra
changes:
- message: Purifying salts now fit into medical belts and medkits.
type: Tweak
id: 2426
time: '2026-06-19T16:05:49.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6062
- author: rebe83
changes:
- message: Security radio color has been tweaked for legibility. Looking a little
burple... maybe even laughender?
type: Tweak
id: 2427
time: '2026-06-19T16:15:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6016
- author: Halo3moth
changes:
- message: Nanotrasen high command as released a statement on the existance of chameleon
gear, syndicate operatives remember to lock your gear (chameleon gear is no
longer metashielded)
type: Tweak
id: 2428
time: '2026-06-19T17:48:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6000
- author: rebe83
changes:
- message: You are no longer able to identify bomb pens based on damage values in
the examine box. Because they don't do damage. Trust.
type: Tweak
id: 2429
time: '2026-06-19T17:52:44.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6010
- author: rebe83
changes:
- message: A bizarre mixup at the cube factory has been fixed, and kobold cubes
once more produce actual kobolds.
type: Fix
id: 2430
time: '2026-06-19T17:59:46.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5968
- author: DisposableCrewmember42, neomoth
changes:
- message: Melee screenshake for the attacker now has a heavy and light damage variant.
The heavy damage variant is also triggered by two-handed weapons being wielded.
type: Tweak
- message: Melee screenshake only occurs for the target if total damage > 4
type: Tweak
- message: Explosion screenshake now includes a directional camera kick that falls
off with distance
type: Tweak
- message: Explosion screenshake now falls off with distance
type: Tweak
id: 2431
time: '2026-06-19T18:12:00.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6059
- author: Proxysseia
changes:
- message: '"Cosmic Cultists want to end the world" is now common knowledge. Their
metashield has been removed.'
type: Remove
id: 2432
time: '2026-06-19T18:35:33.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6026
- author: rebe83
changes:
- message: Felinids can now use their claws to try and hold fast against space wind.
or the warden.
type: Add
id: 2433
time: '2026-06-19T19:26:22.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5996
- author: ShepardToTheStars
changes:
- message: Cats and other animals will no longer attack players who were cloned
after becoming a zombie.
type: Fix
- message: The Pacifism trait is now properly re-applied to players who were cloned
after becoming a zombie.
type: Fix
- message: Cloned Initial Infected now get an escape and live objective after being
cloned.
type: Tweak
id: 2434
time: '2026-06-19T21:42:45.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6053
- author: ShepardToTheStars
changes:
- message: The syndicate hardsuits now have 15% more aura when you turn the light
on in the dark.
type: Tweak
- message: The vulpkanin syndicate suits have had a facelift and now match better
with other syndicate hardsuits.
type: Add
id: 2435
time: '2026-06-19T21:53:47.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6060
- author: ShepardToTheStars
changes:
- message: SRN-made borgs no longer have borg AA as soon as they are made. No more
walking into the AI core.
type: Fix
- message: SRNs can print batteries in their exosuit fabricator again.
type: Fix
id: 2436
time: '2026-06-19T22:06:51.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/6045
- author: stormyatt
changes:
- message: hitman card implant to hitmans. cause calling cards are fun!
type: Add
id: 2437
time: '2026-06-20T10:46:03.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5896
Order: 1
+26
View File
@@ -1045,4 +1045,30 @@
id: 121
time: '2026-06-05T15:07:41.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5880
- author: snowy_winter
changes:
- message: 'Edge: Added department faxes and pagers.'
type: Add
- message: 'Edge: Main bridge is now more open; surgery room removed; and AI core
fixed up a bit.'
type: Tweak
- message: 'Edge: EPI now has artifacts again yay'
type: Fix
id: 122
time: '2026-06-08T21:57:40.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5983
- author: Stxcking
changes:
- message: 'Shoko: Shoko is now 1/3 blue (BlueSec).'
type: Tweak
- message: 'Shoko: Engineering''s TEG and gas recycler set-ups have been improved!
Atmos has two more APC as well!'
type: Tweak
- message: 'Shoko: Surgery rooms have been replaced.'
type: Tweak
- message: 'Shoko: Departmental pager doorbells and faxes have been implemented!'
type: Tweak
id: 123
time: '2026-06-12T17:16:00.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/5940
Order: 3
File diff suppressed because one or more lines are too long
@@ -1,7 +1,6 @@
## Names of Psionic Powers
psionic-power-name-dispel = Dispel
psionic-power-name-eruption = Psionic Eruption
psionic-power-name-fractured-form = Fractured Form
psionic-power-name-mass-sleep = Mass Sleep
psionic-power-name-mindswap = Mind Swap
psionic-power-name-mindswap-return = Mind Swap Return
@@ -27,13 +26,6 @@ psionic-equipped-shielded-in-doafter = The insulative gear broke your concentrat
psionic-dispelled = Someone dispelled your psionic concentration!
## Specific Psionic messages
# Fractured Form
psionic-power-fractured-form-nobodies = You have no alternate forms to switch to!
psionic-power-fractured-form-sleepy = You feel very sleepy... You should find somewhere to rest.
psionic-power-fractured-form-ssd = { CAPITALIZE(SUBJECT($ent)) } { CONJUGATE-BE($ent) } in a deep sleep. { CAPITALIZE(POSS-ADJ($ent)) } eyes seem to be darting around as if dreaming.
psionic-power-fractured-form-examine-self = You feel a strange connection to { OBJECT($ent) }.
psionic-power-fractured-form-dispelled = Someone dispelled your sleepiness..
# Metapsionic Pulse
psionic-power-metapsionic-success = You detect psychic presence there.
psionic-power-metapsionic-failure = You don't detect any psychic presence there.
@@ -100,6 +92,8 @@ psionic-power-precognition-unknown-shuttle-disaster-evac-pod-result-message = Yo
psionic-power-precognition-syndicate-armsdealer-result-message = You see a vision of a ship lurking in the shadows, its cargo deadly.
psionic-power-precognition-rift-spawn-result-message = You see a small spark of energy, quickly expanding as it tears reality apart, twisting everything around it.
psionic-power-precognition-asakim-spawn-result-message = You smell stale air from a cryopod opening, and the faint echo of an intelligence far away but very near.
psionic-power-precognition-pitbull-spawn-result-message = You see a vision of a hundred small creatures being torn apart by bloodthirsty beasts in a maze of steel.
psionic-power-precognition-hitman-spawn-result-message = You see a man in a business suit, a corpse at their feet.
# Psionic Eruption
psionic-eruption-begin = {CAPITALIZE(THE($user))} is being consumed by a psionic energy!
@@ -0,0 +1 @@
anomaly-behavior-always-grow = [color=red]Anomaly never stops growing.[/color]
@@ -70,7 +70,6 @@ crime-assist-question-isitcategorycde = Is the item in question a category C, D,
crime-assist-question-isitcontrolleditem = Was stolen object a controlled item?
crime-assist-question-wassuspectinarestrictedlocation = Was the suspect in a restricted location, or anywhere the suspect did not have legal access to?
crime-assist-question-wasentrancelocked = Did the suspect force through a locked access point to get to the location?
crime-assist-question-questionwasithighsec = Was location that the suspect entered a High Security Area? (e.g. Bridge, Vault, Armory, Life support, AI etc)
crime-assist-question-didsuspectbreaksomething = Did the suspect break something?
crime-assist-question-weretheremanysuspects = Were there many suspects in a group causing a disturbance?
crime-assist-question-wasdamagesmall = Was the damage minor, or easily undone?
@@ -96,7 +95,7 @@ crime-assist-crimedetail-trespass = To enter into an area where one is not autho
crime-assist-crimedetail-vandalism = To deface or superficially damage public property, or property belonging to another person.
crime-assist-crimedetail-hooliganism = To intentionally and maliciously engage in disruptive conduct, where one refuses to cease.
crime-assist-crimedetail-assault = To cause physical harm or to effect unwanted physical contact on an Employee, without the apparent intent to kill them, or to threaten such actions with both capability and intent to do so.
crime-assist-crimedetail-breakingandentering = To break and enter into a high security area where one is not authorised nor invited, with intent to commit a crime within.
crime-assist-crimedetail-breakingandentering = To break and enter into an area where one is not authorised nor invited.
crime-assist-crimedetail-rioting = To partake in an unauthorised riotous, tumultuous, and disruptive public assembly that refuses to disperse after warning.
crime-assist-crimedetail-endangerment = To recklessly abandon obligations involving the continued wellbeing and/or protection of life and property, through malpractice, action, or inaction.
crime-assist-crimedetail-possession = To be in unauthorised possession of restricted items or items of particular danger.

Some files were not shown because too many files have changed in this diff Show More