From 1141f261ae1d0277f2555ae8a9b4dae5a90412db Mon Sep 17 00:00:00 2001 From: gluesniffler <159397573+gluesniffler@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:14:31 -0400 Subject: [PATCH 001/135] Adds PKA & Jetpack Module for Salvage Cyborgs (#550) # Description Gives salvage borgs a special jetpack module with half of the capacity of a normal mini-jetpack. Granting them about 2 minutes of thrust, which allows them to be more useful in space, partake in some rescue missions and to some extent be independent for a limited amount of time if something happens to the salvagers. It also adds a PKA module, which gives them a PKA which can't be wielded, leading to a hilarious accuracy penalty. ---

Media

Demo of the Modules [![Crafting demo, basic usage](https://i.ytimg.com/vi/k6xbEAtudVA/maxresdefault.jpg)](https://youtu.be/k6xbEAtudVA "PKA/Jetpack Borg Demo") Stormtrooper aim vs dragon AI [![Soloing space dragon AI, ft. stormtrooper aim](https://i.ytimg.com/vi/0e8iXbtD-Pc/maxresdefault.jpg)](https://www.youtube.com/watch?v=0e8iXbtD-Pc "Stormtrooper vs Space Dragon AI") Refillable jetpack module demo [![Refilling jetpack](https://i.ytimg.com/vi/y7Ie81NV2QM/maxresdefault.jpg)](https://youtu.be/y7Ie81NV2QM "Refill showcase of the jetpack module")

--- # Changelog :cl: - add: Added an unlockable PKA and Jetpack module to Salvage Cyborgs --------- Signed-off-by: gluesniffler <159397573+gluesniffler@users.noreply.github.com> --- .../Unary/EntitySystems/GasCanisterSystem.cs | 26 +++++++++++- .../Silicons/Borgs/BorgSystem.Modules.cs | 5 +++ .../Borgs/Components/BorgJetpackComponent.cs | 12 ++++++ .../Locale/en-US/research/technologies.ftl | 1 + .../Specific/Robotics/borg_modules.yml | 28 ++++++++++++ .../Entities/Objects/Tools/jetpacks.yml | 40 ++++++++++++++++++ .../Entities/Structures/Machines/lathe.yml | 2 + .../Storage/Canisters/gas_canisters.yml | 1 + .../Prototypes/Recipes/Lathes/robotics.yml | 24 +++++++++++ Resources/Prototypes/Research/industrial.yml | 13 ++++++ .../Robotics/borgmodule.rsi/icon-jetpack.png | Bin 0 -> 303 bytes .../Robotics/borgmodule.rsi/icon-pka.png | Bin 0 -> 299 bytes .../Robotics/borgmodule.rsi/meta.json | 6 +++ 13 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 Content.Server/Silicons/Borgs/Components/BorgJetpackComponent.cs create mode 100644 Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-jetpack.png create mode 100644 Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-pka.png diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs index 3e4340bf1db..d53e29c9499 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs @@ -15,6 +15,7 @@ using Content.Shared.Database; using Content.Shared.Interaction; using Content.Shared.Lock; +using Content.Server.Silicons.Borgs.Components; using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; @@ -91,6 +92,10 @@ private void DirtyUI(EntityUid uid, if (canister.GasTankSlot.Item != null) { var tank = canister.GasTankSlot.Item.Value; + if (TryComp(tank, out var jetpack) && jetpack.JetpackUid.HasValue) + { + tank = jetpack.JetpackUid.Value; + } var tankComponent = Comp(tank); tankLabel = Name(tank); tankPressure = tankComponent.Air.Pressure; @@ -163,7 +168,12 @@ private void OnCanisterUpdated(EntityUid uid, GasCanisterComponent canister, ref { if (canister.GasTankSlot.Item != null) { - var gasTank = Comp(canister.GasTankSlot.Item.Value); + var tank = canister.GasTankSlot.Item; + if (TryComp(tank, out var jetpack) && jetpack.JetpackUid.HasValue) + { + tank = jetpack.JetpackUid.Value; + } + var gasTank = Comp(tank.Value); _atmos.ReleaseGasTo(canister.Air, gasTank.Air, canister.ReleasePressure); } else @@ -233,7 +243,19 @@ private void OnCanisterInsertAttempt(EntityUid uid, GasCanisterComponent compone if (args.Slot.ID != component.ContainerName || args.User == null) return; - if (!TryComp(args.Item, out var gasTank) || gasTank.IsValveOpen) + var tank = args.Item; + + if (TryComp(tank, out var jetpack)) + { + if (!jetpack.JetpackUid.HasValue) + { + args.Cancelled = true; + return; + } + tank = jetpack.JetpackUid.Value; + } + + if (!TryComp(tank, out var gasTank) || gasTank.IsValveOpen) { args.Cancelled = true; return; diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs index cc57c34c475..7ede2342428 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs @@ -2,6 +2,7 @@ using Content.Shared.Hands.Components; using Content.Shared.Interaction.Components; using Content.Shared.Silicons.Borgs.Components; +using Content.Server.Silicons.Borgs.Components; using Robust.Shared.Containers; namespace Content.Server.Silicons.Borgs; @@ -190,6 +191,10 @@ private void ProvideItems(EntityUid chassis, EntityUid uid, BorgChassisComponent if (!component.ItemsCreated) { item = Spawn(itemProto, xform.Coordinates); + if (TryComp(uid, out var module)) + { + module.JetpackUid = item; + } } else { diff --git a/Content.Server/Silicons/Borgs/Components/BorgJetpackComponent.cs b/Content.Server/Silicons/Borgs/Components/BorgJetpackComponent.cs new file mode 100644 index 00000000000..3a71dd3a501 --- /dev/null +++ b/Content.Server/Silicons/Borgs/Components/BorgJetpackComponent.cs @@ -0,0 +1,12 @@ +using Robust.Shared.GameStates; + +namespace Content.Server.Silicons.Borgs.Components; + +/// +/// Server side indicator for a jetpack module. Used as conditional for inserting in canisters. +/// +[RegisterComponent] +public sealed partial class BorgJetpackComponent : Component +{ + public EntityUid? JetpackUid = null; +} \ No newline at end of file diff --git a/Resources/Locale/en-US/research/technologies.ftl b/Resources/Locale/en-US/research/technologies.ftl index a68f9e80b4e..96cb2039116 100644 --- a/Resources/Locale/en-US/research/technologies.ftl +++ b/Resources/Locale/en-US/research/technologies.ftl @@ -16,6 +16,7 @@ research-technology-shuttlecraft = Shuttlecraft research-technology-ripley-aplu = Ripley APLU research-technology-advanced-atmospherics = Advanced Atmospherics research-technology-advanced-tools = Advanced Tools +research-technology-mechanized-salvaging = Mechanized Salvaging research-technology-super-powercells = Super Powercells research-technology-bluespace-storage = Bluespace Storage research-technology-portable-fission = Portable Fission diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml index d37523bd735..a7cf7ad5c80 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml @@ -210,6 +210,34 @@ - Crowbar - RadioHandheld +- type: entity + id: BorgModuleJetpack + parent: [ BaseBorgModuleCargo, BaseProviderBorgModule ] + name: jetpack cyborg module + description: A piece of tech that gives cyborgs new abilities. Needs to be loaded by a cyborg before you can refill the jetpack. + components: + - type: Sprite + layers: + - state: cargo + - state: icon-jetpack + - type: BorgJetpack + - type: ItemBorgModule + items: + - JetpackMicroFilled + +- type: entity + id: BorgModulePka + parent: [ BaseBorgModuleCargo, BaseProviderBorgModule ] + name: proto kinetic accelerator cyborg module + components: + - type: Sprite + layers: + - state: cargo + - state: icon-pka + - type: ItemBorgModule + items: + - WeaponProtoKineticAccelerator + - type: entity id: BorgModuleGrapplingGun parent: [ BaseBorgModuleCargo, BaseProviderBorgModule ] diff --git a/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml index d0ac9c7a78a..a4c103847fe 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml @@ -295,3 +295,43 @@ moles: - 1.025689525 # oxygen - 1.025689525 # nitrogen + +#Empty micro - Used in the Cyborg module, visually the same as mini jetpack. +- type: entity + id: JetpackMicro + parent: BaseJetpack + name: micro jetpack + suffix: Empty + components: + - type: Item + sprite: Objects/Tanks/Jetpacks/mini.rsi + - type: Sprite + sprite: Objects/Tanks/Jetpacks/mini.rsi + - type: Clothing + sprite: Objects/Tanks/Jetpacks/mini.rsi + slots: + - Back + - suitStorage + - Belt + - type: GasTank + outputPressure: 42.6 + air: + volume: 0.75 + + +# Filled micro +- type: entity + id: JetpackMicroFilled + parent: JetpackMicro + name: micro jetpack + suffix: Filled + components: + - type: GasTank + outputPressure: 42.6 + air: + # 2 minutes of thrust + volume: 0.75 + temperature: 293.15 + moles: + - 0.153853429 # oxygen + - 0.153853429 # nitrogen diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 5d727207fe6..7e861db0d5a 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -594,6 +594,8 @@ - BorgModuleAdvancedTool - BorgModuleGPS - BorgModuleRCD + - BorgModuleJetpack + - BorgModulePka - BorgModuleArtifact - BorgModuleAnomaly - BorgModuleGardening diff --git a/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml b/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml index cd44f5f585a..52b008c7f2c 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml @@ -98,6 +98,7 @@ whitelist: components: - GasTank + - BorgJetpack - type: StaticPrice price: 1000 - type: AccessReader diff --git a/Resources/Prototypes/Recipes/Lathes/robotics.yml b/Resources/Prototypes/Recipes/Lathes/robotics.yml index f42e2851c78..bf6f479703e 100644 --- a/Resources/Prototypes/Recipes/Lathes/robotics.yml +++ b/Resources/Prototypes/Recipes/Lathes/robotics.yml @@ -612,3 +612,27 @@ Steel: 250 Glass: 250 Plastic: 250 + +- type: latheRecipe + id: BorgModulePka + result: BorgModulePka + category: Robotics + completetime: 3 + materials: + Steel: 1000 + Glass: 500 + Plastic: 500 + Silver: 100 + +- type: latheRecipe + id: BorgModuleJetpack + result: BorgModuleJetpack + category: Robotics + completetime: 3 + materials: + Steel: 250 + Glass: 250 + Plastic: 250 + Gold: 100 + Plasma: 1000 + diff --git a/Resources/Prototypes/Research/industrial.yml b/Resources/Prototypes/Research/industrial.yml index edcc9c66364..33377f52520 100644 --- a/Resources/Prototypes/Research/industrial.yml +++ b/Resources/Prototypes/Research/industrial.yml @@ -179,6 +179,19 @@ - BorgModuleAdvancedTool - BorgModuleRCD +- type: technology + id: MechanizedSalvaging + name: research-technology-mechanized-salvaging + icon: + sprite: Mobs/Silicon/chassis.rsi + state: miner + discipline: Industrial + tier: 2 + cost: 10000 + recipeUnlocks: + - BorgModulePka + - BorgModuleJetpack + # Tier 3 - type: technology diff --git a/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-jetpack.png b/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-jetpack.png new file mode 100644 index 0000000000000000000000000000000000000000..ec7033ec2fed40d598cfbe156ccc2dd8030c3855 GIT binary patch literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oArNM~bhqvgQ1GFr zi(^QHdvbyV>taO%DJB?kK=FXbs=wuZ`hU*rYqTwV`}lV_kJhx0DzlHftYWVFmzeP5 z>ud4D{0hpO)ASC1m)|d0_y6D756|UKmNl%(p5w_ebcip%-Lt@(6$WsMB4)L?~ZHs72j;rE1bH=;zhy6;oiQ-K6 z_tm96u&EGS^E0iDe?}Vnr~118Uh?cecFi(o@q5PtaO%DJB?kK=FXbs=wuZ`hU*rYqTwV`}lV_kJhx0DzlHftYS`>*8cm7 z!JfU9eGkvHN+&3n>D=&H6`1f<=gAAB6MIi5tXDf|kbF>(?cDTdJl0E>8Mo}vnvg8Q zd{VLC*Bj9`j+wDM`|Imdew_Ozo}>BPSh+3w`uxks8MCjwPq}d6Qo; Date: Tue, 6 Aug 2024 01:15:00 +0000 Subject: [PATCH 002/135] Automatic Changelog Update (#550) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a0631c5f9d8..35142b8bbfa 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4934,3 +4934,9 @@ Entries: message: Lamiae should now be rendered much better. id: 6217 time: '2024-08-05T17:15:51.0000000+00:00' +- author: gluesniffler + changes: + - type: Add + message: Added an unlockable PKA and Jetpack module to Salvage Cyborgs + id: 6218 + time: '2024-08-06T01:14:31.0000000+00:00' From 981b7dd9e3ce6be45911d29b605593cf7b48ea34 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Tue, 6 Aug 2024 00:52:32 -0400 Subject: [PATCH 003/135] Rebase Blood Drinker System, Arachne, Oneirophage (#438) # Description This is a simple rebase of the Blood Drinker System, and its related features that have been commented out and/or omitted due to its lack of rebase. I am NOT substantially updating any of this code at this time, outside of the barest minimum updates needed to make it run in the first place. The reason I am doing this is that I require the Blood Drinker system functional as a prerequisite for future features, and I will update or refactor it when needed. Arachne are still pending a Full Rework, but that is beyond the scope of this PR. # TODO - [x] Make the code functional - [x] Port Arachne - [x] Uncomment Oneirophages - [x] Re-add Oneirophage midround event # Changelog :cl: - add: Arachne have been reimplemented! - add: Oneirophages are back! --------- Signed-off-by: VMSolidus --- Content.Server/Arachne/ArachneSystem.cs | 231 ++++++++++++++++ Content.Server/Arachne/CocoonComponent.cs | 13 + .../Vampire/BloodSuckedComponent.cs | 9 + .../Vampire/BloodSuckerComponent.cs | 44 +++ Content.Server/Vampire/BloodSuckerSystem.cs | 213 ++++++++++++++ .../BloodSuckerGlandInjectorComponent.cs | 23 ++ .../BloodSuckerGlandInjectorSystem.cs | 39 +++ Content.Shared/Arachne/ArachneComponent.cs | 21 ++ Content.Shared/Arachne/Events.cs | 11 + Content.Shared/Arachne/WebComponent.cs | 8 + .../Vampiric/BloodSuckDoAfterEvent.cs | 10 + Resources/Locale/en-US/abilities/arachne.ftl | 13 + .../Locale/en-US/abilities/bloodsucker.ftl | 19 ++ Resources/Locale/en-US/species/species.ftl | 1 + .../Chemistry/metabolizer_types.yml | 6 +- Resources/Prototypes/Damage/containers.yml | 10 + Resources/Prototypes/Damage/modifier_sets.yml | 13 + .../Entities/Clothing/OuterClothing/armor.yml | 6 + .../OuterClothing/base_clothingouter.yml | 1 + .../Entities/Clothing/OuterClothing/suits.yml | 20 ++ .../Entities/Mobs/Player/arachne.yml | 35 +++ .../Entities/Mobs/Species/arachne.yml | 220 +++++++++++++++ Resources/Prototypes/GameRules/events.yml | 16 ++ .../anytaur_inventory_template.yml | 112 ++++++++ .../Entities/Body/Mechanisms/vampiric.yml | 22 ++ .../Entities/Body/Parts/spider.yml | 24 +- .../Entities/Body/Prototypes/arachne.yml | 63 +++++ .../Body/Prototypes/vampiricanimal.yml | 43 +++ .../Entities/Markers/Spawners/ghost_roles.yml | 40 +-- .../Entities/Mobs/NPCs/mutants.yml | 259 +++++++++--------- .../Entities/Structures/Webbing/webs.yml | 93 +++++++ Resources/Prototypes/Reagents/biological.yml | 23 ++ Resources/Prototypes/Species/arachne.yml | 50 ++++ Resources/Prototypes/tags.yml | 9 + .../female_full.png | Bin 0 -> 140 bytes .../female_none.png | Bin 0 -> 112 bytes .../female_top.png | Bin 0 -> 140 bytes .../anytaur_masking_helpers.rsi/full.png | Bin 0 -> 112 bytes .../anytaur_masking_helpers.rsi/male_full.png | Bin 0 -> 112 bytes .../anytaur_masking_helpers.rsi/male_none.png | Bin 0 -> 112 bytes .../anytaur_masking_helpers.rsi/male_top.png | Bin 0 -> 112 bytes .../anytaur_masking_helpers.rsi/meta.json | 59 ++++ .../anytaur_masking_helpers.rsi/none.png | Bin 0 -> 112 bytes .../anytaur_masking_helpers.rsi/top.png | Bin 0 -> 112 bytes .../unisex_full.png | Bin 0 -> 112 bytes .../unisex_none.png | Bin 0 -> 112 bytes .../unisex_top.png | Bin 0 -> 112 bytes .../Customization/spidereyes.rsi/eyes.png | Bin 0 -> 5070 bytes .../Customization/spidereyes.rsi/meta.json | 15 + .../Mobs/Species/arachne.rsi/meta.json | 19 ++ .../Mobs/Species/arachne.rsi/spider_body.png | Bin 0 -> 3288 bytes .../Species/arachne.rsi/spider_body_front.png | Bin 0 -> 761 bytes .../Textures/Mobs/Species/eyes.rsi/eyes.png | Bin 0 -> 5553 bytes .../Textures/Mobs/Species/eyes.rsi/meta.json | 15 + .../Structures/cocoon.rsi/cocoon1.png | Bin 0 -> 669 bytes .../Structures/cocoon.rsi/cocoon2.png | Bin 0 -> 636 bytes .../Structures/cocoon.rsi/cocoon3.png | Bin 0 -> 578 bytes .../Structures/cocoon.rsi/cocoon_large1.png | Bin 0 -> 762 bytes .../Structures/cocoon.rsi/cocoon_large2.png | Bin 0 -> 683 bytes .../Structures/cocoon.rsi/cocoon_large3.png | Bin 0 -> 876 bytes .../Structures/cocoon.rsi/meta.json | 35 +++ 61 files changed, 1704 insertions(+), 159 deletions(-) create mode 100644 Content.Server/Arachne/ArachneSystem.cs create mode 100644 Content.Server/Arachne/CocoonComponent.cs create mode 100644 Content.Server/Vampire/BloodSuckedComponent.cs create mode 100644 Content.Server/Vampire/BloodSuckerComponent.cs create mode 100644 Content.Server/Vampire/BloodSuckerSystem.cs create mode 100644 Content.Server/Vampire/Injector/BloodSuckerGlandInjectorComponent.cs create mode 100644 Content.Server/Vampire/Injector/BloodSuckerGlandInjectorSystem.cs create mode 100644 Content.Shared/Arachne/ArachneComponent.cs create mode 100644 Content.Shared/Arachne/Events.cs create mode 100644 Content.Shared/Arachne/WebComponent.cs create mode 100644 Content.Shared/Vampiric/BloodSuckDoAfterEvent.cs create mode 100644 Resources/Locale/en-US/abilities/arachne.ftl create mode 100644 Resources/Locale/en-US/abilities/bloodsucker.ftl create mode 100644 Resources/Prototypes/Entities/Mobs/Player/arachne.yml create mode 100644 Resources/Prototypes/Entities/Mobs/Species/arachne.yml create mode 100644 Resources/Prototypes/InventoryTemplates/anytaur_inventory_template.yml create mode 100644 Resources/Prototypes/Nyanotrasen/Entities/Body/Mechanisms/vampiric.yml create mode 100644 Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/arachne.yml create mode 100644 Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/vampiricanimal.yml create mode 100644 Resources/Prototypes/Nyanotrasen/Entities/Structures/Webbing/webs.yml create mode 100644 Resources/Prototypes/Species/arachne.yml create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_full.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_none.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_top.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/full.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_full.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_none.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_top.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/none.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/top.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_full.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_none.png create mode 100644 Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_top.png create mode 100644 Resources/Textures/Mobs/Customization/spidereyes.rsi/eyes.png create mode 100644 Resources/Textures/Mobs/Customization/spidereyes.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Species/arachne.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Species/arachne.rsi/spider_body.png create mode 100644 Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png create mode 100644 Resources/Textures/Mobs/Species/eyes.rsi/eyes.png create mode 100644 Resources/Textures/Mobs/Species/eyes.rsi/meta.json create mode 100644 Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png create mode 100644 Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon2.png create mode 100644 Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon3.png create mode 100644 Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png create mode 100644 Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large2.png create mode 100644 Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png create mode 100644 Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/meta.json diff --git a/Content.Server/Arachne/ArachneSystem.cs b/Content.Server/Arachne/ArachneSystem.cs new file mode 100644 index 00000000000..9cdefb441be --- /dev/null +++ b/Content.Server/Arachne/ArachneSystem.cs @@ -0,0 +1,231 @@ +using Content.Shared.Arachne; +using Content.Shared.Actions; +using Content.Shared.IdentityManagement; +using Content.Shared.Verbs; +using Content.Shared.Buckle.Components; +using Content.Shared.DoAfter; +using Content.Shared.Stunnable; +using Content.Shared.Eye.Blinding.Systems; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Damage; +using Content.Shared.Inventory; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Humanoid; +using Content.Shared.Nutrition.EntitySystems; +using Content.Server.Buckle.Systems; +using Content.Server.Popups; +using Content.Server.DoAfter; +using Content.Server.Body.Components; +using Content.Server.Vampiric; +using Content.Server.Speech.Components; +using Robust.Shared.Physics.Components; +using Robust.Shared.Containers; +using Robust.Shared.Map; +using Robust.Shared.Utility; +using Robust.Server.Console; + +namespace Content.Server.Arachne +{ + public sealed class ArachneSystem : EntitySystem + { + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly BuckleSystem _buckleSystem = default!; + [Dependency] private readonly ItemSlotsSystem _itemSlots = default!; + [Dependency] private readonly BlindableSystem _blindableSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + + [Dependency] private readonly IServerConsoleHost _host = default!; + [Dependency] private readonly BloodSuckerSystem _bloodSuckerSystem = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + + private const string BodySlot = "body_slot"; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent>(AddCocoonVerb); + + SubscribeLocalEvent(OnCocEntInserted); + SubscribeLocalEvent(OnCocEntRemoved); + SubscribeLocalEvent(OnDamageChanged); + SubscribeLocalEvent>(AddSuccVerb); + SubscribeLocalEvent(OnCocoonDoAfter); + } + + private void AddCocoonVerb(EntityUid uid, ArachneComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + if (args.Target == uid) + return; + + if (!TryComp(args.Target, out var bloodstream)) + return; + + if (bloodstream.BloodReagent != component.WebBloodReagent) + return; + + InnateVerb verb = new() + { + Act = () => + { + StartCocooning(uid, component, args.Target); + }, + Text = Loc.GetString("cocoon"), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnCocEntInserted(EntityUid uid, CocoonComponent component, EntInsertedIntoContainerMessage args) + { + _blindableSystem.UpdateIsBlind(args.Entity); + EnsureComp(args.Entity); + + if (TryComp(args.Entity, out var currentAccent)) + { + component.WasReplacementAccent = true; + component.OldAccent = currentAccent.Accent; + currentAccent.Accent = "mumble"; + } else + { + component.WasReplacementAccent = false; + var replacement = EnsureComp(args.Entity); + replacement.Accent = "mumble"; + } + } + + private void OnCocEntRemoved(EntityUid uid, CocoonComponent component, EntRemovedFromContainerMessage args) + { + if (component.WasReplacementAccent && TryComp(args.Entity, out var replacement)) + { + replacement.Accent = component.OldAccent; + } else + { + RemComp(args.Entity); + } + + RemComp(args.Entity); + _blindableSystem.UpdateIsBlind(args.Entity); + } + + private void OnDamageChanged(EntityUid uid, CocoonComponent component, DamageChangedEvent args) + { + if (!args.DamageIncreased) + return; + + if (args.DamageDelta == null) + return; + + var body = _itemSlots.GetItemOrNull(uid, BodySlot); + + if (body == null) + return; + + var damage = args.DamageDelta * component.DamagePassthrough; + _damageableSystem.TryChangeDamage(body, damage); + } + + private void AddSuccVerb(EntityUid uid, CocoonComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + if (!TryComp(args.User, out var sucker)) + return; + + if (!sucker.WebRequired) + return; + + var victim = _itemSlots.GetItemOrNull(uid, BodySlot); + + if (victim == null) + return; + + if (!TryComp(victim, out var stream)) + return; + + AlternativeVerb verb = new() + { + Act = () => + { + _bloodSuckerSystem.StartSuccDoAfter(args.User, victim.Value, sucker, stream, false); // start doafter + }, + Text = Loc.GetString("action-name-suck-blood"), + Icon = new SpriteSpecifier.Texture(new ("/Textures/Nyanotrasen/Icons/verbiconfangs.png")), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnEntRemoved(EntityUid uid, WebComponent web, EntRemovedFromContainerMessage args) + { + if (!TryComp(uid, out var strap)) + return; + + if (HasComp(args.Entity)) + _buckleSystem.StrapSetEnabled(uid, false, strap); + } + + private void StartCocooning(EntityUid uid, ArachneComponent component, EntityUid target) + { + _popupSystem.PopupEntity(Loc.GetString("cocoon-start-third-person", ("target", Identity.Entity(target, EntityManager)), ("spider", Identity.Entity(uid, EntityManager))), uid, + Shared.Popups.PopupType.MediumCaution); + + _popupSystem.PopupEntity(Loc.GetString("cocoon-start-second-person", ("target", Identity.Entity(target, EntityManager))), uid, uid, Shared.Popups.PopupType.Medium); + + var delay = component.CocoonDelay; + + if (HasComp(target)) + delay *= component.CocoonKnockdownMultiplier; + + // Is it good practice to use empty data just to disambiguate doafters + // Who knows, there's no docs! + var ev = new ArachneCocoonDoAfterEvent(); + + var args = new DoAfterArgs(EntityManager, uid, delay, ev, uid, target: target) + { + BreakOnUserMove = true, + BreakOnTargetMove = true, + }; + + _doAfter.TryStartDoAfter(args); + } + + private void OnCocoonDoAfter(EntityUid uid, ArachneComponent component, ArachneCocoonDoAfterEvent args) + { + if (args.Handled || args.Cancelled || args.Args.Target == null) + return; + + var spawnProto = HasComp(args.Args.Target) ? "CocoonedHumanoid" : "CocoonSmall"; + Transform(args.Args.Target.Value).AttachToGridOrMap(); + var cocoon = Spawn(spawnProto, Transform(args.Args.Target.Value).Coordinates); + + if (!TryComp(cocoon, out var slots)) + return; + + // todo: our species should use scale visuals probably... + // TODO: We need a client-accessible notion of scale influence here. + /* if (spawnProto == "CocoonedHumanoid" && TryComp(args.Args.Target.Value, out var sprite)) */ + /* { */ + /* // why the fuck is this only available as a console command. */ + /* _host.ExecuteCommand(null, "scale " + cocoon + " " + sprite.Scale.Y); */ + if (TryComp(args.Args.Target.Value, out var physics)) + { + var scale = Math.Clamp(1 / (35 / physics.FixturesMass), 0.35, 2.5); + _host.ExecuteCommand(null, "scale " + cocoon + " " + scale); + } + _itemSlots.SetLock(cocoon, BodySlot, false, slots); + _itemSlots.TryInsert(cocoon, BodySlot, args.Args.Target.Value, args.Args.User); + _itemSlots.SetLock(cocoon, BodySlot, true, slots); + + var impact = (spawnProto == "CocoonedHumanoid") ? LogImpact.High : LogImpact.Medium; + + _adminLogger.Add(LogType.Action, impact, $"{ToPrettyString(args.Args.User):player} cocooned {ToPrettyString(args.Args.Target.Value):target}"); + args.Handled = true; + } + } +} diff --git a/Content.Server/Arachne/CocoonComponent.cs b/Content.Server/Arachne/CocoonComponent.cs new file mode 100644 index 00000000000..42ecf27971a --- /dev/null +++ b/Content.Server/Arachne/CocoonComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Server.Arachne +{ + [RegisterComponent] + public sealed partial class CocoonComponent : Component + { + public bool WasReplacementAccent = false; + + public string OldAccent = ""; + + [DataField("damagePassthrough")] + public float DamagePassthrough = 0.5f; + } +} diff --git a/Content.Server/Vampire/BloodSuckedComponent.cs b/Content.Server/Vampire/BloodSuckedComponent.cs new file mode 100644 index 00000000000..d7e402cd98a --- /dev/null +++ b/Content.Server/Vampire/BloodSuckedComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Vampiric +{ + /// + /// For entities who have been succed. + /// + [RegisterComponent] + public sealed partial class BloodSuckedComponent : Component + {} +} diff --git a/Content.Server/Vampire/BloodSuckerComponent.cs b/Content.Server/Vampire/BloodSuckerComponent.cs new file mode 100644 index 00000000000..f5619d1cb49 --- /dev/null +++ b/Content.Server/Vampire/BloodSuckerComponent.cs @@ -0,0 +1,44 @@ +namespace Content.Server.Vampiric +{ + [RegisterComponent] + public sealed partial class BloodSuckerComponent : Component + { + /// + /// How much to succ each time we succ. + /// + [DataField("unitsToSucc")] + public float UnitsToSucc = 20f; + + /// + /// The time (in seconds) that it takes to succ an entity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan Delay = TimeSpan.FromSeconds(4); + + // ***INJECT WHEN SUCC*** + + /// + /// Whether to inject chems into a chemstream when we suck something. + /// + [DataField("injectWhenSucc")] + public bool InjectWhenSucc = false; + + /// + /// How many units of our injected chem to inject. + /// + [DataField("unitsToInject")] + public float UnitsToInject = 5; + + /// + /// Which reagent to inject. + /// + [DataField("injectReagent")] + public string InjectReagent = ""; + + /// + /// Whether we need to web the thing up first... + /// + [DataField("webRequired")] + public bool WebRequired = false; + } +} diff --git a/Content.Server/Vampire/BloodSuckerSystem.cs b/Content.Server/Vampire/BloodSuckerSystem.cs new file mode 100644 index 00000000000..a63334a8943 --- /dev/null +++ b/Content.Server/Vampire/BloodSuckerSystem.cs @@ -0,0 +1,213 @@ +using Content.Shared.Verbs; +using Content.Shared.Damage; +using Content.Shared.DoAfter; +using Content.Shared.Damage.Prototypes; +using Content.Shared.Interaction; +using Content.Shared.Inventory; +using Content.Shared.Administration.Logs; +using Content.Shared.Vampiric; +using Content.Server.Atmos.Components; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Shared.Chemistry.EntitySystems; +using Content.Server.Popups; +using Content.Server.HealthExaminable; +using Content.Server.DoAfter; +using Content.Server.Nutrition.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Utility; + +namespace Content.Server.Vampiric +{ + public sealed class BloodSuckerSystem : EntitySystem + { + [Dependency] private readonly BodySystem _bodySystem = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionSystem = default!; + [Dependency] private readonly PopupSystem _popups = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly StomachSystem _stomachSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly InventorySystem _inventorySystem = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent>(AddSuccVerb); + SubscribeLocalEvent(OnHealthExamined); + SubscribeLocalEvent(OnDamageChanged); + SubscribeLocalEvent(OnDoAfter); + } + + private void AddSuccVerb(EntityUid uid, BloodSuckerComponent component, GetVerbsEvent args) + { + if (args.User == args.Target) + return; + if (component.WebRequired) + return; // handled elsewhere + if (!TryComp(args.Target, out var bloodstream)) + return; + if (!args.CanAccess) + return; + + InnateVerb verb = new() + { + Act = () => + { + StartSuccDoAfter(uid, args.Target, component, bloodstream); // start doafter + }, + Text = Loc.GetString("action-name-suck-blood"), + Icon = new SpriteSpecifier.Texture(new ("/Textures/Nyanotrasen/Icons/verbiconfangs.png")), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnHealthExamined(EntityUid uid, BloodSuckedComponent component, HealthBeingExaminedEvent args) + { + args.Message.PushNewline(); + args.Message.AddMarkup(Loc.GetString("bloodsucked-health-examine", ("target", uid))); + } + + private void OnDamageChanged(EntityUid uid, BloodSuckedComponent component, DamageChangedEvent args) + { + if (args.DamageIncreased) + return; + + if (_prototypeManager.TryIndex("Brute", out var brute) && args.Damageable.Damage.TryGetDamageInGroup(brute, out var bruteTotal) + && _prototypeManager.TryIndex("Airloss", out var airloss) && args.Damageable.Damage.TryGetDamageInGroup(airloss, out var airlossTotal)) + { + if (bruteTotal == 0 && airlossTotal == 0) + RemComp(uid); + } + } + + private void OnDoAfter(EntityUid uid, BloodSuckerComponent component, BloodSuckDoAfterEvent args) + { + if (args.Cancelled || args.Handled || args.Args.Target == null) + return; + + args.Handled = TrySucc(uid, args.Args.Target.Value); + } + + public void StartSuccDoAfter(EntityUid bloodsucker, EntityUid victim, BloodSuckerComponent? bloodSuckerComponent = null, BloodstreamComponent? stream = null, bool doChecks = true) + { + if (!Resolve(bloodsucker, ref bloodSuckerComponent)) + return; + + if (!Resolve(victim, ref stream)) + return; + + if (doChecks) + { + if (!_interactionSystem.InRangeUnobstructed(bloodsucker, victim)) + { + return; + } + + if (_inventorySystem.TryGetSlotEntity(victim, "head", out var headUid) && HasComp(headUid)) + { + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-helmet", ("helmet", headUid)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + return; + } + + if (_inventorySystem.TryGetSlotEntity(bloodsucker, "mask", out var maskUid) && + EntityManager.TryGetComponent(maskUid, out var blocker) && + blocker.Enabled) + { + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-mask", ("mask", maskUid)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + return; + } + } + + if (stream.BloodReagent != "Blood") + { + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-not-blood", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + return; + } + + if (_solutionSystem.PercentFull(stream.Owner) != 0) + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-no-blood", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + + _popups.PopupEntity(Loc.GetString("bloodsucker-doafter-start-victim", ("sucker", bloodsucker)), victim, victim, Shared.Popups.PopupType.LargeCaution); + _popups.PopupEntity(Loc.GetString("bloodsucker-doafter-start", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + + var ev = new BloodSuckDoAfterEvent(); + var args = new DoAfterArgs(EntityManager, bloodsucker, bloodSuckerComponent.Delay, ev, bloodsucker, target: victim) + { + BreakOnTargetMove = true, + BreakOnUserMove = false, + DistanceThreshold = 2f, + NeedHand = false + }; + + _doAfter.TryStartDoAfter(args); + } + + public bool TrySucc(EntityUid bloodsucker, EntityUid victim, BloodSuckerComponent? bloodsuckerComp = null) + { + // Is bloodsucker a bloodsucker? + if (!Resolve(bloodsucker, ref bloodsuckerComp)) + return false; + + // Does victim have a bloodstream? + if (!TryComp(victim, out var bloodstream)) + return false; + + // No blood left, yikes. + if (_bloodstreamSystem.GetBloodLevelPercentage(victim, bloodstream) == 0.0f) + return false; + + // Does bloodsucker have a stomach? + var stomachList = _bodySystem.GetBodyOrganComponents(bloodsucker); + if (stomachList.Count == 0) + return false; + + if (!_solutionSystem.TryGetSolution(stomachList[0].Comp.Owner, StomachSystem.DefaultSolutionName, out var stomachSolution)) + return false; + + // Are we too full? + + if (_solutionSystem.PercentFull(bloodsucker) >= 1) + { + _popups.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough"), bloodsucker, bloodsucker, Shared.Popups.PopupType.MediumCaution); + return false; + } + + _adminLogger.Add(Shared.Database.LogType.MeleeHit, Shared.Database.LogImpact.Medium, $"{ToPrettyString(bloodsucker):player} sucked blood from {ToPrettyString(victim):target}"); + + // All good, succ time. + _audio.PlayPvs("/Audio/Items/drink.ogg", bloodsucker); + _popups.PopupEntity(Loc.GetString("bloodsucker-blood-sucked-victim", ("sucker", bloodsucker)), victim, victim, Shared.Popups.PopupType.LargeCaution); + _popups.PopupEntity(Loc.GetString("bloodsucker-blood-sucked", ("target", victim)), bloodsucker, bloodsucker, Shared.Popups.PopupType.Medium); + EnsureComp(victim); + + // Make everything actually ingest. + if (bloodstream.BloodSolution == null) + return false; + + var temp = _solutionSystem.SplitSolution(bloodstream.BloodSolution.Value, bloodsuckerComp.UnitsToSucc); + _stomachSystem.TryTransferSolution(stomachList[0].Comp.Owner, temp, stomachList[0].Comp); + + // Add a little pierce + DamageSpecifier damage = new(); + damage.DamageDict.Add("Piercing", 1); // Slowly accumulate enough to gib after like half an hour + + _damageableSystem.TryChangeDamage(victim, damage, true, true); + + //I'm not porting the nocturine gland, this code is deprecated, and will be reworked at a later date. + //if (bloodsuckerComp.InjectWhenSucc && _solutionSystem.TryGetInjectableSolution(victim, out var injectable)) + //{ + // _solutionSystem.TryAddReagent(victim, injectable, bloodsuckerComp.InjectReagent, bloodsuckerComp.UnitsToInject, out var acceptedQuantity); + //} + return true; + } + + private record struct BloodSuckData() + {} + } +} diff --git a/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorComponent.cs b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorComponent.cs new file mode 100644 index 00000000000..1a3c9b1588a --- /dev/null +++ b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorComponent.cs @@ -0,0 +1,23 @@ +namespace Content.Server.Vampiric +{ + [RegisterComponent] + /// + /// Item that gives a bloodsucker injection glands (for poison, usually) + /// + public sealed partial class BloodSuckerGlandInjectorComponent : Component + { + public bool Used = false; + + /// + /// How many units of our injected chem to inject. + /// + [DataField("unitsToInject")] + public float UnitsToInject = 5; + + /// + /// Which reagent to inject. + /// + [DataField("injectReagent")] + public string InjectReagent = ""; + } +} diff --git a/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorSystem.cs b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorSystem.cs new file mode 100644 index 00000000000..d2a92f24be6 --- /dev/null +++ b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorSystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Popups; +using Content.Shared.Interaction; + +namespace Content.Server.Vampiric +{ + public sealed class BloodSuckerGlandInjectorSystem : EntitySystem + { + [Dependency] private readonly PopupSystem _popupSystem = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAfterInteract); + } + + private void OnAfterInteract(EntityUid uid, BloodSuckerGlandInjectorComponent component, AfterInteractEvent args) + { + if (component.Used) + return; + + if (!args.CanReach) + return; + + if (!TryComp(args.Target, out var bloodSuckerComponent)) + return; + + // They already have one. + if (bloodSuckerComponent.InjectWhenSucc) + return; + + bloodSuckerComponent.InjectWhenSucc = true; + bloodSuckerComponent.InjectReagent = component.InjectReagent; + bloodSuckerComponent.UnitsToInject = component.UnitsToInject; + component.Used = true; + QueueDel(uid); + + _popupSystem.PopupEntity(Loc.GetString("bloodsucker-glands-throb"), args.Target.Value, args.Target.Value); + } + } +} diff --git a/Content.Shared/Arachne/ArachneComponent.cs b/Content.Shared/Arachne/ArachneComponent.cs new file mode 100644 index 00000000000..04c369cc456 --- /dev/null +++ b/Content.Shared/Arachne/ArachneComponent.cs @@ -0,0 +1,21 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Arachne +{ + [RegisterComponent, NetworkedComponent] + public sealed partial class ArachneComponent : Component + { + [DataField("cocoonDelay")] + public float CocoonDelay = 12f; + + [DataField("cocoonKnockdownMultiplier")] + public float CocoonKnockdownMultiplier = 0.5f; + + /// + /// Blood reagent required to web up a mob. + /// + + [DataField("webBloodReagent")] + public string WebBloodReagent = "Blood"; + } +} diff --git a/Content.Shared/Arachne/Events.cs b/Content.Shared/Arachne/Events.cs new file mode 100644 index 00000000000..02001286ac6 --- /dev/null +++ b/Content.Shared/Arachne/Events.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Map; +using Robust.Shared.Serialization; +using Content.Shared.DoAfter; + +namespace Content.Shared.Arachne +{ + [Serializable, NetSerializable] + public sealed partial class ArachneCocoonDoAfterEvent : SimpleDoAfterEvent + { + } +} diff --git a/Content.Shared/Arachne/WebComponent.cs b/Content.Shared/Arachne/WebComponent.cs new file mode 100644 index 00000000000..c8284f39434 --- /dev/null +++ b/Content.Shared/Arachne/WebComponent.cs @@ -0,0 +1,8 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Arachne +{ + [RegisterComponent, NetworkedComponent] + public sealed partial class WebComponent : Component + {} +} diff --git a/Content.Shared/Vampiric/BloodSuckDoAfterEvent.cs b/Content.Shared/Vampiric/BloodSuckDoAfterEvent.cs new file mode 100644 index 00000000000..6aadc258d73 --- /dev/null +++ b/Content.Shared/Vampiric/BloodSuckDoAfterEvent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.Serialization; +using Content.Shared.DoAfter; + +namespace Content.Shared.Vampiric +{ + [Serializable, NetSerializable] + public sealed partial class BloodSuckDoAfterEvent : SimpleDoAfterEvent + { + } +} diff --git a/Resources/Locale/en-US/abilities/arachne.ftl b/Resources/Locale/en-US/abilities/arachne.ftl new file mode 100644 index 00000000000..6f6348d7212 --- /dev/null +++ b/Resources/Locale/en-US/abilities/arachne.ftl @@ -0,0 +1,13 @@ +action-name-spin-web = Spin Web +action-desc-spin-web = Use your spinnerets to make a spider web in the current tile. Makes you hungrier and thirstier. +action-name-spin-web-space = You can't spin a web in space! +action-name-spin-web-blocked = There's no room for a web here. +spin-web-action-hungry = You're too hungry to spin a web! +spin-web-action-thirsty = You're too thirsty to spin a web! +spin-web-start-second-person = You start spinning a web. +spin-web-start-third-person = {CAPITALIZE(THE($spider))} starts spinning a web! +cocoon-start-second-person = You start cocooning {THE($target)}. +cocoon-start-third-person = {CAPITALIZE(THE($spider))} starts cocooning {THE($target)}. +spun-web-second-person = You spin up a web. +spun-web-third-person = {CAPITALIZE(THE($spider))} spins up a web! +cocoon = Cocoon diff --git a/Resources/Locale/en-US/abilities/bloodsucker.ftl b/Resources/Locale/en-US/abilities/bloodsucker.ftl new file mode 100644 index 00000000000..d956eaff84e --- /dev/null +++ b/Resources/Locale/en-US/abilities/bloodsucker.ftl @@ -0,0 +1,19 @@ +action-name-suck-blood = Suck Blood +action-description-suck-blood = Suck the blood of the victim in your hand. + +bloodsucker-fail-helmet = You'd need to remove {THE($helmet)}. +bloodsucker-fail-mask = You'd need to remove your mask! + +bloodsucker-fail-not-blood = { CAPITALIZE(SUBJECT($target)) } doesn't have delicious, nourishing mortal blood. +bloodsucker-fail-no-blood = { CAPITALIZE(SUBJECT($target)) } has no blood in { POSS-ADJ($target) } body. +bloodsucker-fail-no-blood-bloodsucked = { CAPITALIZE(SUBJECT($target)) } has been sucked dry. + +bloodsucker-blood-sucked = You suck some blood from {$target}. +bloodsucker-doafter-start = You try to suck blood from {$target}. + +bloodsucker-doafter-start-victim = {CAPITALIZE(THE($sucker))} is trying to bite your neck! +bloodsucker-blood-sucked-victim = {CAPITALIZE(THE($sucker))} sucks some of your blood! + +bloodsucked-health-examine = [color=red]{ CAPITALIZE(SUBJECT($target)) } { CONJUGATE-HAVE($target) } bite marks on { POSS-ADJ($target) } neck.[/color] + +bloodsucker-glands-throb = The glands behind your fangs feel a bit sore. diff --git a/Resources/Locale/en-US/species/species.ftl b/Resources/Locale/en-US/species/species.ftl index f31b1fa0f00..79ce7fea6a1 100644 --- a/Resources/Locale/en-US/species/species.ftl +++ b/Resources/Locale/en-US/species/species.ftl @@ -6,6 +6,7 @@ species-name-reptilian = Reptilian species-name-slime = Slime Person species-name-diona = Diona species-name-arachnid = Arachnid +species-name-arachne = Arachne species-name-moth = Moth Person species-name-skeleton = Skeleton species-name-vox = Vox diff --git a/Resources/Prototypes/Chemistry/metabolizer_types.yml b/Resources/Prototypes/Chemistry/metabolizer_types.yml index 259387b6d5c..4d48dab9925 100644 --- a/Resources/Prototypes/Chemistry/metabolizer_types.yml +++ b/Resources/Prototypes/Chemistry/metabolizer_types.yml @@ -1,4 +1,4 @@ -# If your species wants to metabolize stuff differently, +# If your species wants to metabolize stuff differently, # you'll likely have to tag its metabolizers with something other than Human. - type: metabolizerType @@ -44,3 +44,7 @@ - type: metabolizerType id: Arachnid name: arachnid + +- type: metabolizerType + id: Vampiric + name: vampiric diff --git a/Resources/Prototypes/Damage/containers.yml b/Resources/Prototypes/Damage/containers.yml index fb40e9b658f..b01d22df3b7 100644 --- a/Resources/Prototypes/Damage/containers.yml +++ b/Resources/Prototypes/Damage/containers.yml @@ -52,3 +52,13 @@ id: ShadowHaze supportedTypes: - Heat + +- type: damageContainer + id: HalfSpirit + supportedGroups: + - Burn + - Brute + - Airloss + - Immaterial + supportedTypes: + - Poison diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index 31dd47a9e16..a6798e39cfe 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -336,3 +336,16 @@ flatReductions: # can't punch the endoskeleton to death Blunt: 5 + +- type: damageModifierSet + id: HalfSpirit + coefficients: + Cold: 0.5 + Shock: 0.75 + Blunt: 0.75 + Slash: 0.75 + Piercing: 0.75 + Heat: 1.25 + Holy: 1.5 + flatReductions: + Cold: 3 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index 9a1f1427402..b62658270eb 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -138,6 +138,9 @@ Radiation: 0 Caustic: 0.75 - type: GroupExamine + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterArmorHeavy @@ -234,6 +237,9 @@ - type: ExplosionResistance damageCoefficient: 0.5 - type: GroupExamine + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterBaseLarge diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index 8f4312e7711..36327fe1f78 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -138,6 +138,7 @@ - Hardsuit - WhitelistChameleon - HidesHarpyWings #DeltaV: Used by harpies to help render their hardsuit sprites + - FullBodyOuter - type: Clothing equipDelay: 2.5 # Hardsuits are heavy and take a while to put on/off. unequipDelay: 2.5 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index d6cd5295731..9f0a01cc481 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -25,6 +25,7 @@ tags: - Hardsuit - WhitelistChameleon + - FullBodyOuter - HidesHarpyWings - type: entity @@ -38,6 +39,17 @@ sprite: Clothing/OuterClothing/Suits/janitor_bombsuit.rsi - type: Clothing sprite: Clothing/OuterClothing/Suits/janitor_bombsuit.rsi + - type: ClothingSpeedModifier + walkModifier: 0.8 + sprintModifier: 0.8 + - type: ExplosionResistance + damageCoefficient: 0.15 + - type: GroupExamine + - type: Tag + tags: + - Hardsuit + - WhitelistChameleon + - FullBodyOuter - type: entity parent: ClothingOuterBaseLarge @@ -97,6 +109,7 @@ - type: GroupExamine - type: Tag tags: + - FullBodyOuter - WhitelistChameleon - HidesHarpyWings @@ -124,6 +137,7 @@ toggleable-clothing: !type:ContainerSlot {} - type: Tag tags: + - FullBodyOuter - WhitelistChameleon - HidesHarpyWings @@ -177,6 +191,9 @@ sprite: Clothing/OuterClothing/Suits/chicken.rsi - type: Clothing sprite: Clothing/OuterClothing/Suits/chicken.rsi + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterBase @@ -202,6 +219,9 @@ - type: ContainerContainer containers: toggleable-clothing: !type:ContainerSlot {} + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterBase diff --git a/Resources/Prototypes/Entities/Mobs/Player/arachne.yml b/Resources/Prototypes/Entities/Mobs/Player/arachne.yml new file mode 100644 index 00000000000..bebf42f31ba --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Player/arachne.yml @@ -0,0 +1,35 @@ +- type: entity + save: false + name: Urist McArachne + parent: MobArachneBase + id: MobArachne + components: + - type: CombatMode + - type: InteractionPopup + successChance: 1 + interactSuccessString: hugging-success-generic + interactSuccessSound: /Audio/Effects/thudswoosh.ogg + messagePerceivedByOthers: hugging-success-generic-others + - type: MindContainer + showExamineInfo: true + - type: Input + context: "human" + - type: MobMover + - type: InputMover + - type: Respirator + damage: + types: + Asphyxiation: 1.0 + damageRecovery: + types: + Asphyxiation: -1.0 + - type: Alerts + - type: Actions + - type: Eye + - type: CameraRecoil + - type: Examiner + - type: CanHostGuardian + - type: NpcFactionMember + factions: + - NanoTrasen + - type: PotentialPsionic diff --git a/Resources/Prototypes/Entities/Mobs/Species/arachne.yml b/Resources/Prototypes/Entities/Mobs/Species/arachne.yml new file mode 100644 index 00000000000..2f6437dc14e --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Species/arachne.yml @@ -0,0 +1,220 @@ +- type: entity + save: false + name: Urist McArachne + parent: BaseMobHuman + id: MobArachneBase + abstract: true + components: + - type: Sprite + # Arachne are one of the species that needs a manual visual layers setup. + layers: + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body + - map: [ "enum.HumanoidVisualLayers.Chest" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: torso_m + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body_front + - map: [ "enum.HumanoidVisualLayers.Head" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: head_m + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + color: "#008800" + sprite: Mobs/Species/eyes.rsi + state: eyes + - map: [ "enum.HumanoidVisualLayers.RArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_arm + - map: [ "enum.HumanoidVisualLayers.LArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_arm + - shader: StencilClear + sprite: Mobs/Species/Human/parts.rsi + state: l_leg + - shader: StencilMask + map: [ "enum.HumanoidVisualLayers.StencilMask" ] + sprite: Mobs/Customization/anytaur_masking_helpers.rsi + state: unisex_full + visible: false + - map: [ "jumpsuit" ] + - map: [ "enum.HumanoidVisualLayers.LHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_hand + - map: [ "enum.HumanoidVisualLayers.RHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_hand + - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "enum.HumanoidVisualLayers.Hair" ] + state: bald + sprite: Mobs/Customization/human_hair.rsi + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] + - map: [ "enum.HumanoidVisualLayers.Tail" ] + sprite: Mobs/Customization/masking_helpers.rsi + state: none + visible: false + - map: [ "clownedon" ] # Dynamically generated + sprite: "Effects/creampie.rsi" + state: "creampie_human" + visible: false + - type: HumanoidAppearance + species: Arachne + - type: Fixtures + fixtures: # TODO: This needs a second fixture just for mob collisions. + fix1: + shape: + !type:PhysShapeCircle + radius: 0.40 + density: 140 + restitution: 0.0 + mask: + - MobMask + layer: + - MobLayer + - type: Body + prototype: Arachne + requiredLegs: 8 + - type: Speech + speechSounds: Alto + - type: Inventory + templateId: anytaur + - type: Tag + tags: + - CanPilot + - ShoesRequiredStepTriggerImmune + - DoorBumpOpener + - type: Bloodstream + bloodReagent: DemonsBlood + - type: BloodSucker + webRequired: true + - type: Arachne + - type: DamageVisuals + thresholds: [ 20, 40, 100 ] + targetLayers: + - "enum.HumanoidVisualLayers.Chest" + - "enum.HumanoidVisualLayers.Head" + - "enum.HumanoidVisualLayers.LArm" + - "enum.HumanoidVisualLayers.RArm" + - type: MovedByPressure + pressureResistance: 4 + - type: Barotrauma + damage: + types: + Blunt: 0.05 #per second, scales with pressure and other constants. Reduced Damage. This allows medicine to heal faster than damage. + - type: MovementAlwaysTouching + - type: MovementSpeedModifier + baseWalkSpeed : 3.0 + baseSprintSpeed : 5.0 + - type: FireVisuals + sprite: Mobs/Effects/onfire.rsi + normalState: Generic_mob_burning + alternateState: arachne_standing + fireStackAlternateState: 3 + - type: Spider + - type: IgnoreSpiderWeb + +- type: entity + save: false + name: Urist McHands + parent: MobHumanDummy + id: MobArachneDummy + noSpawn: true + description: A dummy arachne meant to be used in character setup. + components: + - type: Sprite + layers: + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body + - map: [ "enum.HumanoidVisualLayers.Chest" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: torso_m + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body_front + - map: [ "enum.HumanoidVisualLayers.Head" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: head_m + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + color: "#008800" + sprite: Mobs/Species/eyes.rsi + state: eyes + - map: [ "enum.HumanoidVisualLayers.RArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_arm + - map: [ "enum.HumanoidVisualLayers.LArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_arm + - shader: StencilClear + sprite: Mobs/Species/Human/parts.rsi + state: l_leg + - shader: StencilMask + map: [ "enum.HumanoidVisualLayers.StencilMask" ] + sprite: Mobs/Customization/anytaur_masking_helpers.rsi + state: unisex_full + visible: false + - map: [ "jumpsuit" ] + - map: [ "enum.HumanoidVisualLayers.LHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_hand + - map: [ "enum.HumanoidVisualLayers.RHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_hand + - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "enum.HumanoidVisualLayers.Hair" ] + state: bald + sprite: Mobs/Customization/human_hair.rsi + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] + - map: [ "enum.HumanoidVisualLayers.Tail" ] + sprite: Mobs/Customization/masking_helpers.rsi + state: none + visible: false + - type: Inventory + templateId: anytaur + - type: HumanoidAppearance + species: Arachne diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 7863224436c..ca885117449 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -413,6 +413,22 @@ # - id: MobClownSpider # prob: 0.05 +- type: entity + id: OneirophageSpawn + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + id: VentCritters + earliestStart: 15 + minimumPlayers: 15 + weight: 4 + duration: 60 + - type: VentCrittersRule + entries: + - id: MobGiantSpiderVampireAngry + prob: 0.01 + - type: entity id: ZombieOutbreak parent: BaseGameRule diff --git a/Resources/Prototypes/InventoryTemplates/anytaur_inventory_template.yml b/Resources/Prototypes/InventoryTemplates/anytaur_inventory_template.yml new file mode 100644 index 00000000000..0dd5961aef3 --- /dev/null +++ b/Resources/Prototypes/InventoryTemplates/anytaur_inventory_template.yml @@ -0,0 +1,112 @@ +- type: inventoryTemplate + id: anytaur + slots: + - name: jumpsuit + slotTexture: uniform + slotFlags: INNERCLOTHING + stripTime: 5 + uiWindowPos: 0,2 + strippingWindowPos: 0,2 + displayName: Jumpsuit + - name: outerClothing + slotTexture: suit + slotFlags: OUTERCLOTHING + slotGroup: MainHotbar + stripTime: 6 + uiWindowPos: 1,2 + strippingWindowPos: 1,2 + displayName: Suit + blacklist: + tags: + - FullBodyOuter + - name: gloves + slotTexture: gloves + slotFlags: GLOVES + uiWindowPos: 2,2 + strippingWindowPos: 2,2 + displayName: Gloves + - name: neck + slotTexture: neck + slotFlags: NECK + uiWindowPos: 0,1 + strippingWindowPos: 0,1 + displayName: Neck + - name: mask + slotTexture: mask + slotFlags: MASK + uiWindowPos: 1,1 + strippingWindowPos: 1,1 + displayName: Mask + - name: eyes + slotTexture: glasses + slotFlags: EYES + stripTime: 2 + uiWindowPos: 0,0 + strippingWindowPos: 0,0 + displayName: Eyes + - name: ears + slotTexture: ears + slotFlags: EARS + stripTime: 2 + uiWindowPos: 2,0 + strippingWindowPos: 2,1 + displayName: Ears + - name: head + slotTexture: head + slotFlags: HEAD + uiWindowPos: 1,0 + strippingWindowPos: 1,0 + displayName: Head + - name: pocket1 + slotTexture: pocket + slotFlags: POCKET + slotGroup: MainHotbar + stripTime: 2 + uiWindowPos: 0,3 + strippingWindowPos: 0,3 + dependsOn: jumpsuit + displayName: Pocket 1 + stripHidden: true + - name: pocket2 + slotTexture: pocket + slotFlags: POCKET + slotGroup: MainHotbar + stripTime: 2 + uiWindowPos: 2,3 + strippingWindowPos: 2,3 + dependsOn: jumpsuit + displayName: Pocket 2 + stripHidden: true + - name: suitstorage + slotTexture: suit_storage + slotFlags: SUITSTORAGE + stripTime: 2 + uiWindowPos: 2,0 + strippingWindowPos: 2,0 + dependsOn: outerClothing + displayName: Suit Storage + - name: id + slotTexture: id + slotFlags: IDCARD + slotGroup: SecondHotbar + stripTime: 6 + uiWindowPos: 2,1 + strippingWindowPos: 2,4 + dependsOn: jumpsuit + displayName: ID + - name: belt + slotTexture: belt + slotFlags: BELT + slotGroup: SecondHotbar + stripTime: 5 + uiWindowPos: 3,1 + strippingWindowPos: 1,3 + displayName: Belt + - name: back + slotTexture: back + slotFlags: BACK + slotGroup: SecondHotbar + stripTime: 5 + uiWindowPos: 3,0 + strippingWindowPos: 0,4 + displayName: Back diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Mechanisms/vampiric.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Mechanisms/vampiric.yml new file mode 100644 index 00000000000..23934b3ebcc --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Mechanisms/vampiric.yml @@ -0,0 +1,22 @@ +- type: entity + id: OrganVampiricHumanoidStomach + parent: OrganHumanStomach + components: + - type: Metabolizer + # mm yummy + maxReagents: 3 + metabolizerTypes: [Vampiric] + groups: + - id: Food + - id: Drink + +- type: entity + id: OrganVampiricStomach + parent: OrganAnimalStomach + components: + - type: Metabolizer + maxReagents: 3 + metabolizerTypes: [Vampiric] + groups: + - id: Food + - id: Drink diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml index a900f7524e7..7e71227dbcb 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml @@ -24,13 +24,33 @@ - ReagentId: DemonsBlood Quantity: 10 +- type: entity + id: ThoraxSpider + name: "spider thorax" #for arachne, actual spiders should get a cephalothorax that combines with head. + parent: PartSpider + components: + - type: Sprite + sprite: Mobs/Species/Moth/parts.rsi # placeholder sprite + state: "torso_m" + - type: Icon + sprite: Mobs/Species/Moth/parts.rsi + state: "torso_m" + - type: BodyPart #"Other" type + - type: Extractable + juiceSolution: + reagents: + - ReagentId: Fat + Quantity: 10 + - ReagentId: DemonsBlood + Quantity: 20 + - type: entity id: RightLegSpider name: "right spider leg" parent: PartSpider components: - type: Sprite - sprite: Objects/Consumable/Food/meat.rsi + sprite: Objects/Consumable/Food/meat.rsi # placeholder sprite state: spiderleg - type: Icon sprite: Objects/Consumable/Food/meat.rsi @@ -48,7 +68,7 @@ parent: PartSpider components: - type: Sprite - sprite: Objects/Consumable/Food/meat.rsi + sprite: Objects/Consumable/Food/meat.rsi # placeholder sprite state: spiderleg - type: Icon sprite: Objects/Consumable/Food/meat.rsi diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/arachne.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/arachne.yml new file mode 100644 index 00000000000..553391484e2 --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/arachne.yml @@ -0,0 +1,63 @@ +- type: body + id: Arachne + name: "arachne" + root: torso + slots: + head: + part: HeadHuman + connections: + - torso + organs: + brain: OrganHumanBrain + eyes: OrganHumanEyes + torso: + part: TorsoHuman + connections: + - left arm + - right arm + - thorax + organs: + heart: OrganHumanHeart + lungs: OrganHumanLungs + stomach: OrganVampiricHumanoidStomach + liver: OrganHumanLiver + kidneys: OrganHumanKidneys + right arm: + part: RightArmHuman + connections: + - right hand + left arm: + part: LeftArmHuman + connections: + - left hand + right hand: + part: RightHandHuman + left hand: + part: LeftHandHuman + thorax: + part: ThoraxSpider + connections: + - left foreleg + - left second leg + - left third leg + - left hind leg + - right foreleg + - right second leg + - right third leg + - right hind leg + left foreleg: + part: LeftLegSpider + left second leg: + part: LeftLegSpider + left third leg: + part: LeftLegSpider + left hind leg: + part: LeftLegSpider + right foreleg: + part: RightLegSpider + right second leg: + part: RightLegSpider + right third leg: + part: RightLegSpider + right hind leg: + part: RightLegSpider diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/vampiricanimal.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/vampiricanimal.yml new file mode 100644 index 00000000000..3f4cdb06de1 --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/vampiricanimal.yml @@ -0,0 +1,43 @@ +- type: body + id: VampiricAnimal + name: "vampiric animal" + root: torso + slots: + torso: + part: TorsoAnimal + connections: + - legs + organs: + lungs: OrganAnimalLungs + stomach: OrganVampiricStomach + liver: OrganAnimalLiver + heart: OrganAnimalHeart + kidneys: OrganAnimalKidneys + legs: + part: LegsAnimal + connections: + - feet + feet: + part: FeetAnimal + +- type: body + id: VampiricAnimalLarge + name: "large vampiric animal" + root: torso + slots: + torso: + part: TorsoAnimal + connections: + - legs + organs: + lungs: OrganAnimalLungs + stomach: OrganVampiricHumanoidStomach + liver: OrganAnimalLiver + heart: OrganAnimalHeart + kidneys: OrganAnimalKidneys + legs: + part: LegsAnimal + connections: + - feet + feet: + part: FeetAnimal diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml index 2652a89127e..046a324e6f6 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml @@ -51,23 +51,23 @@ - state: prisoner # - type: MidRoundAntagSpawnLocation # When MidRoundAntag? -# - type: entity -# id: SpawnPointGhostVampSpider -# name: ghost role spawn point -# suffix: Vampire spider -# parent: MarkerBase -# noSpawn: true -# components: -# - type: GhostRoleMobSpawner -# prototype: MobGiantSpiderVampireAngry -# - type: GhostRole -# makeSentient: true -# name: ghost-role-information-giant-spider-vampire-name -# description: ghost-role-information-giant-spider-vampire-description -# rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. -# - type: Sprite -# sprite: Markers/jobs.rsi -# layers: -# - state: green -# - sprite: Mobs/Animals/bat.rsi -# state: bat +- type: entity + id: SpawnPointGhostVampSpider + name: ghost role spawn point + suffix: Vampire spider + parent: MarkerBase + noSpawn: true + components: + - type: GhostRoleMobSpawner + prototype: MobGiantSpiderVampireAngry + - type: GhostRole + makeSentient: true + name: ghost-role-information-giant-spider-vampire-name + description: ghost-role-information-giant-spider-vampire-description + rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. + - type: Sprite + sprite: Markers/jobs.rsi + layers: + - state: green + - sprite: Mobs/Animals/bat.rsi + state: bat diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml index 5daf2e15e56..462b3254f1e 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml @@ -70,143 +70,130 @@ - type: Produce - type: NoSlip -# - type: entity -# name: oneirophage -# parent: SimpleMobBase -# id: MobGiantSpiderVampire -# description: The 'dream-eater' spider, rumored to be one of the potential genetic sources for arachne. -# components: -# - type: Sprite -# drawdepth: Mobs -# layers: -# - map: ["enum.DamageStateVisualLayers.Base"] -# state: viper -# sprite: Mobs/Animals/spider.rsi -# - type: Physics -# - type: Fixtures -# fixtures: -# fix1: -# shape: -# !type:PhysShapeCircle -# radius: 0.35 -# density: 130 -# mask: -# - SmallMobMask -# layer: -# - SmallMobLayer -# - type: Appearance -# - type: DamageStateVisuals -# states: -# Alive: -# Base: viper -# Critical: -# Base: viper_dead -# Dead: -# Base: viper_dead -# - type: Butcherable -# spawned: -# - id: FoodMeatSpider -# amount: 2 -# - type: CombatMode -# - type: ReplacementAccent -# accent: xeno -# - type: InteractionPopup -# successChance: 0.5 -# interactSuccessString: petting-success-tarantula -# interactFailureString: petting-failure-generic -# - type: Puller -# needsHands: false -# - type: Arachne -# cocoonDelay: 8 -# - type: SolutionContainerManager -# solutions: -# melee: -# reagents: -# - ReagentId: Nocturine -# Quantity: 20 -# - type: MeleeChemicalInjector -# solution: melee -# transferAmount: 3.5 -# - type: SolutionRegeneration -# solution: melee -# generated: -# reagents: -# - ReagentId: Nocturine -# Quantity: 0.15 -# - type: BloodSucker -# unitsToSucc: 35 -# injectWhenSucc: true -# injectReagent: Cryptobiolin -# unitsToInject: 10 -# webRequired: true -# - type: Bloodstream -# bloodReagent: DemonsBlood -# - type: Body -# prototype: VampiricAnimalLarge -# - type: PotentialPsionic -# - type: Psionic -# removable: false -# - type: MetapsionicPower -# - type: MeleeWeapon -# hidden: true -# angle: 0 -# animation: WeaponArcBite -# damage: -# types: -# Piercing: 8 -# - type: AntiPsionicWeapon -# punish: false -# modifiers: -# coefficients: -# Piercing: 2.25 -# - type: Damageable -# damageContainer: HalfSpirit -# damageModifierSet: HalfSpirit -# - type: StatusEffects -# allowed: -# - Stun -# - KnockedDown -# - SlowedDown -# - Stutter -# - SeeingRainbows -# - Electrocution -# - Drunk -# - SlurredSpeech -# - PressureImmunity -# - Muted -# - ForcedSleep -# - TemporaryBlindness -# - Pacified -# - PsionicsDisabled -# - PsionicallyInsulated -# - type: Tag -# tags: -# - Oneirophage -# - type: MovementAlwaysTouching -# - type: PsionicInvisibleContacts -# whitelist: -# tags: -# - ArachneWeb +- type: entity + name: oneirophage + parent: MobGiantSpider + id: MobGiantSpiderVampire + description: The 'dream-eater' spider, rumored to be one of the potential genetic sources for arachne. + components: + - type: Sprite + drawdepth: Mobs + layers: + - map: ["enum.DamageStateVisualLayers.Base", "movement"] + state: viper + sprite: Mobs/Animals/spider.rsi + - type: SpriteMovement + movementLayers: + movement: + state: viper-moving + noMovementLayers: + movement: + state: viper + - type: Appearance + - type: DamageStateVisuals + states: + Alive: + Base: viper + Critical: + Base: viper_dead + Dead: + Base: viper_dead + - type: ReplacementAccent + accent: xeno + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-tarantula + interactFailureString: petting-failure-generic + interactSuccessSpawn: EffectHearts + interactSuccessSound: + path: /Audio/Animals/snake_hiss.ogg + - type: Puller + needsHands: false + - type: Arachne + cocoonDelay: 8 + - type: SolutionContainerManager + solutions: + melee: + reagents: + - ReagentId: Nocturine + Quantity: 20 + - type: MeleeChemicalInjector + solution: melee + transferAmount: 3.5 + - type: SolutionRegeneration + solution: melee + generated: + reagents: + - ReagentId: Nocturine + Quantity: 0.15 + - type: BloodSucker + unitsToSucc: 35 + injectWhenSucc: true + injectReagent: Cryptobiolin + unitsToInject: 10 + webRequired: true + - type: Bloodstream + bloodReagent: DemonsBlood + - type: Body + prototype: VampiricAnimalLarge + - type: PotentialPsionic + - type: Psionic + removable: false + - type: MetapsionicPower + - type: AntiPsionicWeapon + punish: false + modifiers: + coefficients: + Piercing: 2.25 + - type: Damageable + damageContainer: HalfSpirit + damageModifierSet: HalfSpirit + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - Stutter + - SeeingRainbows + - Electrocution + - Drunk + - SlurredSpeech + - PressureImmunity + - Muted + - ForcedSleep + - TemporaryBlindness + - Pacified + - PsionicsDisabled + - PsionicallyInsulated + - type: Tag + tags: + - Oneirophage + - type: MovementAlwaysTouching + - type: PsionicInvisibleContacts + whitelist: + tags: + - ArachneWeb -# - type: entity -# name: oneirophage -# parent: MobGiantSpiderVampire -# id: MobGiantSpiderVampireAngry -# suffix: Angry -# components: -# - type: NpcFactionMember -# factions: -# - SimpleHostile -# - type: InputMover -# - type: MobMover -# - type: HTN -# rootTask: SimpleHostileCompound -# - type: GhostRole -# makeSentient: true -# name: ghost-role-information-giant-spider-vampire-name -# description: ghost-role-information-giant-spider-vampire-description -# rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. -# - type: GhostTakeoverAvailable +- type: entity + name: oneirophage + parent: MobGiantSpiderVampire + id: MobGiantSpiderVampireAngry + suffix: Angry + components: + - type: NpcFactionMember + factions: + - SimpleHostile + - type: InputMover + - type: MobMover + - type: HTN + rootTask: + task: SimpleHostileCompound + - type: GhostRole + makeSentient: true + name: ghost-role-information-giant-spider-vampire-name + description: ghost-role-information-giant-spider-vampire-description + rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. + - type: GhostTakeoverAvailable - type: entity parent: SimpleMobBase diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Webbing/webs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Webbing/webs.yml new file mode 100644 index 00000000000..e483ea5da71 --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Webbing/webs.yml @@ -0,0 +1,93 @@ +- type: entity + id: CocoonedHumanoid + name: cocooned humanoid + description: Unlucky. + placement: + mode: SnapgridCenter + snap: + - Wall + components: + - type: Sprite + layers: + - sprite: Nyanotrasen/Structures/cocoon.rsi + state: cocoon_large1 + map: [ "enum.DamageStateVisualLayers.Base" ] + - type: RandomSprite + available: + - enum.DamageStateVisualLayers.Base: + cocoon_large1: "" + - enum.DamageStateVisualLayers.Base: #your guess for why randomsprite requires an arbitrary layer is as good as mine friend + cocoon_large2: "" + - enum.DamageStateVisualLayers.Base: + cocoon_large3: "" + - type: Cocoon + - type: Clickable + - type: InteractionOutline + - type: Transform + noRot: true + - type: Damageable + damageModifierSet: Web + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 40 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.4,0.25,0.1" + density: 20 + mask: + - SmallMobMask + layer: + - SmallMobLayer + - type: Physics + bodyType: Dynamic + - type: Pullable + - type: AntiRottingContainer + - type: ItemSlots + slots: + body_slot: + name: Body + locked: true + ejectOnBreak: true + - type: Butcherable + butcheringType: Knife + butcherDelay: 12 + spawned: + - id: MaterialCloth1 + amount: 1 + prob: 0.5 #This doesn't cost hunger so should at least make it not worth it time-wise + - type: Appearance + - type: ContainerContainer + containers: + body_slot: !type:ContainerSlot + +- type: entity + id: CocoonSmall + parent: CocoonedHumanoid + name: cocoon + description: What could be inside...? + placement: + mode: SnapgridCenter + snap: + - Wall + components: + - type: Sprite + layers: + - sprite: Nyanotrasen/Structures/cocoon.rsi + state: cocoon1 + map: [ "enum.DamageStateVisualLayers.Base" ] + - type: RandomSprite + available: + - enum.DamageStateVisualLayers.Base: + cocoon1: "" + - enum.DamageStateVisualLayers.Base: #your guess for why randomsprite requires an arbitrary layer is as good as mine friend + cocoon2: "" + - enum.DamageStateVisualLayers.Base: + cocoon3: "" diff --git a/Resources/Prototypes/Reagents/biological.yml b/Resources/Prototypes/Reagents/biological.yml index 0c53ae10fd1..5c0cef314ca 100644 --- a/Resources/Prototypes/Reagents/biological.yml +++ b/Resources/Prototypes/Reagents/biological.yml @@ -23,6 +23,29 @@ - !type:OrganType type: Human shouldHave: false + - !type:SatiateHunger + factor: 0.5 + conditions: + - !type:OrganType + type: Vampiric + - !type:AdjustReagent + conditions: + - !type:OrganType + type: Vampiric + reagent: Water + amount: 0.15 + - !type:AdjustReagent + conditions: + - !type:OrganType + type: Vampiric + reagent: Protein + amount: 0.15 + - !type:AdjustReagent + conditions: + - !type:OrganType + type: Vampiric + reagent: Omnizine + amount: 0.2 Food: effects: - !type:AdjustReagent diff --git a/Resources/Prototypes/Species/arachne.yml b/Resources/Prototypes/Species/arachne.yml new file mode 100644 index 00000000000..ed494c37cc8 --- /dev/null +++ b/Resources/Prototypes/Species/arachne.yml @@ -0,0 +1,50 @@ +- type: species + id: Arachne + name: species-name-arachne + roundStart: true + prototype: MobArachne + sprites: MobArachneSprites + markingLimits: MobArachneMarkingLimits + dollPrototype: MobArachneDummy + skinColoration: HumanToned + sexes: + - Female + minAge: 60 + youngAge: 150 + oldAge: 400 + maxAge: 666 + +- type: markingPoints + id: MobArachneMarkingLimits + points: + Hair: + points: 1 + required: false + Tail: + points: 1 + required: false + Chest: + points: 1 + required: false + Arms: + points: 2 + required: false + + +- type: speciesBaseSprites + id: MobArachneSprites + sprites: + Head: MobHumanHead + Hair: MobHumanoidAnyMarking + Chest: MobHumanTorso + Eyes: MobArachneEyes + LArm: MobHumanLArm + RArm: MobHumanRArm + LHand: MobHumanLHand + RHand: MobHumanRHand + +- type: humanoidBaseSprite + id: MobArachneEyes + baseSprite: + sprite: Mobs/Species/eyes.rsi + state: eyes diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 9b0ad51cfb6..786f641ddd1 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -16,6 +16,9 @@ - type: Tag id: AppraisalTool +- type: Tag + id: ArachneWeb + - type: Tag id: ArtifactFragment @@ -602,6 +605,9 @@ - type: Tag id: Fruit +- type: Tag + id: FullBodyOuter + - type: Tag id: Galaxythistle @@ -919,6 +925,9 @@ - type: Tag id: Ointment +- type: Tag + id: Oneirophage + - type: Tag id: Ore diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_full.png new file mode 100644 index 0000000000000000000000000000000000000000..acb96562e7374cbaba2d9f8eac4f1983c2722946 GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pW8&%J7@~1LIYA=F!GWQPv*Eu3gIdO!1&Rrbf?NSjtdA<$*!Y?lS%R69 i8<@M9!xb)?)i4xI-eS7+u8$Z{KZB>MpUXO@geCy^0w-qx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_none.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_top.png new file mode 100644 index 0000000000000000000000000000000000000000..acb96562e7374cbaba2d9f8eac4f1983c2722946 GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pW8&%J7@~1LIYA=F!GWQPv*Eu3gIdO!1&Rrbf?NSjtdA<$*!Y?lS%R69 i8<@M9!xb)?)i4xI-eS7+u8$Z{KZB>MpUXO@geCy^0w-qx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/full.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_full.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_none.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_top.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/meta.json b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/meta.json new file mode 100644 index 00000000000..b44be570c4f --- /dev/null +++ b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/meta.json @@ -0,0 +1,59 @@ +{ + "version": 1, + "copyright": "Rane", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "female_none", + "directions": 4 + }, + { + "name": "female_full", + "directions": 4 + }, + { + "name": "female_top", + "directions": 4 + }, + { + "name": "male_none", + "directions": 4 + }, + { + "name": "male_full", + "directions": 4 + }, + { + "name": "male_top", + "directions": 4 + }, + { + "name": "full", + "directions": 4 + }, + { + "name": "none", + "directions": 4 + }, + { + "name": "top", + "directions": 4 + }, + { + "name": "unisex_full", + "directions": 4 + }, + { + "name": "unisex_none", + "directions": 4 + }, + { + "name": "unisex_top", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/none.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/top.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_full.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_none.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_top.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccfaa8db4caa19d2762bbb84aa2c4a5dff53bc GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@pBjM@d7@~1LIYDC41ABo6PATIylLfUu7#QYSZ1zpv!|)iWhQZU-&t;uc GLK6T%$RK0@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/spidereyes.rsi/eyes.png b/Resources/Textures/Mobs/Customization/spidereyes.rsi/eyes.png new file mode 100644 index 0000000000000000000000000000000000000000..0f2534769440310b1f727cde206dfda449257ab0 GIT binary patch literal 5070 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png b/Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png new file mode 100644 index 0000000000000000000000000000000000000000..0171f16fe385fe420c6f1b1142b5381e2284ba92 GIT binary patch literal 761 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9F5M?jcysy3fA0|V1U zPZ!6KiaBrZ9`qM>6gmF!{+8Vi+G2O6t>rz%CBtGXu=nNv`4z?wm8z7c6lHq3>b})` z_pMSxSHic)aOSLUzju~yJ9%bb<>#{RUsQlrUqp7-u2zqhRC<9m~TO#Ecr>eQ`KzJ5W|QoS~ZL{9TeyS3u#mg`xS{f-Zc zH_f%!X2A2MsQ$i*T>MNm)e}>_W+zHysQ0bC`&KU}RO?vs)5>*@^G?6XTR*qBXwtFA z8^4=YdN(}xOj>-=W3fqaYOe1jv*p+4EHOEo_W!p@d(eyKnVA+ct77#2PhxNl{A2R0 zdpb*n)NwJE$t#b!F0?ssYWp|XHPA;)WQzDUp%86RR>uVfJSFu&(@%YlIrnpaYQAWK zDo<#?QtY?iRXg^r%WppT=GK>T+b$K|ce7vG#C`gA#G7eO`R;X3=3HIuan6#L?fS0z zL&DF`SgJptqxZXZuI_`E?Ms&2+_L26pSR6=nPzVzKYu(_&xt({v4}Q2eYn;6dH3B| zW8+XQ(Y^MT3$0(+uIJ~^HIX`LxtxFb@_R{-x7O}C6S6jJ>n@>JZ!cb4Q~zoA3IjA^m*&&Ubxth`@pA}Idyk3R@{B*k#_1*$lJK{*`{;6U*7GLyP1~j zeE)L{|Ekc^YTMW^zrDXo+~`y4mgbG+Z|7=u2#??YV$uJ~l}VU>`gfN9lgpc9^P48s h0VVlTBRtc5eHpZXY!0a6OTm*tEKgTImvv4FO#o58J(mCg literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/eyes.rsi/eyes.png b/Resources/Textures/Mobs/Species/eyes.rsi/eyes.png new file mode 100644 index 0000000000000000000000000000000000000000..b6250e22b38a17c35b2b54789f66bb5cda1db308 GIT binary patch literal 5553 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/eyes.rsi/meta.json b/Resources/Textures/Mobs/Species/eyes.rsi/meta.json new file mode 100644 index 00000000000..a98aba406f1 --- /dev/null +++ b/Resources/Textures/Mobs/Species/eyes.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by @Rane#7518", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "eyes", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png new file mode 100644 index 0000000000000000000000000000000000000000..27741fdf314bc38be7153151d603479000af1891 GIT binary patch literal 669 zcmV;O0%HA%P)$5Dx(m zFBXfsFs^ZhFvIKhs_Q@?a2Eu|Znw+%d={V2CxgL2(&@BRt5s77QvgGJv)QP)!{Lxf zBqH5zS3;qX0suChPIdoDARG?Ma5&VIZq5}t7z~=4e3$?qrcx<&lF#R5GMOk0#n$Wf zbgvNx%x1I6<#LhTZYQJB=)MNvY>Qb6p90{%P$;MnB8HP#EGF%CTX=>j_YedE$8-R| z2pY9PD*b+6(|S1pqs>SHF&0TClhWyQ6o&J|;UM$*{N4f71zSRDY#+4%AZuXAG5}6) zJ*{FSF&>X~3xL8MAVy2#m^3I#?&oqjg$5#%$!M*-lmLq%x>zjq8dr$n%mCybVgTLx zUR_f8)C2?Ph&LJyX|-C`y5LqQR|<#N5hY3%&StYJXt<{%0O37mT984J0?BUyP@joE zOaO?F549B$#R;MmAA^~AnE_;<*&=3=1DK@06q*z%=`4(1e*jw4~ z0qlJMWovU6H!CGJl-MY-xwmdtq%iY)ns=JT%y?aMo6Y-_-gBJS`Tw5(^PJ}DNTn6v)$^dz}l z?&{uG0e*DwrC2OVzu#ADv6;^I`F#40Q3}HmU~mHGDA`>A1U8Z_U5_|(ZouJi__HaQ zb4ntSh&q9ItyYt6w|oCZ)ai881#Y-_Jg%Y$7#{#)v6!9+#DQ$JTE_40cff%7Zs&#L z)@(La1XswMBT4plyIm@kirRiH^P2&PUpCc0o8Q&ftnh~bj4)&Ervm)TumCIo3*Z}` WA1sKIggnat0000>)WwzxBKr~01&TMs}c%@WV_wUYPFI?BEi)4t02Yzh&P)}+3)w-zg#X- zDwPz3@mqWv#0bC=C*w>eBcstsa=Dy%JRWspHk*mt?Us7It}P&@5XKH5PW1czd*+CH zy=I<#amf@8*aR#6tkGuT&~3hV6jRB0QN)BpQv%Znx93ryd@e$n4R$MNZwy{|3K8G+z z!Wb@C4gm4&)`v%71mO4kWiS|M;ZcBOY1xfC6eHr)fzRi=uS=y;5BGiuKv5kI2Xz3D zbULj^5ex=jy*HoFRS*~g7kH2Lwg7s)9`;=ujfVCSW>Y>rs(-WDs2hPmKqp|B26zX=cKp8o0}g-#@aF*j10gEyIQQql Q8~^|S07*qoM6N<$f*=3`Hvj+t literal 0 HcmV?d00001 diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png new file mode 100644 index 0000000000000000000000000000000000000000..f9431f6428586fe569344878961bd645cbc04fc6 GIT binary patch literal 762 zcmVgc z)HGVt5GrUW(MCfaUs*`R6?PUu8&3| zNvG3tb#*1>a@o1Oyxf|EOMu{L0LW@nhDS$7QYw{P@YQN1KA%r^cX!o}?e_MT;npOS z0IYMloFtP;d3$?vgMWN{xLH0wKdZ(L0YI@wA`ywlP)iTC$+wedl~_5y~WPfkvBj3y>__7w^Rr`>L^ z5zz`*DNQVxW%cy*B;jyavm+Di%jHt5z#cw`quGZf5((9|PBO$gJv}9kQ>j#T)_MSj znM}ql8BVj=Oq~EE3y3gB=JUBr#MYRT2ni7n!3I&PNX3w1u}F_;pC|#GC@tUs6Lhgy zXaidIcHUNUn{!$Y^}?1i+)CY#N=3DoO#J%UXS&qe~DNc>iKw1&f>5L*PT;*8~QGffs!} zpU=Pki~!)>Zr7AbC3$_n-??}$BvKPl@Or&&PN$QpR;%WCJR0t~kVr)!dh+Mb%Vi;e0@UO25G7E>wo((o??RzquGg!nR4V3jxrFbX&*%3O z0E81G`|WlU5)_17DiwjiTW>rbi}%=(&*ww%*=%N(%jNq**lxEagrpwNU$2*_ffB3L z${IWs0l-J2k@(Mp0$hEk3tY;H0N}k|Po8sfE##*a31Y2Q6cTGIE(O#1Pj;9&toXiW$VheODDlgT8zK?E?T*O80l5Ya3g z4hJEF1z2KRP8L9d0(`w*ixt?Qz^Fn+hf<~lIGK9w2T~;8?RMdb)e4s!I1vDV(_;Z@ zaAJsPK?p0bYO~p7OCV?~nE~2@bb^MDJU|djc%Q%;i;ZYaz@K~`sb}CY@i-+99Y(s8 zAhX?W!`+Zni39-V>bIfvJK>}Bq&oirjJ71z@AtXHst`+{)9H8sBQF4W&yONKK#(DT zyoWmEg6Am1XCX43PGd<}SpWz>hyvPj6oG^YkErDOS?<#jTvI6!Y&B08jIW6P@f20a z0#hxX%$l3vJF)B8X%5)#dD~4${QyPKZkme+ R_X7X`002ovPDHLkV1mDMGcW)E literal 0 HcmV?d00001 diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png new file mode 100644 index 0000000000000000000000000000000000000000..9a033961ffa27e1796d98c10f6fc9d563f13066a GIT binary patch literal 876 zcmV-y1C#uTP)P6p9*9R5b`t4M~gH+uwv|vr7wIu9v%9!kbKXc6WH6-}`4~`Dy;KodM1O zXMq0~pwVbJn!mrlo5#n;AAbb^VFc^-x=E+g=JoZ}j(k4v%;$5{ZnsYYISByqTrOv7 zwVJuOxG?MW+Hj9uUtgQaWWv-r1tK&6;zS*dMolahvjAM5pPy|e7K??sy1FuzN`)+h z4k{FY#EEjXTG^3ICM^VmdolqKFsu)og-`&AM8Z1e${_WsJ@>Nhc5BBe_9ejW?XBZB zm`y#x5`1}ivC#uTHvG^27y#ncYSqq_b|M4;| za|~gkCEcuJOs7*jPO%RF_xJZssZ{bB3Nbl}=HBV1Z zwiJ4&5-<=Js4E;0Z#J9Wx8hhy0swb+ced-*Ob8%O#Hm!ut2qXwj8m{&E;Dt2K-~3Z z-|aHx9D)b{5EUJdai!im;UbZUd3$@a5Tu<>M;N1I7(2#YZ_f>Sf#zjBr>G0;d{&+S z01k;V?-3skhjz|8t_T9m z+}|fW$GGwZB@4Y?FOY=*0ClCCHQ-*^ct8vPUUAI}K#JNiLu*@g_>hbjTa zp9$BgLl%fe;>v~^j7|qqe@X^I;+0IbvLu-NH#yC###c+Y{tIbhlW zM6IJ*< Date: Tue, 6 Aug 2024 04:52:58 +0000 Subject: [PATCH 004/135] Automatic Changelog Update (#438) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 35142b8bbfa..afe00fec1f2 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4940,3 +4940,11 @@ Entries: message: Added an unlockable PKA and Jetpack module to Salvage Cyborgs id: 6218 time: '2024-08-06T01:14:31.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: Arachne have been reimplemented! + - type: Add + message: Oneirophages are back! + id: 6219 + time: '2024-08-06T04:52:32.0000000+00:00' From aed3baba152a568b0b291fe714beb68f6934761c Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Tue, 6 Aug 2024 01:28:53 -0400 Subject: [PATCH 005/135] CPR Remake (#487) # Description This is a re implementation and complete rewrite of the original Nyanotrasen CPR feature, this time as its own completely standalone system. Unlike the original CPR, this system requires no modification of base game code, and can be toggled on and off via CVars while the server is running. Fixes #473 Fixes #49 # Changelog :cl: - add: CPR has been added to the game. People with CPR training can now perform CPR on anyone who is in either crit or dead states. - add: CPR Training has been added to the game as a new positive trait. All medical staff start with this trait for free. --------- Signed-off-by: VMSolidus --- Content.Server/Atmos/Rotting/RottingSystem.cs | 107 +------------ .../Atmos/Rotting/SharedRottingSystem.cs | 141 +++++++++++++++++- Content.Shared/CCVar/CCVars.cs | 49 ++++++ .../CPR/Components/CPRTrainingComponent.cs | 33 ++++ .../Medical/CPR/Systems/CPRSystem.CVars.cs | 27 ++++ .../Medical/CPR/Systems/CPRSystem.cs | 132 ++++++++++++++++ Resources/Audio/Effects/CPR.ogg | Bin 0 -> 68840 bytes .../components/cpr-training-component.ftl | 6 + Resources/Locale/en-US/traits/traits.ftl | 7 + .../DeltaV/Roles/Jobs/Security/brigmedic.yml | 3 + .../Prototypes/Roles/Jobs/Medical/chemist.yml | 4 + .../Jobs/Medical/chief_medical_officer.yml | 1 + .../Roles/Jobs/Medical/medical_doctor.yml | 4 + .../Roles/Jobs/Medical/medical_intern.yml | 4 + .../Roles/Jobs/Medical/paramedic.yml | 4 + .../Roles/Jobs/Medical/senior_physician.yml | 4 + Resources/Prototypes/Traits/skills.yml | 17 +++ 17 files changed, 431 insertions(+), 112 deletions(-) create mode 100644 Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs create mode 100644 Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs create mode 100644 Content.Shared/Medical/CPR/Systems/CPRSystem.cs create mode 100644 Resources/Audio/Effects/CPR.ogg create mode 100644 Resources/Locale/en-US/medical/components/cpr-training-component.ftl diff --git a/Content.Server/Atmos/Rotting/RottingSystem.cs b/Content.Server/Atmos/Rotting/RottingSystem.cs index 47bac84e0ca..5070b3f197f 100644 --- a/Content.Server/Atmos/Rotting/RottingSystem.cs +++ b/Content.Server/Atmos/Rotting/RottingSystem.cs @@ -1,15 +1,9 @@ -using Content.Shared.Damage; -using Content.Shared.Atmos; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; using Content.Server.Temperature.Components; +using Content.Shared.Atmos; using Content.Shared.Atmos.Rotting; -using Content.Shared.Examine; -using Content.Shared.IdentityManagement; -using Content.Shared.Mobs; -using Content.Shared.Mobs.Components; -using Content.Shared.Mobs.Systems; -using Content.Shared.Rejuvenate; +using Content.Shared.Damage; using Robust.Server.Containers; using Robust.Shared.Physics.Components; using Robust.Shared.Timing; @@ -22,83 +16,16 @@ public sealed class RottingSystem : SharedRottingSystem [Dependency] private readonly AtmosphereSystem _atmosphere = default!; [Dependency] private readonly ContainerSystem _container = default!; [Dependency] private readonly DamageableSystem _damageable = default!; - [Dependency] private readonly MobStateSystem _mobState = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnPerishableMapInit); - SubscribeLocalEvent(OnMobStateChanged); - SubscribeLocalEvent(OnPerishableExamined); - - SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnRottingMobStateChanged); SubscribeLocalEvent(OnGibbed); - SubscribeLocalEvent(OnRejuvenate); SubscribeLocalEvent(OnTempIsRotting); } - private void OnPerishableMapInit(EntityUid uid, PerishableComponent component, MapInitEvent args) - { - component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate; - } - - private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args) - { - if (args.NewMobState != MobState.Dead && args.OldMobState != MobState.Dead) - return; - - if (HasComp(uid)) - return; - - component.RotAccumulator = TimeSpan.Zero; - component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate; - } - - private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args) - { - if (TryComp(uid, out var perishable)) - { - perishable.RotNextUpdate = TimeSpan.Zero; - } - } - - private void OnRottingMobStateChanged(EntityUid uid, RottingComponent component, MobStateChangedEvent args) - { - if (args.NewMobState == MobState.Dead) - return; - RemCompDeferred(uid, component); - } - - public bool IsRotProgressing(EntityUid uid, PerishableComponent? perishable) - { - // things don't perish by default. - if (!Resolve(uid, ref perishable, false)) - return false; - - // only dead things or inanimate objects can rot - if (TryComp(uid, out var mobState) && !_mobState.IsDead(uid, mobState)) - return false; - - if (_container.TryGetOuterContainer(uid, Transform(uid), out var container) && - HasComp(container.Owner)) - { - return false; - } - - var ev = new IsRottingEvent(); - RaiseLocalEvent(uid, ref ev); - - return !ev.Handled; - } - - public bool IsRotten(EntityUid uid, RottingComponent? rotting = null) - { - return Resolve(uid, ref rotting, false); - } - private void OnGibbed(EntityUid uid, RottingComponent component, BeingGibbedEvent args) { if (!TryComp(uid, out var physics)) @@ -112,36 +39,6 @@ private void OnGibbed(EntityUid uid, RottingComponent component, BeingGibbedEven tileMix?.AdjustMoles(Gas.Ammonia, molsToDump); } - private void OnPerishableExamined(Entity perishable, ref ExaminedEvent args) - { - int stage = PerishStage(perishable, MaxStages); - if (stage < 1 || stage > MaxStages) - { - // We dont push an examined string if it hasen't started "perishing" or it's already rotting - return; - } - - var isMob = HasComp(perishable); - var description = "perishable-" + stage + (!isMob ? "-nonmob" : string.Empty); - args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(perishable, EntityManager)))); - } - - /// - /// Return an integer from 0 to maxStage representing how close to rotting an entity is. Used to - /// generate examine messages for items that are starting to rot. - /// - public int PerishStage(Entity perishable, int maxStages) - { - if (perishable.Comp.RotAfter.TotalSeconds == 0 || perishable.Comp.RotAccumulator.TotalSeconds == 0) - return 0; - return (int)(1 + maxStages * perishable.Comp.RotAccumulator.TotalSeconds / perishable.Comp.RotAfter.TotalSeconds); - } - - private void OnRejuvenate(EntityUid uid, RottingComponent component, RejuvenateEvent args) - { - RemCompDeferred(uid); - } - private void OnTempIsRotting(EntityUid uid, TemperatureComponent component, ref IsRottingEvent args) { if (args.Handled) diff --git a/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs b/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs index 5e1758203a8..840818dee59 100644 --- a/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs +++ b/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs @@ -1,29 +1,85 @@ using Content.Shared.Examine; using Content.Shared.IdentityManagement; +using Content.Shared.Mobs; using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.Rejuvenate; +using Robust.Shared.Containers; +using Robust.Shared.Timing; namespace Content.Shared.Atmos.Rotting; public abstract class SharedRottingSystem : EntitySystem { + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + public const int MaxStages = 3; public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnPerishableMapInit); + SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnPerishableExamined); + + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnRottingMobStateChanged); + SubscribeLocalEvent(OnRejuvenate); SubscribeLocalEvent(OnExamined); } - /// - /// Return the rot stage, usually from 0 to 2 inclusive. - /// - public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComponent? perishable = null) + private void OnPerishableMapInit(EntityUid uid, PerishableComponent component, MapInitEvent args) { - if (!Resolve(uid, ref comp, ref perishable)) - return 0; + component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate; + } - return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds); + private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args) + { + if (args.NewMobState != MobState.Dead && args.OldMobState != MobState.Dead) + return; + + if (HasComp(uid)) + return; + + component.RotAccumulator = TimeSpan.Zero; + component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate; + } + + private void OnPerishableExamined(Entity perishable, ref ExaminedEvent args) + { + int stage = PerishStage(perishable, MaxStages); + if (stage < 1 || stage > MaxStages) + { + // We dont push an examined string if it hasen't started "perishing" or it's already rotting + return; + } + + var isMob = HasComp(perishable); + var description = "perishable-" + stage + (!isMob ? "-nonmob" : string.Empty); + args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(perishable, EntityManager)))); + } + + private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args) + { + if (TryComp(uid, out var perishable)) + { + perishable.RotNextUpdate = TimeSpan.Zero; + } + } + + private void OnRottingMobStateChanged(EntityUid uid, RottingComponent component, MobStateChangedEvent args) + { + if (args.NewMobState == MobState.Dead) + return; + RemCompDeferred(uid, component); + } + + private void OnRejuvenate(EntityUid uid, RottingComponent component, RejuvenateEvent args) + { + RemCompDeferred(uid); } private void OnExamined(EntityUid uid, RottingComponent component, ExaminedEvent args) @@ -41,4 +97,75 @@ private void OnExamined(EntityUid uid, RottingComponent component, ExaminedEvent args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(uid, EntityManager)))); } + + /// + /// Return an integer from 0 to maxStage representing how close to rotting an entity is. Used to + /// generate examine messages for items that are starting to rot. + /// + public int PerishStage(Entity perishable, int maxStages) + { + if (perishable.Comp.RotAfter.TotalSeconds == 0 || perishable.Comp.RotAccumulator.TotalSeconds == 0) + return 0; + return (int)(1 + maxStages * perishable.Comp.RotAccumulator.TotalSeconds / perishable.Comp.RotAfter.TotalSeconds); + } + + public bool IsRotProgressing(EntityUid uid, PerishableComponent? perishable) + { + // things don't perish by default. + if (!Resolve(uid, ref perishable, false)) + return false; + + // only dead things or inanimate objects can rot + if (TryComp(uid, out var mobState) && !_mobState.IsDead(uid, mobState)) + return false; + + if (_container.TryGetOuterContainer(uid, Transform(uid), out var container) && + HasComp(container.Owner)) + { + return false; + } + + var ev = new IsRottingEvent(); + RaiseLocalEvent(uid, ref ev); + + return !ev.Handled; + } + + public bool IsRotten(EntityUid uid, RottingComponent? rotting = null) + { + return Resolve(uid, ref rotting, false); + } + + public void ReduceAccumulator(EntityUid uid, TimeSpan time) + { + if (!TryComp(uid, out var perishable)) + return; + + if (!TryComp(uid, out var rotting)) + { + perishable.RotAccumulator -= time; + return; + } + var total = (rotting.TotalRotTime + perishable.RotAccumulator) - time; + + if (total < perishable.RotAfter) + { + RemCompDeferred(uid, rotting); + perishable.RotAccumulator = total; + } + + else + rotting.TotalRotTime = total - perishable.RotAfter; + } + + /// + /// Return the rot stage, usually from 0 to 2 inclusive. + /// + public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComponent? perishable = null) + { + if (!Resolve(uid, ref comp, ref perishable)) + return 0; + + return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds); + } } diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index facbd1d71b6..3fc7e7247e6 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -2291,6 +2291,55 @@ public static readonly CVarDef /// public static readonly CVarDef StationGoalsChance = CVarDef.Create("game.station_goals_chance", 0.1f, CVar.SERVERONLY); + + + #region CPR System + /// + /// Controls whether the entire CPR system runs. When false, nobody can perform CPR. You should probably remove the trait too + /// if you are wishing to permanently disable the system on your server. + /// + public static readonly CVarDef EnableCPR = + CVarDef.Create("cpr.enable", true, CVar.REPLICATED | CVar.SERVER); + + /// + /// Toggles whether or not CPR reduces rot timers(As an abstraction of delaying brain death, the IRL actual purpose of CPR) + /// + public static readonly CVarDef CPRReducesRot = + CVarDef.Create("cpr.reduces_rot", true, CVar.REPLICATED | CVar.SERVER); + + /// + /// Toggles whether or not CPR heals airloss, included for completeness sake. I'm not going to stop you if your intention is to make CPR do nothing. + /// I guess it might be funny to troll your players with? I won't judge. + /// + public static readonly CVarDef CPRHealsAirloss = + CVarDef.Create("cpr.heals_airloss", true, CVar.REPLICATED | CVar.SERVER); + + /// + /// The chance for a patient to be resuscitated when CPR is successfully performed. + /// Setting this above 0 isn't very realistic, but people who see CPR in movies and TV will expect CPR to work this way. + /// + public static readonly CVarDef CPRResuscitationChance = + CVarDef.Create("cpr.resuscitation_chance", 0.05f, CVar.REPLICATED | CVar.SERVER); + + /// + /// By default, CPR reduces rot timers by an amount of seconds equal to the time spent performing CPR. This is an optional multiplier that can increase or decrease the amount + /// of rot reduction. Set it to 2 for if you want 3 seconds of CPR to reduce 6 seconds of rot. + /// + /// + /// If you're wondering why there isn't a CVar for setting the duration of the doafter, that's because it's not actually possible to have a timespan in cvar form + /// Curiously, it's also not possible for **shared** systems to set variable timespans. Which is where this system lives. + /// + public static readonly CVarDef CPRRotReductionMultiplier = + CVarDef.Create("cpr.rot_reduction_multiplier", 1f, CVar.REPLICATED | CVar.SERVER); + + /// + /// By default, CPR heals airloss by 1 point for every second spent performing CPR. Just like above, this directly multiplies the healing amount. + /// Set it to 2 to get 6 points of airloss healing for every 3 seconds of CPR. + /// + public static readonly CVarDef CPRAirlossReductionMultiplier = + CVarDef.Create("cpr.airloss_reduction_multiplier", 1f, CVar.REPLICATED | CVar.SERVER); + + #endregion #region Contests System diff --git a/Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs b/Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs new file mode 100644 index 00000000000..e01250858a1 --- /dev/null +++ b/Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs @@ -0,0 +1,33 @@ +using Robust.Shared.GameStates; +using Content.Shared.DoAfter; +using Robust.Shared.Audio; +using Robust.Shared.Serialization; + +namespace Content.Shared.Medical.CPR +{ + [RegisterComponent, NetworkedComponent] + public sealed partial class CPRTrainingComponent : Component + { + [DataField] + public SoundSpecifier CPRSound = new SoundPathSpecifier("/Audio/Effects/CPR.ogg"); + + /// + /// How long the doafter for CPR takes + /// + [DataField] + public TimeSpan DoAfterDuration = TimeSpan.FromSeconds(3); + + [DataField] + public int AirlossHeal = 6; + + [DataField] + public float CrackRibsModifier = 1f; + public EntityUid? CPRPlayingStream; + } + + [Serializable, NetSerializable] + public sealed partial class CPRDoAfterEvent : SimpleDoAfterEvent + { + + } +} diff --git a/Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs b/Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs new file mode 100644 index 00000000000..9840b8ffbd4 --- /dev/null +++ b/Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs @@ -0,0 +1,27 @@ +using Content.Shared.CCVar; +using Robust.Shared.Configuration; + +namespace Content.Shared.Medical.CPR +{ + public sealed partial class CPRSystem + { + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public bool EnableCPR { get; private set; } + public bool HealsAirloss { get; private set; } + public bool ReducesRot { get; private set; } + public float ResuscitationChance { get; private set; } + public float RotReductionMultiplier { get; private set; } + public float AirlossReductionMultiplier { get; private set; } + + private void InitializeCVars() + { + Subs.CVar(_cfg, CCVars.EnableCPR, value => EnableCPR = value, true); + Subs.CVar(_cfg, CCVars.CPRHealsAirloss, value => HealsAirloss = value, true); + Subs.CVar(_cfg, CCVars.CPRReducesRot, value => ReducesRot = value, true); + Subs.CVar(_cfg, CCVars.CPRResuscitationChance, value => ResuscitationChance = value, true); + Subs.CVar(_cfg, CCVars.CPRRotReductionMultiplier, value => RotReductionMultiplier = value, true); + Subs.CVar(_cfg, CCVars.CPRAirlossReductionMultiplier, value => AirlossReductionMultiplier = value, true); + } + } +} diff --git a/Content.Shared/Medical/CPR/Systems/CPRSystem.cs b/Content.Shared/Medical/CPR/Systems/CPRSystem.cs new file mode 100644 index 00000000000..799c0664a66 --- /dev/null +++ b/Content.Shared/Medical/CPR/Systems/CPRSystem.cs @@ -0,0 +1,132 @@ +using Content.Shared.Popups; +using Content.Shared.Atmos.Rotting; +using Content.Shared.Damage; +using Content.Shared.DoAfter; +using Content.Shared.Inventory; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.Verbs; +using Robust.Shared.Network; +using Robust.Shared.Utility; +using Robust.Shared.Random; +using Robust.Shared.Audio.Systems; + +namespace Content.Shared.Medical.CPR +{ + public sealed partial class CPRSystem : EntitySystem + { + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + [Dependency] private readonly SharedRottingSystem _rottingSystem = default!; + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly INetManager _net = default!; + public override void Initialize() + { + base.Initialize(); + InitializeCVars(); + SubscribeLocalEvent>(AddCPRVerb); + SubscribeLocalEvent(OnCPRDoAfter); + } + + private void AddCPRVerb(EntityUid uid, CPRTrainingComponent component, GetVerbsEvent args) + { + if (!EnableCPR || !args.CanInteract || !args.CanAccess + || !TryComp(args.Target, out var targetState) + || targetState.CurrentState == MobState.Alive) + return; + + InnateVerb verb = new() + { + Act = () => + { + StartCPR(uid, args.Target, component); + }, + Text = Loc.GetString("cpr-verb"), + Icon = new SpriteSpecifier.Rsi(new("Interface/Alerts/human_alive.rsi"), "health4"), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void StartCPR(EntityUid performer, EntityUid target, CPRTrainingComponent cprComponent) + { + if (HasComp(target)) + { + _popupSystem.PopupEntity(Loc.GetString("cpr-target-rotting", ("entity", target)), performer, performer); + return; + } + + if (_inventory.TryGetSlotEntity(target, "outerClothing", out var outer)) + { + _popupSystem.PopupEntity(Loc.GetString("cpr-must-remove", ("clothing", outer)), performer, performer, PopupType.MediumCaution); + return; + } + + if (_inventory.TryGetSlotEntity(target, "mask", out var mask)) + { + _popupSystem.PopupEntity(Loc.GetString("cpr-must-remove", ("clothing", mask)), performer, performer, PopupType.MediumCaution); + return; + } + + if (_inventory.TryGetSlotEntity(performer, "mask", out var maskSelf)) + { + _popupSystem.PopupEntity(Loc.GetString("cpr-must-remove-own-mask", ("clothing", maskSelf)), performer, performer, PopupType.MediumCaution); + return; + } + + if (_net.IsServer) + { + _popupSystem.PopupEntity(Loc.GetString("cpr-start-second-person", ("target", target)), target, performer, PopupType.Medium); + _popupSystem.PopupEntity(Loc.GetString("cpr-start-second-person-patient", ("user", performer)), target, target, PopupType.Medium); + cprComponent.CPRPlayingStream = _audio.PlayPvs(cprComponent.CPRSound, performer).Value.Entity; + } + + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, performer, cprComponent.DoAfterDuration, new CPRDoAfterEvent(), performer, target, performer) + { + BreakOnTargetMove = true, + BreakOnUserMove = true, + NeedHand = true, + BlockDuplicate = true + }); + } + + private void OnCPRDoAfter(EntityUid performer, CPRTrainingComponent component, CPRDoAfterEvent args) + { + component.CPRPlayingStream = _audio.Stop(component.CPRPlayingStream); + + if (args.Target == null) + return; + + if (HealsAirloss) + { + // There is PROBABLY a better way to do this, by all means let me know + var healing = new DamageSpecifier() + { + DamageDict = new() + { + { "Asphyxiation", -component.AirlossHeal * AirlossReductionMultiplier} + } + }; + _damageable.TryChangeDamage(args.Target, healing, true, origin: performer); + } + + if (ReducesRot) + _rottingSystem.ReduceAccumulator((EntityUid) args.Target, component.DoAfterDuration * RotReductionMultiplier); + + if (_robustRandom.Prob(ResuscitationChance) + && _mobThreshold.TryGetThresholdForState((EntityUid) args.Target, MobState.Dead, out var threshold) + && TryComp(args.Target, out var damageableComponent) + && TryComp(args.Target, out var state) + && damageableComponent.TotalDamage < threshold) + { + _mobStateSystem.ChangeMobState(args.Target.Value, MobState.Critical, state, performer); + } + } + } +} diff --git a/Resources/Audio/Effects/CPR.ogg b/Resources/Audio/Effects/CPR.ogg new file mode 100644 index 0000000000000000000000000000000000000000..2c7cedd2033c906029dcd1a8d90ab45b68bb0eba GIT binary patch literal 68840 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.mL>w?>>sa5J>hq2ux0H{*l6BSYS#*3Iz* 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

UUXQ{C-_~qG0dZv#l zCq_`E1x}SXgE`LQ zbrkgM_!ki11;k1qn1qlZ>3gGrlgiLc#;m7K+btJxRUTw*KY!M+G`4Gt zL!o!!t=q2pemc#DBobXk8@LecZ1vX+_U7cn-s3Nuw@%JLOx~W!vzwR2bO^gmY#ziR zUK28rv(w!%)+>qaP>q0wG|pQ;ayN|XGy)-K(|n*6JhSMK^}`F;Gat8djN-&9FH=U! zsK3F?$t=T;b=4`y+%#7bn0I?kP%P>~@yAbAJQn=iG=p{a8IT`UnE>*YwrMn$s#oO5 z6iX+$Om%$BuDNgi;4^=+4O`#AosL~gZ`25mst4u!QO5{fn{Aw>=I2~KYu4*$`>aF< zbDaIJ<%@4cdef;_BOB-{)ka=X;=rvhAHaElEJ}-Cge??rQT1Bep`4 z!1bNMLnhXf^IT+eXG*#(G(xB&sGsoAVnit6VgDJan8Bk4j?{f?<(_{#p~^jeN+mmo zGjPAi%Fd`+hRUKI1anaj?b928=EI88MEdokw_o2lKr4qJXd)+7R^F?3vf9ZSx|Q)G%#oW)tK_F)G}i&WSGGgV`sud z@r&}eb`%(1F&@sw@a0-a7d_o{$3&06>Ph{Bc)?bOqvA$`en>yJUJO-l^t=q%U1`WL z&qmmLx9pS}1!N15KFR3mckDlFz1VA(*~nVgEZvv#^SJ1MKUePm&`;*)_Q5%%&-gK(#xusMm618_PK{3@q~EU~XZe$M&vt;f`H3MH)H${hE|8*v&w7%IHE zPrkO={i3yfl-3lldHS4xJjzgBp&%7|R^q$$kp%K$)Rj6lJJX{zYT7qr)bh~8*I|OQ z&L4bMQ=tOvb)D@n{%fE!#gpQp$R{n7&enr!dSA4fthW9_%PR7IG)munD@O8?ip}58 zca0nu96BFafheG3^VgdK=Q%hmS(?upPCSZIhtCMT-uYi{(qMOW6`rGjAR;NjPF{u*AI~i89u%rBwDN`}Qeqk4b3f(A;2d zDH3A|Ri0Lh6oH_qWe4p=I3}vleR@IH16MxdA)A{vzv6*shF6v7j2rEF`SBaE10h|Z*(!2 ze~QwpJ)Sy=2YaX)ZgcPMDT`6<@f zg%_l-DW-TWxzD}PFlbg;_7oJW+6ek9H{b>|QHofMuIW6{&+GnW`RMH3^SKbY_2tkO zvn}aqp|=Vr5&S0k2&RTn(u?#vW(9ou0$4mYcreMDiSf8$7q1eJx^zT5us!&vy;(f?OFBw;9M`vdbK zK{?81CVms{)hG|uU0UO)g_fji5c8?fnu0Eh| zkLwv}W6It$n=sDMD!>=$$m#9M2_s61?#A{)7m9y1`eG&pEwWz&ak0>}+{#72V%ud; zjgxJpME!VWj%M=@>MwT-tb^P>tC6n8JduY^!cRcVGkeb`U?!F%0DR4#*wG66TX&!Z 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 literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/medical/components/cpr-training-component.ftl b/Resources/Locale/en-US/medical/components/cpr-training-component.ftl new file mode 100644 index 00000000000..7ed824a369f --- /dev/null +++ b/Resources/Locale/en-US/medical/components/cpr-training-component.ftl @@ -0,0 +1,6 @@ +cpr-start-second-person = You start performing CPR on {CAPITALIZE($target)}. +cpr-start-second-person-patient = {CAPITALIZE(THE($user))} starts performing CPR on you. +cpr-must-remove = You must remove {THE($clothing)} from the patient. +cpr-must-remove-own-mask = You must remove your {THE($clothing)}. +cpr-target-rotting = {CAPITALIZE($entity)} is too far gone... +cpr-verb = Perform CPR diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 600a9834fd4..f4c4b158fce 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -35,6 +35,13 @@ trait-description-Stutter = You t-t-talk with a bit of a s-s-stutter... trait-name-Snoring = Snoring trait-description-Snoring = You will snore while sleeping. +trait-name-CPRTraining = CPR Training +trait-description-CPRTraining = At some point in your life, you have received training in how to perform CPR. + This trait is automatically given for free to medical doctors, and is intended for non-medical characters + +trait-name-NormalVisionHarpy = Trichromat Modification +trait-description-NormalVisionHarpy = Your eyes have been modified by means of advanced medicine to see in the standard colors of Red, Green, and Blue. + trait-name-Southern = Southern Drawl trait-description-Southern = You have a different way of speakin'. diff --git a/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml b/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml index daf7f1195c0..f4b2fe95e14 100644 --- a/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml +++ b/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml @@ -26,6 +26,9 @@ special: - !type:AddImplantSpecial implants: [ MindShieldImplant ] + - !type:AddComponentSpecial + components: + - type: CPRTraining - type: startingGear id: CorpsmanGear # see Prototypes/Roles/Jobs/Fun/misc_startinggear.yml for "BrigmedicGear" diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml b/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml index 3fe22792092..66466352cbe 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml @@ -14,6 +14,10 @@ - Medical - Chemistry - Maintenance + special: + - !type:AddComponentSpecial + components: + - type: CPRTraining - type: startingGear id: ChemistGear diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index 4a65b791283..61b1df7784f 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -44,6 +44,7 @@ components: - type: PsionicBonusChance #Nyano - Summary: makes it more likely to become psionic. flatBonus: 0.025 + - type: CPRTraining - type: startingGear id: CMOGear diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml index cc048470f0c..627b0e17dc3 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml @@ -16,6 +16,10 @@ extendedAccess: - Chemistry - Paramedic # DeltaV - Add Paramedic access + special: + - !type:AddComponentSpecial + components: + - type: CPRTraining - type: startingGear id: DoctorGear diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml index 0166a3dfadb..003eab22d25 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml @@ -15,6 +15,10 @@ access: - Medical - Maintenance + special: + - !type:AddComponentSpecial + components: + - type: CPRTraining - type: startingGear id: MedicalInternGear diff --git a/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml b/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml index 9e3484a8dcf..0937a4627ae 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml @@ -23,6 +23,10 @@ - Paramedic # DeltaV - Add Paramedic access extendedAccess: - Chemistry + special: + - !type:AddComponentSpecial + components: + - type: CPRTraining - type: startingGear id: ParamedicGear diff --git a/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml b/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml index ac6e0620f5a..d13fd18afdd 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/senior_physician.yml @@ -21,6 +21,10 @@ - Medical - Maintenance - Chemistry + special: + - !type:AddComponentSpecial + components: + - type: CPRTraining - type: startingGear id: SeniorPhysicianGear diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index 16b628a56d8..b23e0216224 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -1,3 +1,20 @@ +- type: trait + id: CPRTraining + category: Mental + points: -2 + components: + - type: CPRTraining + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - MedicalDoctor + - Chemist + - MedicalIntern + - Paramedic + - ChiefMedicalOfficer + - Brigmedic + - type: trait id: HeavyweightDrunk category: Physical From b1674d169148573dfcc11a26156c1a4559672337 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 05:29:22 +0000 Subject: [PATCH 006/135] Automatic Changelog Update (#487) --- Resources/Changelog/Changelog.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index afe00fec1f2..e294394372d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4948,3 +4948,15 @@ Entries: message: Oneirophages are back! id: 6219 time: '2024-08-06T04:52:32.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: >- + CPR has been added to the game. People with CPR training can now perform + CPR on anyone who is in either crit or dead states. + - type: Add + message: >- + CPR Training has been added to the game as a new positive trait. All + medical staff start with this trait for free. + id: 6220 + time: '2024-08-06T05:28:54.0000000+00:00' From 22ff27c0985a04bf16a4e567326dfbd4ada4450e Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Tue, 6 Aug 2024 16:05:58 +0800 Subject: [PATCH 007/135] New Trait: Self-Aware (#680) # Description **Self-Aware** is a 2-point Mental trait that allows you to precisely examine your Brute/Burn damage as if using a health analyzer, and estimate the level of your toxin/airloss damage. Inspired by the SS13 trait of the same name. ## Media

Expand **Trait entry** ![image](https://github.com/user-attachments/assets/8faae16f-7dd5-42cd-8332-c65a0c610429) **No damage** ![image](https://github.com/user-attachments/assets/72bfa0f4-57fa-4b8d-b974-a604b4030ea6) **Damaged** ![image](https://github.com/user-attachments/assets/ec6318b4-41dc-4d3b-9aec-8f02333363e7)
# Changelog :cl: Skubman add: Add the Self-Aware trait, a 2-point trait that allows you to examine your Brute/Burn damage numbers like a health analyzer, and estimate your toxin/airloss damage. --------- Signed-off-by: Angelo Fallaria Co-authored-by: VMSolidus --- .../Body/Systems/BloodstreamSystem.cs | 15 ++- .../HealthExaminableComponent.cs | 8 +- .../HealthExaminableSystem.cs | 116 +++++++++++++++++- .../Traits/Assorted/SelfAwareComponent.cs | 31 +++++ .../Locale/en-US/bloodstream/bloodstream.ftl | 4 + .../health-examinable-selfaware.ftl | 22 ++++ Resources/Locale/en-US/traits/traits.ftl | 6 + Resources/Prototypes/Traits/skills.yml | 18 +++ 8 files changed, 210 insertions(+), 10 deletions(-) create mode 100644 Content.Server/Traits/Assorted/SelfAwareComponent.cs create mode 100644 Resources/Locale/en-US/health-examinable/health-examinable-selfaware.ftl diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index 9e29fdf7568..0edb190c16e 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -242,20 +242,29 @@ private void OnHealthBeingExamined(Entity ent, ref HealthB if (ent.Comp.BleedAmount > ent.Comp.MaxBleedAmount / 2) { args.Message.PushNewline(); - args.Message.AddMarkup(Loc.GetString("bloodstream-component-profusely-bleeding", ("target", ent.Owner))); + if (!args.IsSelfAware) + args.Message.AddMarkup(Loc.GetString("bloodstream-component-profusely-bleeding", ("target", ent.Owner))); + else + args.Message.AddMarkup(Loc.GetString("bloodstream-component-selfaware-profusely-bleeding")); } // Shows bleeding message when bleeding, but less than profusely. else if (ent.Comp.BleedAmount > 0) { args.Message.PushNewline(); - args.Message.AddMarkup(Loc.GetString("bloodstream-component-bleeding", ("target", ent.Owner))); + if (!args.IsSelfAware) + args.Message.AddMarkup(Loc.GetString("bloodstream-component-bleeding", ("target", ent.Owner))); + else + args.Message.AddMarkup(Loc.GetString("bloodstream-component-selfaware-bleeding")); } // If the mob's blood level is below the damage threshhold, the pale message is added. if (GetBloodLevelPercentage(ent, ent) < ent.Comp.BloodlossThreshold) { args.Message.PushNewline(); - args.Message.AddMarkup(Loc.GetString("bloodstream-component-looks-pale", ("target", ent.Owner))); + if (!args.IsSelfAware) + args.Message.AddMarkup(Loc.GetString("bloodstream-component-looks-pale", ("target", ent.Owner))); + else + args.Message.AddMarkup(Loc.GetString("bloodstream-component-selfaware-looks-pale")); } } diff --git a/Content.Server/HealthExaminable/HealthExaminableComponent.cs b/Content.Server/HealthExaminable/HealthExaminableComponent.cs index 3f434a93cfe..04053aed70e 100644 --- a/Content.Server/HealthExaminable/HealthExaminableComponent.cs +++ b/Content.Server/HealthExaminable/HealthExaminableComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.Damage.Prototypes; +using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; @@ -7,8 +7,12 @@ namespace Content.Server.HealthExaminable; [RegisterComponent, Access(typeof(HealthExaminableSystem))] public sealed partial class HealthExaminableComponent : Component { + // + // The thresholds for determining the examine text for certain amounts of damage. + // These are calculated as a percentage of the entity's critical threshold. + // public List Thresholds = new() - { FixedPoint2.New(10), FixedPoint2.New(25), FixedPoint2.New(50), FixedPoint2.New(75) }; + { FixedPoint2.New(0.10), FixedPoint2.New(0.25), FixedPoint2.New(0.50), FixedPoint2.New(0.75) }; [DataField("examinableTypes", required: true, customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] public HashSet ExaminableTypes = default!; diff --git a/Content.Server/HealthExaminable/HealthExaminableSystem.cs b/Content.Server/HealthExaminable/HealthExaminableSystem.cs index ed69a1c096a..89291726fbe 100644 --- a/Content.Server/HealthExaminable/HealthExaminableSystem.cs +++ b/Content.Server/HealthExaminable/HealthExaminableSystem.cs @@ -1,15 +1,20 @@ -using Content.Shared.Damage; +using Content.Server.Traits.Assorted; +using Content.Shared.Damage; using Content.Shared.Examine; using Content.Shared.FixedPoint; using Content.Shared.IdentityManagement; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Verbs; using Robust.Shared.Utility; +using System.Linq; namespace Content.Server.HealthExaminable; public sealed class HealthExaminableSystem : EntitySystem { [Dependency] private readonly ExamineSystemShared _examineSystem = default!; + [Dependency] private readonly MobThresholdSystem _threshold = default!; public override void Initialize() { @@ -29,7 +34,13 @@ private void OnGetExamineVerbs(EntityUid uid, HealthExaminableComponent componen { Act = () => { - var markup = CreateMarkup(uid, component, damage); + FormattedMessage markup; + if (uid == args.User + && TryComp(uid, out var selfAware)) + markup = CreateMarkupSelfAware(uid, selfAware, component, damage); + else + markup = CreateMarkup(uid, component, damage); + _examineSystem.SendExamineTooltip(args.User, uid, markup, false, false); }, Text = Loc.GetString("health-examinable-verb-text"), @@ -47,6 +58,9 @@ private FormattedMessage CreateMarkup(EntityUid uid, HealthExaminableComponent c var msg = new FormattedMessage(); var first = true; + + var adjustedThresholds = GetAdjustedThresholds(uid, component.Thresholds); + foreach (var type in component.ExaminableTypes) { if (!damage.Damage.DamageDict.TryGetValue(type, out var dmg)) @@ -58,7 +72,7 @@ private FormattedMessage CreateMarkup(EntityUid uid, HealthExaminableComponent c FixedPoint2 closest = FixedPoint2.Zero; string chosenLocStr = string.Empty; - foreach (var threshold in component.Thresholds) + foreach (var threshold in adjustedThresholds) { var str = $"health-examinable-{component.LocPrefix}-{type}-{threshold}"; var tempLocStr = Loc.GetString($"health-examinable-{component.LocPrefix}-{type}-{threshold}", ("target", Identity.Entity(uid, EntityManager))); @@ -94,10 +108,100 @@ private FormattedMessage CreateMarkup(EntityUid uid, HealthExaminableComponent c } // Anything else want to add on to this? - RaiseLocalEvent(uid, new HealthBeingExaminedEvent(msg), true); + RaiseLocalEvent(uid, new HealthBeingExaminedEvent(msg, false), true); return msg; } + + private FormattedMessage CreateMarkupSelfAware(EntityUid target, SelfAwareComponent selfAware, HealthExaminableComponent component, DamageableComponent damage) + { + var msg = new FormattedMessage(); + + var first = true; + + foreach (var type in selfAware.AnalyzableTypes) + { + if (!damage.Damage.DamageDict.TryGetValue(type, out var typeDmgUnrounded)) + continue; + + var typeDmg = (int) Math.Round(typeDmgUnrounded.Float(), 0); + if (typeDmg <= 0) + continue; + + var damageString = Loc.GetString( + "health-examinable-selfaware-type-text", + ("damageType", Loc.GetString($"health-examinable-selfaware-type-{type}")), + ("amount", typeDmg) + ); + + if (!first) + msg.PushNewline(); + else + first = false; + msg.AddMarkup(damageString); + } + + var adjustedThresholds = GetAdjustedThresholds(target, selfAware.Thresholds); + + foreach (var group in selfAware.DetectableGroups) + { + if (!damage.DamagePerGroup.TryGetValue(group, out var groupDmg) + || groupDmg == FixedPoint2.Zero) + continue; + + FixedPoint2 closest = FixedPoint2.Zero; + + string chosenLocStr = string.Empty; + foreach (var threshold in adjustedThresholds) + { + var locName = $"health-examinable-selfaware-group-{group}-{threshold}"; + var locStr = Loc.GetString(locName); + + var locDoesNotExist = locStr == locName; + if (locDoesNotExist) + continue; + + if (groupDmg > threshold && threshold > closest) + { + chosenLocStr = locStr; + closest = threshold; + } + } + + if (closest == FixedPoint2.Zero) + continue; + + if (!first) + msg.PushNewline(); + else + first = false; + msg.AddMarkup(chosenLocStr); + } + + if (msg.IsEmpty) + msg.AddMarkup(Loc.GetString($"health-examinable-selfaware-none")); + + // Event listeners can know if the examination is Self-Aware. + RaiseLocalEvent(target, new HealthBeingExaminedEvent(msg, true), true); + + return msg; + } + + /// + /// Return thresholds as percentages of an entity's critical threshold. + /// + private List GetAdjustedThresholds(EntityUid uid, List thresholdPercentages) + { + FixedPoint2 critThreshold = 0; + if (TryComp(uid, out var threshold)) + critThreshold = _threshold.GetThresholdForState(uid, Shared.Mobs.MobState.Critical, threshold); + + // Fallback to 100 crit threshold if none found + if (critThreshold == 0) + critThreshold = 100; + + return thresholdPercentages.Select(percentage => critThreshold * percentage).ToList(); + } } /// @@ -108,9 +212,11 @@ private FormattedMessage CreateMarkup(EntityUid uid, HealthExaminableComponent c public sealed class HealthBeingExaminedEvent { public FormattedMessage Message; + public bool IsSelfAware; - public HealthBeingExaminedEvent(FormattedMessage message) + public HealthBeingExaminedEvent(FormattedMessage message, bool isSelfAware) { Message = message; + IsSelfAware = isSelfAware; } } diff --git a/Content.Server/Traits/Assorted/SelfAwareComponent.cs b/Content.Server/Traits/Assorted/SelfAwareComponent.cs new file mode 100644 index 00000000000..03f5cd15502 --- /dev/null +++ b/Content.Server/Traits/Assorted/SelfAwareComponent.cs @@ -0,0 +1,31 @@ +using Content.Shared.Damage.Prototypes; +using Content.Shared.FixedPoint; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; + +namespace Content.Server.Traits.Assorted; + +/// +/// This is used for the Self-Aware trait to enhance the information received from HealthExaminableSystem. +/// +[RegisterComponent] +public sealed partial class SelfAwareComponent : Component +{ + // + // Damage types that an entity is able to precisely analyze like a health analyzer when they examine themselves. + // + [DataField(required: true, customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] + public HashSet AnalyzableTypes = default!; + + // + // Damage groups that an entity is able to detect the presence of when they examine themselves. + // + [DataField(required: true, customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] + public HashSet DetectableGroups = default!; + + // + // The thresholds for determining the examine text of DetectableGroups for certain amounts of damage. + // These are calculated as a percentage of the entity's critical threshold. + // + public List Thresholds = new() + { FixedPoint2.New(0.10), FixedPoint2.New(0.25), FixedPoint2.New(0.40), FixedPoint2.New(0.60) }; +} diff --git a/Resources/Locale/en-US/bloodstream/bloodstream.ftl b/Resources/Locale/en-US/bloodstream/bloodstream.ftl index 7d8f98c3087..65e475f1ab4 100644 --- a/Resources/Locale/en-US/bloodstream/bloodstream.ftl +++ b/Resources/Locale/en-US/bloodstream/bloodstream.ftl @@ -3,3 +3,7 @@ bloodstream-component-bleeding = [color=red]{CAPITALIZE(SUBJECT($target))} {CONJ bloodstream-component-profusely-bleeding = [color=crimson]{CAPITALIZE(SUBJECT($target))} {CONJUGATE-BE($target)} profusely bleeding![/color] bloodstream-component-wounds-cauterized = You feel your wounds painfully close! + +bloodstream-component-selfaware-looks-pale = [color=bisque]You feel dizzy from blood loss.[/color] +bloodstream-component-selfaware-bleeding = [color=red]You are bleeding.[/color] +bloodstream-component-selfaware-profusely-bleeding = [color=crimson]You are profusely bleeding![/color] diff --git a/Resources/Locale/en-US/health-examinable/health-examinable-selfaware.ftl b/Resources/Locale/en-US/health-examinable/health-examinable-selfaware.ftl new file mode 100644 index 00000000000..897c3f718de --- /dev/null +++ b/Resources/Locale/en-US/health-examinable/health-examinable-selfaware.ftl @@ -0,0 +1,22 @@ +health-examinable-selfaware-none = You feel healthy and well. + +health-examinable-selfaware-type-text = You have {$damageType}, around [bold]{$amount}[/bold]. + +health-examinable-selfaware-type-Blunt = [color=red]Blunt[/color] trauma +health-examinable-selfaware-type-Slash = [color=red]Slash[/color] wounds +health-examinable-selfaware-type-Piercing = [color=red]Piercing[/color] wounds + +health-examinable-selfaware-type-Heat = [color=orange]Heat[/color] burns +health-examinable-selfaware-type-Shock = [color=lightgoldenrodyellow]Shock[/color] burns +health-examinable-selfaware-type-Cold = [color=lightblue]Cold[/color] burns +health-examinable-selfaware-type-Caustic = [color=yellowgreen]Caustic[/color] burns + +health-examinable-selfaware-group-Toxin-10 = [color=green]You feel sick.[/color] +health-examinable-selfaware-group-Toxin-25 = [color=green]You feel nauseated.[/color] +health-examinable-selfaware-group-Toxin-40 = [color=green]You feel very unwell![/color] +health-examinable-selfaware-group-Toxin-60 = [color=green]You feel gravely ill![/color] + +health-examinable-selfaware-group-Airloss-10 = [color=lightblue]You feel lightheaded.[/color] +health-examinable-selfaware-group-Airloss-25 = [color=lightblue]You feel faint and woozy.[/color] +health-examinable-selfaware-group-Airloss-40 = [color=lightblue]You're struggling to breathe![/color] +health-examinable-selfaware-group-Airloss-60 = [color=lightblue]You're suffocating badly![/color] diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index f4c4b158fce..07ef099f832 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -8,6 +8,12 @@ trait-description-Narcolepsy = You fall asleep randomly trait-name-Pacifist = Pacifist trait-description-Pacifist = You cannot attack or hurt any living beings. +trait-name-SelfAware = Self-Aware +trait-description-SelfAware = + You possess a keen intuition of your body and senses. + You can accurately examine the severity of your wounds and burns like a health analyzer, + and can gauge if you have toxin or airloss damage. + trait-name-LightweightDrunk = Lightweight Drunk trait-description-LightweightDrunk = Alcohol has a stronger effect on you diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index b23e0216224..6d10886e8fa 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -15,6 +15,24 @@ - ChiefMedicalOfficer - Brigmedic +- type: trait + id: SelfAware + category: Mental + points: -2 + components: + - type: SelfAware + analyzableTypes: + - Blunt + - Slash + - Piercing + - Heat + - Shock + - Cold + - Caustic + detectableGroups: + - Airloss + - Toxin + - type: trait id: HeavyweightDrunk category: Physical From 5fcec4720ed3fb3697aa3517ce7fcfb3228493ae Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 08:06:27 +0000 Subject: [PATCH 008/135] Automatic Changelog Update (#680) --- Resources/Changelog/Changelog.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e294394372d..01f1a833faf 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4960,3 +4960,12 @@ Entries: medical staff start with this trait for free. id: 6220 time: '2024-08-06T05:28:54.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add the Self-Aware trait, a 2-point trait that allows you to examine + your Brute/Burn damage numbers like a health analyzer, and estimate your + toxin/airloss damage. + id: 6221 + time: '2024-08-06T08:05:59.0000000+00:00' From 498d070a73227dedb9e08636a6f574682b86f0d3 Mon Sep 17 00:00:00 2001 From: "Tad \"Taddy\" Johnson" <120885811+TadJohnson00@users.noreply.github.com> Date: Wed, 7 Aug 2024 05:05:46 +1000 Subject: [PATCH 009/135] Remove Overlay Restrict From Vulps (#683) # Description As title, will allow players to put as many overlay markings as required for their vulps. --- # Changelog :cl: TJohnson - tweak: Removed overlay restriction for vulps, you can now have as many overlay markings as you want! Signed-off-by: Tad "Taddy" Johnson <120885811+TadJohnson00@users.noreply.github.com> --- Resources/Prototypes/DeltaV/Species/vulpkanin.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Resources/Prototypes/DeltaV/Species/vulpkanin.yml b/Resources/Prototypes/DeltaV/Species/vulpkanin.yml index 8a3cd4c47ce..e139279dd5c 100644 --- a/Resources/Prototypes/DeltaV/Species/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Species/vulpkanin.yml @@ -62,9 +62,6 @@ points: 1 required: true defaultMarkings: [ VulpEar ] - Overlay: - points: 2 - required: false - type: humanoidBaseSprite id: MobVulpkaninHead From cb3ddd458132809a21f0bfc38028f0ed79795b83 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 19:06:41 +0000 Subject: [PATCH 010/135] Automatic Changelog Update (#683) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 01f1a833faf..39fcb78cfa7 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4969,3 +4969,11 @@ Entries: toxin/airloss damage. id: 6221 time: '2024-08-06T08:05:59.0000000+00:00' +- author: TJohnson + changes: + - type: Tweak + message: >- + Removed overlay restriction for vulps, you can now have as many overlay + markings as you want! + id: 6222 + time: '2024-08-06T19:05:46.0000000+00:00' From 55aa822a96f2ef8777e3b17efff0d4b4860b7010 Mon Sep 17 00:00:00 2001 From: username <113782077+whateverusername0@users.noreply.github.com> Date: Wed, 7 Aug 2024 05:08:47 +1000 Subject: [PATCH 011/135] Stamina Damage Resistance Real (#679) # Description Added stamina damage resistance, acts the same way as armor does. Call this shock resistance if you wish :trollface: Just attach StaminaDamageResistance component to an entity with a set multiplier and have fun. Made all hardsuits 25% stun resistant by default. With some variety, e.g. nukie, ERT, captain, HoS suits are 50%, DS are 90%, etc. etc. This will not remove stuneta but it will make it more difficult to stamcrit a traitor or such. Some armor/batong ratios that you need to hit before the target is stamcritted: 0% - 3 batong hits 25% - 4 batong hits 50% - 6 batong hits 75% - 12 batong hits 90% - 28 batong hits :trollface: 100% - ![image](https://github.com/user-attachments/assets/da147676-520b-4e3c-b027-ef9dc6a7394b) # Changelog :cl: - add: Added different stamina damage resistance to hardsuits. --------- Co-authored-by: whateverusername0 --- .../Abilities/Boxer/BoxingSystem.cs | 4 +- .../Nyanotrasen/Abilities/Oni/OniSystem.cs | 4 +- .../Nyanotrasen/Psionics/PsionicsSystem.cs | 12 +++-- ...eHitEvent.cs => TakeStaminaDamageEvent.cs} | 12 ++--- .../Damage/Systems/StaminaSystem.cs | 35 ++++++++++----- .../Inventory/InventorySystem.Relay.cs | 2 + .../StaminaDamageResistanceComponent.cs | 12 +++++ .../StaminaDamageResistanceSystem.cs | 26 +++++++++++ .../Locale/en-US/armor/armor-examine.ftl | 1 + .../OuterClothing/base_clothingouter.yml | 2 + .../Clothing/OuterClothing/hardsuits.yml | 44 +++++++++++++++++++ 11 files changed, 128 insertions(+), 26 deletions(-) rename Content.Shared/Damage/Events/{StaminaMeleeHitEvent.cs => TakeStaminaDamageEvent.cs} (67%) create mode 100644 Content.Shared/Stunnable/StaminaDamageResistanceComponent.cs create mode 100644 Content.Shared/Stunnable/StaminaDamageResistanceSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Boxer/BoxingSystem.cs b/Content.Server/Nyanotrasen/Abilities/Boxer/BoxingSystem.cs index 8bb68cb6f55..6f533c34199 100644 --- a/Content.Server/Nyanotrasen/Abilities/Boxer/BoxingSystem.cs +++ b/Content.Server/Nyanotrasen/Abilities/Boxer/BoxingSystem.cs @@ -14,7 +14,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnMeleeHit); - SubscribeLocalEvent(OnStamHit); + SubscribeLocalEvent(OnStamHit); } private void OnInit(EntityUid uid, BoxerComponent component, ComponentInit args) @@ -27,7 +27,7 @@ private void OnMeleeHit(EntityUid uid, BoxerComponent component, MeleeHitEvent a args.ModifiersList.Add(component.UnarmedModifiers); } - private void OnStamHit(EntityUid uid, BoxingGlovesComponent component, StaminaMeleeHitEvent args) + private void OnStamHit(EntityUid uid, BoxingGlovesComponent component, TakeStaminaDamageEvent args) { if (!_containerSystem.TryGetContainingContainer(uid, out var equipee)) return; diff --git a/Content.Server/Nyanotrasen/Abilities/Oni/OniSystem.cs b/Content.Server/Nyanotrasen/Abilities/Oni/OniSystem.cs index 6fdb27097e9..4fc078e85bc 100644 --- a/Content.Server/Nyanotrasen/Abilities/Oni/OniSystem.cs +++ b/Content.Server/Nyanotrasen/Abilities/Oni/OniSystem.cs @@ -21,7 +21,7 @@ public override void Initialize() SubscribeLocalEvent(OnEntRemoved); SubscribeLocalEvent(OnOniMeleeHit); SubscribeLocalEvent(OnHeldMeleeHit); - SubscribeLocalEvent(OnStamHit); + SubscribeLocalEvent(OnStamHit); } private void OnEntInserted(EntityUid uid, OniComponent component, EntInsertedIntoContainerMessage args) @@ -68,7 +68,7 @@ private void OnHeldMeleeHit(EntityUid uid, HeldByOniComponent component, MeleeHi args.ModifiersList.Add(oni.MeleeModifiers); } - private void OnStamHit(EntityUid uid, HeldByOniComponent component, StaminaMeleeHitEvent args) + private void OnStamHit(EntityUid uid, HeldByOniComponent component, TakeStaminaDamageEvent args) { if (!TryComp(component.Holder, out var oni)) return; diff --git a/Content.Server/Nyanotrasen/Psionics/PsionicsSystem.cs b/Content.Server/Nyanotrasen/Psionics/PsionicsSystem.cs index 5a96af2e96b..33505e3f6fc 100644 --- a/Content.Server/Nyanotrasen/Psionics/PsionicsSystem.cs +++ b/Content.Server/Nyanotrasen/Psionics/PsionicsSystem.cs @@ -51,7 +51,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnMeleeHit); - SubscribeLocalEvent(OnStamHit); + SubscribeLocalEvent(OnStamHit); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnRemove); @@ -110,14 +110,12 @@ private void OnRemove(EntityUid uid, PsionicComponent component, ComponentRemove _npcFactonSystem.RemoveFaction(uid, "PsionicInterloper"); } - private void OnStamHit(EntityUid uid, AntiPsionicWeaponComponent component, StaminaMeleeHitEvent args) + private void OnStamHit(EntityUid uid, AntiPsionicWeaponComponent component, TakeStaminaDamageEvent args) { var bonus = false; - foreach (var stam in args.HitList) - { - if (HasComp(stam.Entity)) - bonus = true; - } + + if (HasComp(args.Target)) + bonus = true; if (!bonus) return; diff --git a/Content.Shared/Damage/Events/StaminaMeleeHitEvent.cs b/Content.Shared/Damage/Events/TakeStaminaDamageEvent.cs similarity index 67% rename from Content.Shared/Damage/Events/StaminaMeleeHitEvent.cs rename to Content.Shared/Damage/Events/TakeStaminaDamageEvent.cs index c5ed0ddb602..6fca9dc2ef3 100644 --- a/Content.Shared/Damage/Events/StaminaMeleeHitEvent.cs +++ b/Content.Shared/Damage/Events/TakeStaminaDamageEvent.cs @@ -1,5 +1,5 @@ using Content.Shared.Damage.Components; -using Robust.Shared.Collections; +using Content.Shared.Inventory; namespace Content.Shared.Damage.Events; @@ -7,12 +7,14 @@ namespace Content.Shared.Damage.Events; /// The components in the list are going to be hit, /// give opportunities to change the damage or other stuff. /// -public sealed class StaminaMeleeHitEvent : HandledEntityEventArgs +public sealed class TakeStaminaDamageEvent : HandledEntityEventArgs, IInventoryRelayEvent { + public SlotFlags TargetSlots { get; } = ~SlotFlags.POCKET; + /// /// List of hit stamina components. /// - public List<(EntityUid Entity, StaminaComponent Component)> HitList; + public EntityUid Target; /// /// The multiplier. Generally, try to use *= or /= instead of overwriting. @@ -24,8 +26,8 @@ public sealed class StaminaMeleeHitEvent : HandledEntityEventArgs /// public float FlatModifier = 0; - public StaminaMeleeHitEvent(List<(EntityUid Entity, StaminaComponent Component)> hitList) + public TakeStaminaDamageEvent(EntityUid target) { - HitList = hitList; + Target = target; } } diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index de5338615ee..5c46e6055d1 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -166,20 +166,20 @@ private void OnMeleeHit(EntityUid uid, StaminaDamageOnHitComponent component, Me toHit.Add((ent, stam)); } - var hitEvent = new StaminaMeleeHitEvent(toHit); - RaiseLocalEvent(uid, hitEvent); + foreach (var (ent, comp) in toHit) + { + var hitEvent = new TakeStaminaDamageEvent(ent); + RaiseLocalEvent(uid, hitEvent); - if (hitEvent.Handled) - return; + if (hitEvent.Handled) + return; - var damage = component.Damage; + var damage = component.Damage; - damage *= hitEvent.Multiplier; + damage *= hitEvent.Multiplier; - damage += hitEvent.FlatModifier; + damage += hitEvent.FlatModifier; - foreach (var (ent, comp) in toHit) - { TakeStaminaDamage(ent, damage / toHit.Count, comp, source: args.User, with: args.Weapon, sound: component.Sound); } } @@ -204,12 +204,27 @@ private void OnThrowHit(EntityUid uid, StaminaDamageOnCollideComponent component private void OnCollide(EntityUid uid, StaminaDamageOnCollideComponent component, EntityUid target) { + if (!TryComp(target, out var stamComp)) + return; + var ev = new StaminaDamageOnHitAttemptEvent(); RaiseLocalEvent(uid, ref ev); if (ev.Cancelled) return; - TakeStaminaDamage(target, component.Damage, source: uid, sound: component.Sound); + var hitEvent = new TakeStaminaDamageEvent(target); + RaiseLocalEvent(target, hitEvent); + + if (hitEvent.Handled) + return; + + var damage = component.Damage; + + damage *= hitEvent.Multiplier; + + damage += hitEvent.FlatModifier; + + TakeStaminaDamage(target, damage, source: uid, sound: component.Sound); } private void SetStaminaAlert(EntityUid uid, StaminaComponent? component = null) diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index c43a5885077..3308e881c52 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -1,5 +1,6 @@ using Content.Shared.Chemistry; using Content.Shared.Damage; +using Content.Shared.Damage.Events; using Content.Shared.Electrocution; using Content.Shared.Explosion; using Content.Shared.Eye.Blinding.Systems; @@ -20,6 +21,7 @@ public partial class InventorySystem public void InitializeRelay() { SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); diff --git a/Content.Shared/Stunnable/StaminaDamageResistanceComponent.cs b/Content.Shared/Stunnable/StaminaDamageResistanceComponent.cs new file mode 100644 index 00000000000..dc291bbe8ba --- /dev/null +++ b/Content.Shared/Stunnable/StaminaDamageResistanceComponent.cs @@ -0,0 +1,12 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Stunnable; + +[RegisterComponent, NetworkedComponent] +public sealed partial class StaminaDamageResistanceComponent : Component +{ + /// + /// 1 - no reduction, 0 - full reduction + /// + [DataField] public float Coefficient = 1; +} diff --git a/Content.Shared/Stunnable/StaminaDamageResistanceSystem.cs b/Content.Shared/Stunnable/StaminaDamageResistanceSystem.cs new file mode 100644 index 00000000000..7632eed504d --- /dev/null +++ b/Content.Shared/Stunnable/StaminaDamageResistanceSystem.cs @@ -0,0 +1,26 @@ +using Content.Shared.Damage.Events; +using Content.Shared.Examine; +using Content.Shared.Inventory; + +namespace Content.Shared.Stunnable; + +public sealed partial class StaminaDamageResistanceSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnStaminaMeleeHit); + SubscribeLocalEvent(OnExamine); + } + + private void OnStaminaMeleeHit(Entity ent, ref InventoryRelayedEvent args) + { + args.Args.Multiplier *= ent.Comp.Coefficient; + } + private void OnExamine(Entity ent, ref ExaminedEvent args) + { + var percentage = (1 - ent.Comp.Coefficient) * 100; + args.PushMarkup(Loc.GetString("armor-examine-stamina", ("num", percentage))); + } +} diff --git a/Resources/Locale/en-US/armor/armor-examine.ftl b/Resources/Locale/en-US/armor/armor-examine.ftl index d49a1373f28..6dc511e66e5 100644 --- a/Resources/Locale/en-US/armor/armor-examine.ftl +++ b/Resources/Locale/en-US/armor/armor-examine.ftl @@ -17,3 +17,4 @@ armor-damage-type-cold = Cold armor-damage-type-poison = Poison armor-damage-type-shock = Shock armor-damage-type-structural = Structural +armor-examine-stamina = Reduces your stamina damage by [color=cyan]{$num}%[/color]. \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index 36327fe1f78..d6a2cd446be 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -142,6 +142,8 @@ - type: Clothing equipDelay: 2.5 # Hardsuits are heavy and take a while to put on/off. unequipDelay: 2.5 + - type: StaminaDamageResistance + coefficient: 0.75 # 25% - type: entity abstract: true diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml index e0d8e7290da..70ab3016469 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml @@ -100,6 +100,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitEngineering + - type: StaminaDamageResistance + coefficient: 0.75 # 25% #Spationaut Hardsuit - type: entity @@ -221,6 +223,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitSecurity + - type: StaminaDamageResistance + coefficient: 0.75 # 25% #Brigmedic Hardsuit - type: entity @@ -248,6 +252,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitBrigmedic + - type: StaminaDamageResistance + coefficient: 0.75 # 25% #Warden's Hardsuit - type: entity @@ -278,6 +284,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitWarden + - type: StaminaDamageResistance + coefficient: 0.65 # 35% #Captain's Hardsuit - type: entity @@ -310,6 +318,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitCap + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Chief Engineer's Hardsuit - type: entity @@ -345,6 +355,8 @@ - type: ClothingGrantComponent component: - type: SupermatterImmune + - type: StaminaDamageResistance + coefficient: 0.65 # 35% #Chief Medical Officer's Hardsuit - type: entity @@ -412,6 +424,8 @@ price: 750 - type: StealTarget stealGroup: ClothingOuterHardsuitRd + - type: StaminaDamageResistance + coefficient: 0.75 # 25% as in "shock resistance" :trollface: #Head of Security's Hardsuit - type: entity @@ -443,6 +457,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitSecurityRed + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Luxury Mining Hardsuit - type: entity @@ -520,6 +536,8 @@ - Hardsuit - WhitelistChameleon - HidesHarpyWings + - type: StaminaDamageResistance + coefficient: 0.5 # 50% # Syndicate Medic Hardsuit - type: entity @@ -539,6 +557,8 @@ - Hardsuit - WhitelistChameleon - HidesHarpyWings + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Syndicate Elite Hardsuit - type: entity @@ -575,6 +595,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitSyndieElite + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Syndicate Commander Hardsuit - type: entity @@ -607,6 +629,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitSyndieCommander + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Cybersun Juggernaut Hardsuit - type: entity @@ -639,6 +663,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitCybersun + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Wizard Hardsuit - type: entity @@ -671,6 +697,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitWizard + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Ling Space Suit - type: entity @@ -766,6 +794,8 @@ clothingPrototype: ClothingHeadHelmetHardsuitPirateCap - type: StaticPrice price: 0 + - type: StaminaDamageResistance + coefficient: 0.75 # 25% #CENTCOMM / ERT HARDSUITS #ERT Leader Hardsuit @@ -781,6 +811,8 @@ sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertleader.rsi - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitERTLeader + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #ERT Chaplain Hardsuit - type: entity @@ -795,6 +827,8 @@ sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertchaplain.rsi - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitERTChaplain + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #ERT Engineer Hardsuit - type: entity @@ -809,6 +843,8 @@ sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertengineer.rsi - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitERTEngineer + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #ERT Medic Hardsuit - type: entity @@ -823,6 +859,8 @@ sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertmedical.rsi - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitERTMedical + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #ERT Security Hardsuit - type: entity @@ -841,6 +879,8 @@ tags: - Hardsuit - WhitelistChameleon + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #ERT Janitor Hardsuit - type: entity @@ -855,6 +895,8 @@ sprite: Clothing/OuterClothing/Hardsuits/ERTSuits/ertjanitor.rsi - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitERTJanitor + - type: StaminaDamageResistance + coefficient: 0.5 # 50% #Deathsquad - type: entity @@ -889,6 +931,8 @@ - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitDeathsquad + - type: StaminaDamageResistance + coefficient: 0.1 # 90% #CBURN Hardsuit - type: entity From b7d30808f78456443343312d16b64ae01ea54d10 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 19:09:14 +0000 Subject: [PATCH 012/135] Automatic Changelog Update (#679) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 39fcb78cfa7..018c5adbd0d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4977,3 +4977,9 @@ Entries: markings as you want! id: 6222 time: '2024-08-06T19:05:46.0000000+00:00' +- author: whateverusername0 + changes: + - type: Add + message: Added different stamina damage resistance to hardsuits. + id: 6223 + time: '2024-08-06T19:08:48.0000000+00:00' From 6ab179737b5f42b800ab7436791509e9cc917254 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Wed, 7 Aug 2024 03:12:33 +0800 Subject: [PATCH 013/135] New Trait: Blood Deficiency (#686) # Description **Blood Deficiency** is a +2 points negative Physical trait that makes you slowly lose blood over time. When left untreated you will die from blood loss. Inspired by the SS13 trait of the same name. Slash/Piercing weapons and bleeding are much more lethal against you. The moment you start taking **any** blood loss damage, you start dying because you can't regenerate blood. Even just two consecutive kitchen knife stabs will make you bleed enough to die slowly unless you immediately apply gauze. Blood packs, iron pills (or copper for Arachnids), and gauze to stop bleeding will help you survive with this trait. Here's how the timeline looks for untreated blood deficiency: - ~0-21 minutes: losing blood slowly - ~21-31 minutes: blood level below 90%, start taking bloodloss damage - ~31-33 minutes: critical - ~34 minutes: death ## Media
Expand **Trait entry** ![image](https://github.com/user-attachments/assets/ea4a0c3c-7c05-45fc-8a32-48957701a246) ![image](https://github.com/user-attachments/assets/37398779-90a4-4f4f-a183-38d806184394) As shown above, even just reducing the blood volume to less than 90% means you will die a slow and painful death.

# Changelog :cl: Skubman - add: Add the Blood Deficiency trait, a new negative trait that makes you slowly lose blood over time. You must routinely receive blood loss treatment to live, and even normally non-lethal bleeding can make you start dying slowly. --- .../Body/Components/BloodstreamComponent.cs | 15 ++++++++++- .../Body/Systems/BloodstreamSystem.cs | 25 +++++++++++++++---- .../Traits/BloodDeficiencyComponent.cs | 14 +++++++++++ .../Traits/BloodDeficiencySystem.cs | 23 +++++++++++++++++ Resources/Locale/en-US/traits/traits.ftl | 5 ++++ Resources/Prototypes/Traits/disabilities.yml | 14 +++++++++++ 6 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 Content.Server/Traits/BloodDeficiencyComponent.cs create mode 100644 Content.Server/Traits/BloodDeficiencySystem.cs diff --git a/Content.Server/Body/Components/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs index 1d8aa9ffd3d..7a4af3e4cc1 100644 --- a/Content.Server/Body/Components/BloodstreamComponent.cs +++ b/Content.Server/Body/Components/BloodstreamComponent.cs @@ -1,5 +1,6 @@ using Content.Server.Body.Systems; using Content.Server.Chemistry.EntitySystems; +using Content.Server.Traits.Assorted; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Damage; @@ -11,7 +12,7 @@ namespace Content.Server.Body.Components { - [RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem))] + [RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem), typeof(BloodDeficiencySystem))] public sealed partial class BloodstreamComponent : Component { public static string DefaultChemicalsSolutionName = "chemicals"; @@ -171,5 +172,17 @@ public sealed partial class BloodstreamComponent : Component /// [ViewVariables(VVAccess.ReadWrite)] public TimeSpan StatusTime; + + /// + /// If this is true, the entity will not passively regenerate blood, + /// and instead will slowly lose blood. + /// + public bool HasBloodDeficiency = false; + + /// + /// How much reagent of blood should be removed with blood deficiency in each update interval? + /// + [DataField] + public FixedPoint2 BloodDeficiencyLossAmount; } } diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index 0edb190c16e..fafc649eb29 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -118,11 +118,14 @@ public override void Update(float frameTime) if (!_solutionContainerSystem.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution)) continue; - // Adds blood to their blood level if it is below the maximum; Blood regeneration. Must be alive. - if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid)) - { - TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream); - } + // Removes blood for Blood Deficiency constantly. + if (bloodstream.HasBloodDeficiency) + if (!_mobStateSystem.IsDead(uid)) + RemoveBlood(uid, bloodstream.BloodDeficiencyLossAmount, bloodstream); + // Adds blood to their blood level if it is below the maximum. + else if (bloodSolution.Volume < bloodSolution.MaxVolume) + if (!_mobStateSystem.IsDead(uid)) + TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream); // Removes blood from the bloodstream based on bleed amount (bleed rate) // as well as stop their bleeding to a certain extent. @@ -472,4 +475,16 @@ public void ChangeBloodReagent(EntityUid uid, string reagent, BloodstreamCompone if (currentVolume > 0) _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, currentVolume, out _); } + + /// + /// Remove blood from an entity, without spilling it. + /// + private void RemoveBlood(EntityUid uid, FixedPoint2 amount, BloodstreamComponent? component = null) + { + if (!Resolve(uid, ref component, logMissing: false) + || !_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution)) + return; + + bloodSolution.RemoveReagent(component.BloodReagent, amount); + } } diff --git a/Content.Server/Traits/BloodDeficiencyComponent.cs b/Content.Server/Traits/BloodDeficiencyComponent.cs new file mode 100644 index 00000000000..616f60cd834 --- /dev/null +++ b/Content.Server/Traits/BloodDeficiencyComponent.cs @@ -0,0 +1,14 @@ +namespace Content.Server.Traits.Assorted; + +/// +/// This is used for the Blood Deficiency trait. +/// +[RegisterComponent] +public sealed partial class BloodDeficiencyComponent : Component +{ + // + // How much reagent of blood should be removed in each update interval? + // + [DataField(required: true)] + public float BloodLossAmount; +} diff --git a/Content.Server/Traits/BloodDeficiencySystem.cs b/Content.Server/Traits/BloodDeficiencySystem.cs new file mode 100644 index 00000000000..f1ae4909956 --- /dev/null +++ b/Content.Server/Traits/BloodDeficiencySystem.cs @@ -0,0 +1,23 @@ +using Content.Server.Body.Systems; +using Content.Server.Body.Components; +using Content.Shared.Damage; + +namespace Content.Server.Traits.Assorted; + +public sealed class BloodDeficiencySystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + } + + private void OnStartup(EntityUid uid, BloodDeficiencyComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var bloodstream)) + return; + + bloodstream.HasBloodDeficiency = true; + bloodstream.BloodDeficiencyLossAmount = component.BloodLossAmount; + } +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 07ef099f832..bf0a44e767e 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -23,6 +23,11 @@ trait-description-HeavyweightDrunk = Alcohol is afraid of you. trait-name-Muted = Muted trait-description-Muted = You can't speak +trait-name-BloodDeficiency = Blood Deficiency +trait-description-BloodDeficiency = + Your body loses more blood than it can replenish. + You lose blood over time, and when left untreated you will eventually die from blood loss. + trait-name-Paracusia = Paracusia trait-description-Paracusia = You hear sounds that aren't really there diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index eb96d37e01a..afdd27f339d 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -94,3 +94,17 @@ - MedicalBorg components: - type: Snoring + +- type: trait + id: BloodDeficiency + category: Physical + points: 2 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + components: + - type: BloodDeficiency # 0.07 = start taking bloodloss damage at around ~21.4 minutes, + bloodLossAmount: 0.07 # then become crit ~10 minutes later From bc3ffaf0cb61ba7febfad2c94c90e3d371510fc6 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 19:13:16 +0000 Subject: [PATCH 014/135] Automatic Changelog Update (#686) --- Resources/Changelog/Changelog.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 018c5adbd0d..7b3e9c5f2cc 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4983,3 +4983,13 @@ Entries: message: Added different stamina damage resistance to hardsuits. id: 6223 time: '2024-08-06T19:08:48.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add the Blood Deficiency trait, a new negative trait that makes you + slowly lose blood over time. You must routinely receive blood loss + treatment to live, and even normally non-lethal bleeding can make you + start dying slowly. + id: 6224 + time: '2024-08-06T19:12:34.0000000+00:00' From 65748934f108517a3551805f20440038551fedb1 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Wed, 7 Aug 2024 03:50:19 +0800 Subject: [PATCH 015/135] New Trait: Oni Damage Bonuses (#676) # Description Adds three new 1-point traits for Onis that **redistribute** your damage bonuses, allowing you to specialize in Slash or Piercing instead of Blunt, or be a generalist who is equally effective with all melee Brute weapons. The three new traits are **Swashbuckler**, **Spearmaster**, and **Weapons Generalist**. | Traits / Damage Bonus | Blunt | Slash | Piercing | |------------------------|-------|-------|----------| | Base Oni (No Traits) | 35% | 20% | 20% | | **Swashbuckler** | 20% | 35% | 20% | | **Spearmaster** | 20% | 20% | 35% | | **Weapons Generalist** | 25% | 25% | 25% | # Changelog :cl: Skubman - add: Add three new 1-point traits for Onis that allow you to specialize in Slash or Piercing damage or be a melee weapons generalist. --------- Signed-off-by: Angelo Fallaria Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- .../Assorted/OniDamageModifierComponent.cs | 16 +++++ .../Assorted/OniDamageModifierSystem.cs | 31 ++++++++++ Resources/Locale/en-US/traits/traits.ftl | 15 +++++ Resources/Prototypes/Traits/species.yml | 62 +++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 Content.Server/Traits/Assorted/OniDamageModifierComponent.cs create mode 100644 Content.Server/Traits/Assorted/OniDamageModifierSystem.cs create mode 100644 Resources/Prototypes/Traits/species.yml diff --git a/Content.Server/Traits/Assorted/OniDamageModifierComponent.cs b/Content.Server/Traits/Assorted/OniDamageModifierComponent.cs new file mode 100644 index 00000000000..d6cf032aabd --- /dev/null +++ b/Content.Server/Traits/Assorted/OniDamageModifierComponent.cs @@ -0,0 +1,16 @@ +using Content.Shared.Damage; + +namespace Content.Server.Traits.Assorted; + +/// +/// This is used for traits that modify Oni damage modifiers. +/// +[RegisterComponent] +public sealed partial class OniDamageModifierComponent : Component +{ + /// + /// Which damage modifiers to override. + /// + [DataField("modifiers", required: true)] + public DamageModifierSet MeleeModifierReplacers = default!; +} diff --git a/Content.Server/Traits/Assorted/OniDamageModifierSystem.cs b/Content.Server/Traits/Assorted/OniDamageModifierSystem.cs new file mode 100644 index 00000000000..9d701053769 --- /dev/null +++ b/Content.Server/Traits/Assorted/OniDamageModifierSystem.cs @@ -0,0 +1,31 @@ +using Content.Server.Abilities.Oni; +using Content.Shared.Damage; + +namespace Content.Server.Traits.Assorted; + +public sealed class OniDamageModifierSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + } + + private void OnStartup(EntityUid uid, OniDamageModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var oni)) + return; + + foreach (var (key, value) in component.MeleeModifierReplacers.Coefficients) + { + oni.MeleeModifiers.Coefficients[key] = value; + + } + + foreach (var (key, value) in component.MeleeModifierReplacers.FlatReduction) + { + oni.MeleeModifiers.FlatReduction[key] = value; + + } + } +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index bf0a44e767e..528517684c4 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -87,3 +87,18 @@ trait-description-Voracious = trait-name-LightStep = Light Step trait-description-LightStep = You move with a gentle step, making your footsteps quieter. + +trait-name-Swashbuckler = Swashbuckler +trait-description-Swashbuckler = + You are an expert in swordsmanship, wielding swords, knives, and other blades with unrivaled finesse. + Your melee Slash bonus is increased to 35%, but your melee Blunt bonus is reduced to 20%. + +trait-name-Spearmaster = Spearmaster +trait-description-Spearmaster = + You have an outstanding proficiency with spears, wielding them as an extension of your body. + Your melee Piercing bonus is increased to 35%, but your melee Blunt bonus is reduced to 20%. + +trait-name-WeaponsGeneralist = Weapons Generalist +trait-description-WeaponsGeneralist = + You are a jack of all trades with melee weapons, enabling you to be versatile with your weapon arsenal. + Your melee damage bonus for all Brute damage types (Blunt, Slash, Piercing) becomes 25%. \ No newline at end of file diff --git a/Resources/Prototypes/Traits/species.yml b/Resources/Prototypes/Traits/species.yml new file mode 100644 index 00000000000..2c298252289 --- /dev/null +++ b/Resources/Prototypes/Traits/species.yml @@ -0,0 +1,62 @@ +- type: trait + id: Swashbuckler + category: Physical + points: -1 + components: + - type: OniDamageModifier + modifiers: + coefficients: + Blunt: 1.2 + Slash: 1.35 + Piercing: 1.2 + requirements: + - !type:CharacterSpeciesRequirement + species: + - Oni + - !type:CharacterTraitRequirement + inverted: true + traits: + - Spearmaster + - WeaponsGeneralist + +- type: trait + id: Spearmaster + category: Physical + points: -1 + components: + - type: OniDamageModifier + modifiers: + coefficients: + Blunt: 1.2 + Slash: 1.2 + Piercing: 1.35 + requirements: + - !type:CharacterSpeciesRequirement + species: + - Oni + - !type:CharacterTraitRequirement + inverted: true + traits: + - Swashbuckler + - WeaponsGeneralist + +- type: trait + id: WeaponsGeneralist + category: Physical + points: -1 + components: + - type: OniDamageModifier + modifiers: + coefficients: + Blunt: 1.25 + Slash: 1.25 + Piercing: 1.25 + requirements: + - !type:CharacterSpeciesRequirement + species: + - Oni + - !type:CharacterTraitRequirement + inverted: true + traits: + - Swashbuckler + - Spearmaster From 0e293730ebcb5f38f0a8cd455f90b399369ddbcb Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 19:50:43 +0000 Subject: [PATCH 016/135] Automatic Changelog Update (#676) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 7b3e9c5f2cc..6263b7d4005 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4993,3 +4993,11 @@ Entries: start dying slowly. id: 6224 time: '2024-08-06T19:12:34.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add three new 1-point traits for Onis that allow you to specialize in + Slash or Piercing damage or be a melee weapons generalist. + id: 6225 + time: '2024-08-06T19:50:20.0000000+00:00' From 32b08b03501bd65faed05fdffa1c8f7a6d55b016 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Tue, 6 Aug 2024 16:23:34 -0400 Subject: [PATCH 017/135] Port Justice Department From DeltaV (#675) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This ports https://github.com/DeltaV-Station/Delta-v/pull/660 > ## About the PR > Adds the Justice Department, a department enveloping the lawyer and 3 new roles that manage the court system and charges against the accused. Includes: • New department, Justice! • 3 new roles: ◦ Chief Justice: The main, impartial judge for the station responsible for adjudicating criminal and civil trials, as well as other small matters like paroles and pardons. ◦ Clerk: The court clerk, who organizes trials, notarizes court documents (warrants, sentences, etc), and ensures correct sentencing and due process for the accused in sec custody. ◦ Prosecutor: A special lawyer role that legally advises sec and handles all of its court prep and prosecution, freeing up sec's time to go stun baton the clown instead of waiting for trial. • Antag objective to steal the Clerk's notary stamp, an object imbued with the authority to officialize court decisions. • Made the Lawyer role easier to understand and added them to the department. Renamed to Attorney, they now exclusively defend the accused or can sue on their behalf. Can also curse at the prosecutor in the bar. • Changed SoP to match. Notable changes include ◦ Felony charges and above must be reviewed and approved by the Clerk or Chief Justice if those roles are active. ◦ Parole, criminal trials, and civil trials are now all adjudicated by the Chief Justice, or the clerk in their absence. ◦ To ensure fair judgement, a Captain can only remove the Chief Justice with a majority vote from command. ◦ Warrants and court decisions must be written down and stamped with the notary stamp. Warrants must be approved by the Chief Justice. ◦ Full list of SoP changes can be found here: https://docs.google.com/document/d/12ZKTtzvVWBuC7PuiREL9v7mhVZve11p0-T6MBPpVeGs/edit?usp=sharing • Classy wooden desk timer to help keep trials timely and within limits. > > **TO DO:** Chief Justice > > * [x] Role > * [x] Inventory > * [x] Job Description > * [x] Icon > * [x] Access (CMD/CJ/Sec/Justice*) > * [x] Airlocks > * [x] Spawnpoint > * [x] Closet(just reuse legal w/ a lock) > * [x] Gavel** (proto/sprite/sound) > * [x] Stamp (proto/sprite) > * [x] Drip > > Court Clerk > > * [x] Role > * [x] Inventory > * [x] Job Description > * [x] Icon > * [x] Access (Sec/Justice*) > * [x] Spawnpoint > * [x] Closet(just reuse legal w/ a lock) > * [x] Stamp** (proto/sprite) > * [x] Warrant document > * [x] Drip > > Prosecutor > > * [x] Role > * [x] Inventory > * [x] Job Description > * [x] Icon > * [x] Access (Sec/Justice*) > * [x] Spawnpoint > * [x] Closet(just reuse legal w/ a lock) > * [x] Drip(Can be same as lawyer but should have a unique badge) > > SoP/Guidlines > > * [x] Civil and criminal law-penalties > * [x] Legal mutiny? > * [x] Assigning judges when no judge is present > * [x] Judge is representative of CC. Not necessarily _above_ captain but outside. > * [x] When to appeal to a jury? How to pick a jury? (random would be good) > * [x] Rules for gaining warrants > * [x] Procedure for arresting officer filing criminal charges > * [x] Rules for summoning witnesses > * [ ] Guide/book > > Other > > * [ ] Station Beacons > > ## Notes: > * We might want to consider bringing back brig access for cells to give legal dept sec access and not control over prisoners. > * Mapping would need to provide offices for CJ, CC, and Prosecuter. > * Chief Justice is a rep of CC not necessarily above captain but outside > > ## Why / Balance > The current legal system in-game is built around LRP gameplay, with security handling everything relating to arrests, sentencing, trials, and execution. Additionally, it is near-impossible to find an impartial judge for any court case with the current system. New legal department would guarantee an impartial and available judge (whether it be the Chief Justice or Clerk) for any court case, take pressure off of security to handle things like sentencing and trials. Additionally, there will be more roleplay opportunities for things like civil cases, inter-department disputes, internal affairs, or whatever else you may need legal help with. > > ## Technical details > n/a > > ## Media > ![image](https://private-user-images.githubusercontent.com/136020119/295444469-8569ec5a-8a44-41a5-83c8-165c940e9a9a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjI4MjY5MTEsIm5iZiI6MTcyMjgyNjYxMSwicGF0aCI6Ii8xMzYwMjAxMTkvMjk1NDQ0NDY5LTg1NjllYzVhLThhNDQtNDFhNS04M2M4LTE2NWM5NDBlOWE5YS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgwNVQwMjU2NTFaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT03ZjE2M2UxNmE2OWE3YmNkM2MwMzY3YmQ5MWU5MGEwNzFjZTg5NDAyMGZkNzkyZTJjZDRhYWJlYzk1MTNmZDg3JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.kv3SVoSKceqwlIctnBa4u6E3NHMJ3rPrg3VxoTl-jZQ) ![image](https://private-user-images.githubusercontent.com/136020119/295444610-9ab40e2b-149b-4d9d-af13-47c8fec40be3.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjI4MjY5MTEsIm5iZiI6MTcyMjgyNjYxMSwicGF0aCI6Ii8xMzYwMjAxMTkvMjk1NDQ0NjEwLTlhYjQwZTJiLTE0OWItNGQ5ZC1hZjEzLTQ3YzhmZWM0MGJlMy5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgwNVQwMjU2NTFaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT01ZDUyZWQ4NWVkZTM5NDlhNDcxNTNiZGIxZDljMjJkZTBmZThmN2IxNWEwMzk5MWQwMDdjNmQ4MWY1NTcxNWFlJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.jZUnQ8Xj6uor4NAU-IHU7MoD1e3F964XkmZ3aNjPj0U) > > * [x] I have added screenshots/videos to this PR showcasing its changes in-game, **or** this PR does not require an in-game showcase > > ## Breaking changes > none that I know of 😓 > **Changelog** 🆑 Leo, Velcroboy, and Timemaster - add: Added The Justice Department >:) --- .../Components/IdCardConsoleComponent.cs | 3 + Resources/Audio/DeltaV/Items/gavel.ogg | Bin 0 -> 10265 bytes .../en-US/deltav/devices/device-network.ftl | 2 + .../deltav/headset/headset-component.ftl | 2 + .../en-US/deltav/job/department-desc.ftl | 2 + .../Locale/en-US/deltav/job/department.ftl | 2 + .../en-US/deltav/job/job-description.ftl | 4 + .../Locale/en-US/deltav/job/job-names.ftl | 5 + .../en-US/deltav/job/job-supervisors.ftl | 2 + Resources/Locale/en-US/deltav/misc/pda.ftl | 4 + .../deltav/navmap-beacons/station-beacons.ftl | 4 + .../en-US/deltav/paper/stamp-component.ftl | 5 +- .../deltav/prototypes/access/accesses.ftl | 5 +- Resources/Locale/en-US/job/job-names.ftl | 3 +- Resources/Prototypes/Access/misc.yml | 3 + .../Prototypes/DeltaV/Access/justice.yml | 20 ++ Resources/Prototypes/DeltaV/Access/misc.yml | 3 + .../DeltaV/Catalog/Fills/Boxes/general.yml | 26 +++ .../DeltaV/Catalog/Fills/Boxes/pda.yml | 13 ++ .../Catalog/Fills/Lockers/chiefjustice.yml | 21 ++ .../DeltaV/Catalog/Fills/Lockers/clerk.yml | 14 ++ .../DeltaV/Device/devicenet_frequencies.yml | 5 + .../Entities/Clothing/Ears/headsets.yml | 40 ++++ .../DeltaV/Entities/Clothing/Head/hats.yml | 12 ++ .../DeltaV/Entities/Clothing/Neck/cloaks.yml | 12 ++ .../DeltaV/Entities/Clothing/Neck/misc.yml | 13 ++ .../Entities/Clothing/OuterClothing/coats.yml | 14 ++ .../Entities/Clothing/OuterClothing/vests.yml | 12 ++ .../Entities/Clothing/Uniforms/jumpskirts.yml | 34 +++ .../Entities/Clothing/Uniforms/jumpsuits.yml | 56 +++++ .../DeltaV/Entities/Markers/Spawners/jobs.yml | 52 +++++ .../Entities/Objects/Devices/door_remote.yml | 15 ++ .../Objects/Devices/encryption_keys.yml | 16 ++ .../DeltaV/Entities/Objects/Devices/pda.yml | 117 +++++++++++ .../Objects/Devices/station_beacon.yml | 25 +++ .../DeltaV/Entities/Objects/Misc/paper.yml | 25 +++ .../Entities/Objects/Misc/rubber_stamp.yml | 30 +++ .../Objects/Specific/Justice/gavel.yml | 21 ++ .../Objects/Specific/Justice/gavelblock.yml | 19 ++ .../Objects/Specific/Justice/trialtimer.yml | 24 +++ .../Structures/Doors/Airlocks/access.yml | 82 ++++++++ .../Structures/Doors/Airlocks/airlocks.yml | 22 ++ .../Structures/Doors/Windoors/windoor.yml | 36 ++++ .../Storage/Closets/Lockers/lockers.yml | 25 +++ .../Structures/Wallmounts/Signs/signs.yml | 22 ++ .../DeltaV/Objectives/stealTargetGroups.yml | 9 + .../Prototypes/DeltaV/Objectives/traitor.yml | 13 ++ .../Roles/Jobs/Justice/chief_justice.yml | 59 ++++++ .../DeltaV/Roles/Jobs/Justice/clerk.yml | 41 ++++ .../DeltaV/Roles/Jobs/Justice/prosecutor.yml | 34 +++ .../DeltaV/Roles/Jobs/departments.yml | 11 + .../DeltaV/Roles/play_time_trackers.yml | 3 + .../Prototypes/DeltaV/StatusEffects/job.yml | 21 ++ .../Prototypes/DeltaV/radio_channels.yml | 11 +- Resources/Prototypes/DeltaV/tags.yml | 6 + .../Devices/Electronics/door_access.yml | 24 +++ .../Objects/Devices/encryption_keys.yml | 1 + .../Objects/Misc/identification_cards.yml | 55 ++++- .../Objects/Tools/access_configurator.yml | 3 + .../Structures/Doors/Airlocks/access.yml | 6 +- .../Structures/Doors/airlock_groups.yml | 2 + .../Structures/Machines/telecomms.yml | 82 ++++++++ .../Prototypes/Palettes/departmental.yml | 3 +- .../Prototypes/Roles/Jobs/Civilian/lawyer.yml | 2 +- .../Prototypes/Roles/Jobs/departments.yml | 2 +- .../Prototypes/Roles/play_time_trackers.yml | 9 + Resources/Prototypes/StatusEffects/job.yml | 4 +- .../justice.rsi/alt-equipped-EARS.png | Bin 0 -> 847 bytes .../Headsets/justice.rsi/equipped-EARS.png | Bin 0 -> 628 bytes .../Ears/Headsets/justice.rsi/icon.png | Bin 0 -> 728 bytes .../Ears/Headsets/justice.rsi/icon_alt.png | Bin 0 -> 876 bytes .../Ears/Headsets/justice.rsi/meta.json | 25 +++ .../Hats/cj_toque.rsi/equipped-HELMET.png | Bin 0 -> 781 bytes .../Clothing/Head/Hats/cj_toque.rsi/icon.png | Bin 0 -> 647 bytes .../Head/Hats/cj_toque.rsi/inhand-left.png | Bin 0 -> 832 bytes .../Head/Hats/cj_toque.rsi/inhand-right.png | Bin 0 -> 806 bytes .../Clothing/Head/Hats/cj_toque.rsi/meta.json | 26 +++ .../Neck/Cloaks/cjcloak.rsi/equipped-NECK.png | Bin 0 -> 1771 bytes .../Clothing/Neck/Cloaks/cjcloak.rsi/icon.png | Bin 0 -> 1016 bytes .../Neck/Cloaks/cjcloak.rsi/inhand-left.png | Bin 0 -> 831 bytes .../Neck/Cloaks/cjcloak.rsi/inhand-right.png | Bin 0 -> 840 bytes .../Neck/Cloaks/cjcloak.rsi/meta.json | 26 +++ .../prosecutorbadge.rsi/equipped-NECK.png | Bin 0 -> 607 bytes .../Neck/Misc/prosecutorbadge.rsi/icon.png | Bin 0 -> 1018 bytes .../Neck/Misc/prosecutorbadge.rsi/meta.json | 18 ++ .../mantles/cjmantle.rsi/equipped-NECK.png | Bin 0 -> 1346 bytes .../Neck/mantles/cjmantle.rsi/icon.png | Bin 0 -> 744 bytes .../Neck/mantles/cjmantle.rsi/meta.json | 18 ++ .../cjrobe.rsi/equipped-OUTERCLOTHING.png | Bin 0 -> 1830 bytes .../OuterClothing/Coats/cjrobe.rsi/icon.png | Bin 0 -> 979 bytes .../Coats/cjrobe.rsi/inhand-left.png | Bin 0 -> 1058 bytes .../Coats/cjrobe.rsi/inhand-right.png | Bin 0 -> 1028 bytes .../OuterClothing/Coats/cjrobe.rsi/meta.json | 26 +++ .../clerkvest.rsi/equipped-OUTERCLOTHING.png | Bin 0 -> 1137 bytes .../Vests/clerkvest.rsi/icon.png | Bin 0 -> 709 bytes .../Vests/clerkvest.rsi/inhand-left.png | Bin 0 -> 785 bytes .../Vests/clerkvest.rsi/inhand-right.png | Bin 0 -> 787 bytes .../Vests/clerkvest.rsi/meta.json | 26 +++ .../cj.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 1719 bytes .../Uniforms/Jumpskirt/cj.rsi/icon.png | Bin 0 -> 995 bytes .../Uniforms/Jumpskirt/cj.rsi/inhand-left.png | Bin 0 -> 955 bytes .../Jumpskirt/cj.rsi/inhand-right.png | Bin 0 -> 939 bytes .../Uniforms/Jumpskirt/cj.rsi/meta.json | 26 +++ .../clerk.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 1384 bytes .../Uniforms/Jumpskirt/clerk.rsi/icon.png | Bin 0 -> 884 bytes .../Jumpskirt/clerk.rsi/inhand-left.png | Bin 0 -> 967 bytes .../Jumpskirt/clerk.rsi/inhand-right.png | Bin 0 -> 952 bytes .../Uniforms/Jumpskirt/clerk.rsi/meta.json | 26 +++ .../equipped-INNERCLOTHING.png | Bin 0 -> 1681 bytes .../Jumpskirt/prosecutorred.rsi/icon.png | Bin 0 -> 877 bytes .../prosecutorred.rsi/inhand-left.png | Bin 0 -> 983 bytes .../prosecutorred.rsi/inhand-right.png | Bin 0 -> 985 bytes .../Jumpskirt/prosecutorred.rsi/meta.json | 26 +++ .../cj.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 1559 bytes .../Uniforms/Jumpsuit/cj.rsi/icon.png | Bin 0 -> 902 bytes .../Uniforms/Jumpsuit/cj.rsi/inhand-left.png | Bin 0 -> 955 bytes .../Uniforms/Jumpsuit/cj.rsi/inhand-right.png | Bin 0 -> 939 bytes .../Uniforms/Jumpsuit/cj.rsi/meta.json | 26 +++ .../cj_white.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 9718 bytes .../Uniforms/Jumpsuit/cj_white.rsi/icon.png | Bin 0 -> 537 bytes .../Jumpsuit/cj_white.rsi/inhand-left.png | Bin 0 -> 7793 bytes .../Jumpsuit/cj_white.rsi/inhand-right.png | Bin 0 -> 7879 bytes .../Uniforms/Jumpsuit/cj_white.rsi/meta.json | 26 +++ .../cjformal.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 9423 bytes .../Uniforms/Jumpsuit/cjformal.rsi/icon.png | Bin 0 -> 5678 bytes .../Jumpsuit/cjformal.rsi/inhand-left.png | Bin 0 -> 7183 bytes .../Jumpsuit/cjformal.rsi/inhand-right.png | Bin 0 -> 7415 bytes .../Uniforms/Jumpsuit/cjformal.rsi/meta.json | 26 +++ .../clerk.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 1447 bytes .../Uniforms/Jumpsuit/clerk.rsi/icon.png | Bin 0 -> 910 bytes .../Jumpsuit/clerk.rsi/inhand-left.png | Bin 0 -> 967 bytes .../Jumpsuit/clerk.rsi/inhand-right.png | Bin 0 -> 952 bytes .../Uniforms/Jumpsuit/clerk.rsi/meta.json | 26 +++ .../equipped-INNERCLOTHING.png | Bin 0 -> 1615 bytes .../Jumpsuit/prosecutorred.rsi/icon.png | Bin 0 -> 868 bytes .../prosecutorred.rsi/inhand-left.png | Bin 0 -> 983 bytes .../prosecutorred.rsi/inhand-right.png | Bin 0 -> 985 bytes .../Jumpsuit/prosecutorred.rsi/meta.json | 26 +++ .../Misc/job_icons.rsi/ChiefJustice.png | Bin 0 -> 568 bytes .../Interface/Misc/job_icons.rsi/Clerk.png | Bin 0 -> 537 bytes .../Interface/Misc/job_icons.rsi/Lawyer.png | Bin 0 -> 539 bytes .../Misc/job_icons.rsi/Prosecutor.png | Bin 0 -> 5005 bytes .../Interface/Misc/job_icons.rsi/meta.json | 14 +- .../Interface/Paper/paper_heading_warrant.svg | 127 ++++++++++++ .../paper_heading_warrant.svg.200dpi.png | Bin 0 -> 10022 bytes .../paper_heading_warrant.svg.200dpi.png.yml | 2 + .../DeltaV/Markers/jobs.rsi/chiefjustice.png | Bin 0 -> 1439 bytes .../DeltaV/Markers/jobs.rsi/clerk.png | Bin 0 -> 1031 bytes .../DeltaV/Markers/jobs.rsi/meta.json | 9 + .../DeltaV/Markers/jobs.rsi/prosecutor.png | Bin 0 -> 836 bytes .../encryption_keys.rsi/justice_label.png | Bin 0 -> 570 bytes .../Devices/encryption_keys.rsi/meta.json | 9 +- .../DeltaV/Objects/Devices/pda.rsi/meta.json | 11 +- .../Devices/pda.rsi/pda-chiefjustice.png | Bin 0 -> 943 bytes .../Objects/Devices/pda.rsi/pda-clerk.png | Bin 0 -> 1022 bytes .../Devices/pda.rsi/pda-prosecutor.png | Bin 0 -> 6141 bytes .../Objects/Misc/bureaucracy.rsi/meta.json | 2 +- .../DeltaV/Objects/Misc/stamps.rsi/meta.json | 8 +- .../Objects/Misc/stamps.rsi/stamp-cj.png | Bin 0 -> 5263 bytes .../Objects/Misc/stamps.rsi/stamp-notary.png | Bin 0 -> 777 bytes .../Specific/Justice/gavel.rsi/icon.png | Bin 0 -> 434 bytes .../Justice/gavel.rsi/inhand-left.png | Bin 0 -> 11051 bytes .../Justice/gavel.rsi/inhand-right.png | Bin 0 -> 11817 bytes .../Specific/Justice/gavel.rsi/meta.json | 22 ++ .../Specific/Justice/gavelblock.rsi/icon.png | Bin 0 -> 225 bytes .../Specific/Justice/gavelblock.rsi/meta.json | 14 ++ .../Specific/Justice/trialtimer.rsi/meta.json | 14 ++ .../Justice/trialtimer.rsi/trialtimer.png | Bin 0 -> 1170 bytes .../Airlocks/Glass/justice.rsi/assembly.png | Bin 0 -> 1645 bytes .../Glass/justice.rsi/bolted_unlit.png | Bin 0 -> 144 bytes .../Airlocks/Glass/justice.rsi/closed.png | Bin 0 -> 1763 bytes .../Glass/justice.rsi/closed_unlit.png | Bin 0 -> 144 bytes .../Airlocks/Glass/justice.rsi/closing.png | Bin 0 -> 3014 bytes .../Glass/justice.rsi/closing_unlit.png | Bin 0 -> 432 bytes .../Airlocks/Glass/justice.rsi/deny_unlit.png | Bin 0 -> 321 bytes .../Glass/justice.rsi/emergency_unlit.png | Bin 0 -> 588 bytes .../Airlocks/Glass/justice.rsi/meta.json | 195 ++++++++++++++++++ .../Doors/Airlocks/Glass/justice.rsi/open.png | Bin 0 -> 760 bytes .../Airlocks/Glass/justice.rsi/opening.png | Bin 0 -> 3247 bytes .../Glass/justice.rsi/opening_unlit.png | Bin 0 -> 284 bytes .../Glass/justice.rsi/panel_closing.png | Bin 0 -> 445 bytes .../Airlocks/Glass/justice.rsi/panel_open.png | Bin 0 -> 315 bytes .../Glass/justice.rsi/panel_opening.png | Bin 0 -> 470 bytes .../Airlocks/Glass/justice.rsi/sparks.png | Bin 0 -> 697 bytes .../Glass/justice.rsi/sparks_broken.png | Bin 0 -> 183 bytes .../Glass/justice.rsi/sparks_damaged.png | Bin 0 -> 184 bytes .../Glass/justice.rsi/sparks_open.png | Bin 0 -> 175 bytes .../Airlocks/Glass/justice.rsi/welded.png | Bin 0 -> 296 bytes .../Standard/justice.rsi/assembly.png | Bin 0 -> 1369 bytes .../Standard/justice.rsi/bolted_unlit.png | Bin 0 -> 144 bytes .../Airlocks/Standard/justice.rsi/closed.png | Bin 0 -> 1488 bytes .../Standard/justice.rsi/closed_unlit.png | Bin 0 -> 144 bytes .../Airlocks/Standard/justice.rsi/closing.png | Bin 0 -> 2683 bytes .../Standard/justice.rsi/closing_unlit.png | Bin 0 -> 432 bytes .../Standard/justice.rsi/deny_unlit.png | Bin 0 -> 321 bytes .../Standard/justice.rsi/emergency_unlit.png | Bin 0 -> 588 bytes .../Airlocks/Standard/justice.rsi/meta.json | 195 ++++++++++++++++++ .../Airlocks/Standard/justice.rsi/open.png | Bin 0 -> 729 bytes .../Airlocks/Standard/justice.rsi/opening.png | Bin 0 -> 2825 bytes .../Standard/justice.rsi/opening_unlit.png | Bin 0 -> 284 bytes .../Standard/justice.rsi/panel_closing.png | Bin 0 -> 445 bytes .../Standard/justice.rsi/panel_open.png | Bin 0 -> 315 bytes .../Standard/justice.rsi/panel_opening.png | Bin 0 -> 470 bytes .../Airlocks/Standard/justice.rsi/sparks.png | Bin 0 -> 697 bytes .../Standard/justice.rsi/sparks_broken.png | Bin 0 -> 183 bytes .../Standard/justice.rsi/sparks_damaged.png | Bin 0 -> 184 bytes .../Standard/justice.rsi/sparks_open.png | Bin 0 -> 175 bytes .../Airlocks/Standard/justice.rsi/welded.png | Bin 0 -> 296 bytes .../Wallmounts/signs.rsi/direction_court.png | Bin 0 -> 898 bytes .../signs.rsi/direction_justice.png | Bin 0 -> 926 bytes .../Structures/Wallmounts/signs.rsi/meta.json | 10 +- .../Objects/Misc/bureaucracy.rsi/meta.json | 3 + .../bureaucracy.rsi/paper_stamp-notary.png | Bin 0 -> 625 bytes .../Structures/Storage/closet.rsi/cj.png | Bin 0 -> 5692 bytes .../Structures/Storage/closet.rsi/cj_door.png | Bin 0 -> 5840 bytes .../Structures/Storage/closet.rsi/cj_open.png | Bin 0 -> 5529 bytes .../Structures/Storage/closet.rsi/clerk.png | Bin 0 -> 5806 bytes .../Storage/closet.rsi/clerk_door.png | Bin 0 -> 5853 bytes .../Storage/closet.rsi/clerk_open.png | Bin 0 -> 5588 bytes .../Structures/Storage/closet.rsi/meta.json | 20 +- 220 files changed, 2278 insertions(+), 23 deletions(-) create mode 100644 Resources/Audio/DeltaV/Items/gavel.ogg create mode 100644 Resources/Locale/en-US/deltav/devices/device-network.ftl create mode 100644 Resources/Locale/en-US/deltav/job/department-desc.ftl create mode 100644 Resources/Locale/en-US/deltav/job/job-supervisors.ftl create mode 100644 Resources/Locale/en-US/deltav/misc/pda.ftl create mode 100644 Resources/Prototypes/DeltaV/Access/justice.yml create mode 100644 Resources/Prototypes/DeltaV/Catalog/Fills/Lockers/chiefjustice.yml create mode 100644 Resources/Prototypes/DeltaV/Catalog/Fills/Lockers/clerk.yml create mode 100644 Resources/Prototypes/DeltaV/Device/devicenet_frequencies.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Clothing/Neck/misc.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Objects/Devices/door_remote.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Objects/Misc/paper.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Objects/Specific/Justice/gavel.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Objects/Specific/Justice/gavelblock.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Objects/Specific/Justice/trialtimer.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Structures/Doors/Airlocks/airlocks.yml create mode 100644 Resources/Prototypes/DeltaV/Entities/Structures/Storage/Closets/Lockers/lockers.yml create mode 100644 Resources/Prototypes/DeltaV/Roles/Jobs/Justice/chief_justice.yml create mode 100644 Resources/Prototypes/DeltaV/Roles/Jobs/Justice/clerk.yml create mode 100644 Resources/Prototypes/DeltaV/Roles/Jobs/Justice/prosecutor.yml create mode 100644 Resources/Prototypes/DeltaV/Roles/Jobs/departments.yml create mode 100644 Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/alt-equipped-EARS.png create mode 100644 Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/equipped-EARS.png create mode 100644 Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/icon_alt.png create mode 100644 Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/equipped-HELMET.png create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/equipped-NECK.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/equipped-NECK.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/mantles/cjmantle.rsi/equipped-NECK.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/mantles/cjmantle.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Neck/mantles/cjmantle.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/equipped-OUTERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/equipped-OUTERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/ChiefJustice.png create mode 100644 Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/Clerk.png create mode 100644 Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/Lawyer.png create mode 100644 Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/Prosecutor.png create mode 100644 Resources/Textures/DeltaV/Interface/Paper/paper_heading_warrant.svg create mode 100644 Resources/Textures/DeltaV/Interface/Paper/paper_heading_warrant.svg.200dpi.png create mode 100644 Resources/Textures/DeltaV/Interface/Paper/paper_heading_warrant.svg.200dpi.png.yml create mode 100644 Resources/Textures/DeltaV/Markers/jobs.rsi/chiefjustice.png create mode 100644 Resources/Textures/DeltaV/Markers/jobs.rsi/clerk.png create mode 100644 Resources/Textures/DeltaV/Markers/jobs.rsi/prosecutor.png create mode 100644 Resources/Textures/DeltaV/Objects/Devices/encryption_keys.rsi/justice_label.png create mode 100644 Resources/Textures/DeltaV/Objects/Devices/pda.rsi/pda-chiefjustice.png create mode 100644 Resources/Textures/DeltaV/Objects/Devices/pda.rsi/pda-clerk.png create mode 100644 Resources/Textures/DeltaV/Objects/Devices/pda.rsi/pda-prosecutor.png create mode 100644 Resources/Textures/DeltaV/Objects/Misc/stamps.rsi/stamp-cj.png create mode 100644 Resources/Textures/DeltaV/Objects/Misc/stamps.rsi/stamp-notary.png create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/gavelblock.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/gavelblock.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/trialtimer.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Objects/Specific/Justice/trialtimer.rsi/trialtimer.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/assembly.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/bolted_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closed.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closed_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closing.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closing_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/deny_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/emergency_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/open.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/opening.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/opening_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/panel_closing.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/panel_open.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/panel_opening.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_broken.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_damaged.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_open.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/welded.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/assembly.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/bolted_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closed.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closed_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closing.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closing_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/deny_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/emergency_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/open.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/opening.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/opening_unlit.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/panel_closing.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/panel_open.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/panel_opening.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_broken.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_damaged.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_open.png create mode 100644 Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/welded.png create mode 100644 Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/direction_court.png create mode 100644 Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/direction_justice.png create mode 100644 Resources/Textures/Objects/Misc/bureaucracy.rsi/paper_stamp-notary.png create mode 100644 Resources/Textures/Structures/Storage/closet.rsi/cj.png create mode 100644 Resources/Textures/Structures/Storage/closet.rsi/cj_door.png create mode 100644 Resources/Textures/Structures/Storage/closet.rsi/cj_open.png create mode 100644 Resources/Textures/Structures/Storage/closet.rsi/clerk.png create mode 100644 Resources/Textures/Structures/Storage/closet.rsi/clerk_door.png create mode 100644 Resources/Textures/Structures/Storage/closet.rsi/clerk_open.png diff --git a/Content.Shared/Access/Components/IdCardConsoleComponent.cs b/Content.Shared/Access/Components/IdCardConsoleComponent.cs index 417b77855cc..c994d83d9c5 100644 --- a/Content.Shared/Access/Components/IdCardConsoleComponent.cs +++ b/Content.Shared/Access/Components/IdCardConsoleComponent.cs @@ -89,6 +89,9 @@ public WriteToTargetIdMessage(string fullName, string jobTitle, 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 P@xgTe~DWM4f39E$c literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/equipped-EARS.png b/Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/equipped-EARS.png new file mode 100644 index 0000000000000000000000000000000000000000..0633bb36441674a5eddb9d7907ca1a5b08699128 GIT binary patch literal 628 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV9d*Ob`Ho)PG(@xm{>aTthP&_ z#Ibtg4hbEPNk?OOB70_OOzd^rcrdBQ=*FF$pO-$nxAU&`h2p0&+$<%N1E*)vB zS)(9R^rYd?bT9uYKRpYVoyqT-8&M+jXVvm)KM!`w=cLF6@9?+Cc-H0i)aI31;}lbK z?XBKv=6Zo@oeL%|IALVT^~HOu%I5vG5A*NyRDP8Bv_0~upnKbz3g<;)OS8SQqP|S2 zu?!1+xBqj=B1R(&bLiX^rmfIwWhd+eWPjRBJCS@o8xZY z-}QyHZ$XC7ZKqc&fDyo1;1OBOz`%C|gc+x5^GO2**Lb=(hE&A8y|t0IK|z2u;E~L_ z2MT90AI-{2PU37~?n?h#Trn-UoKJbaBeXWy?yT}1n?a;u$h>hXKz2(g#_i`P}^{@Un{6BCZw#M`GOv&sQ o;qr&hXurt8riDWwL%4#$q+NJ@K~vOgpt~77UHx3vIVCg!0LP{XRR910 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0ce0c363f81ec594bc330d63cd30799599611907 GIT binary patch literal 728 zcmV;}0w?{6P)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmY3labT3lag+-G2N4009t5L_t(oN9|Ox4uUWcJ&Y3xj>5!-i%$Fm zD}Tb`H^K*qi)>6qH;E+10l6j+FbG%L#KB%d3iR&YyLasYXwwR41^!(DLqq__aq5j_ z!M!YjF(wo%f-~xi;CY^R4}ME0r6%Zu`@XM~#EMD+{lYMW%=3$OKv-(=_=jwgl&atdWPw z&hzU1;lP1WjdPm9CCdi!wrzK_p(qMc?lrXn1Zyhh07;TePC_a;<`QZF_B@W`$=-{A zQ;Q$?^=0mFeEYu$WG?6vOa`2EP{s%?IdF4@>3yw$RzNH869wM2dTcC2di%!!0000< KMNUMnLSTYB21$$n literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/icon_alt.png b/Resources/Textures/DeltaV/Clothing/Ears/Headsets/justice.rsi/icon_alt.png new file mode 100644 index 0000000000000000000000000000000000000000..2142eee0392083d55fbd91f71fb92f30607e72ee GIT binary patch literal 876 zcmV-y1C#uTP)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmY3labT3lag+-G2N400E>)L_t(oN9~j`Pr^_T#}608gt}QKHe75R z7)TnN7-WS{!s4f6U~R&vbrBO1rh+U&Y$XoW|0UPd(E8qMH7>oRd2QdlyWjoayGK-6 zr9h>?KPyl(&41bH#8`7$uP00Iecw2aEH+wr?KqrV?EP?H5E+YrXak^fN%pi@@VYD@ znbTEP3qTT~(yRoSPpe@9p#-=c4B{|~XtUjZ+jmr$mRun4-vr=9CDn8`tDQ9(N6D>b zlK>~{0l3@m`H_RFij8@t0(n7DF(6>i%O%a{^Tf5+>k;Nml+b}a^0{%{xYcUKtJR91 zZnqmpQN-`~uM+40La{Kw`nq&P#A{v@bK4CaOVElz z5GdPR>0sM-(oXC3I@2E)&z0jOML+uf@7@7`NP}d_iaTthP&_ z#Ibtg4hbEPNk?OOB70_OOzd^rcrdBQ=*FF$pO-$nxAU&`h2p0&+$<%N1E*)vB zS)(9R^rYd?bT9uYKRpYVoyqT-8&M+jXVvm)KM!`w=cLF6@9?+Cc-H0i)aI31;}lbK z?XBKv=6Zo@oeL%|IALVT^~HOu%I5vG5A*NyRDP8Bv_0~upnKbz3g<;)OS8SQqP|S2 zu?!1+xBqj=B1R(&bLiX^rmfIwWhd+eWPjRBJCS@o8xZY z-}QyHZ$XC7ZKqc&fDyo1;1OBOz@VoL!i*J5?aP4C;p*w)7*Y}U_LgDxp#XscAA?T_ zO}NoyRU%lTXJJwP`L@UYM(6#GA8(fwzf-W-@#2keARCIiqZ&_LX zz50FXPT`-={m%x~FaBB5v*^Wn|E@(7?tVMH<=NWD;eKW!>rb+^SoHbtd|s)yu%gyR zV9%p)Hjbmc@#@Eqx3_)SC3~}GxlvW+wEmk;x7POQgs+tOW<7J?{+ZXd%wg#Nu`J~) z*PQqJ#1e3F= zf2PlceHaqiPgQ-H|9R`{nucTYe80kH`x`J%`TAnBPOaelF{r5}E)VQCV03 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a06285c67cf62e498813b9a494d5a41ea86ab70 GIT binary patch literal 647 zcmV;20(kw2P)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB6006&9L_t(oM`K_Z1*0J_8UmvsFd6~_90H7_ z+Ak!k@E@0+cds9iY#s|K4&W7#{?En5g;UFKp#0|#Pf2nF(TYKqv$C>+Eyw1FZ{NOw z<$nME%|MDHn1~GlkfG60abOETmZ4*iI7prp%RzP%9ReW5pin3(C}2=l5NCMx`Xz&# zy&l7^gO?b@M8z4d-G0e1b?OA#I{*|7xT1j6;3qi*V4;93+DHw4Vxxal-Dn7mhQMeD hjE2By2n_EK000Y@PE)UtxyAqh002ovPDHLkV1oKU9f$w` literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/Head/Hats/cj_toque.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..60426ff87fd29312e636f4662f9e04a2e77339e0 GIT binary patch literal 832 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 C3xgN{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/meta.json new file mode 100644 index 00000000000..a0670a97c96 --- /dev/null +++ b/Resources/Textures/DeltaV/Clothing/Neck/Cloaks/cjcloak.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Spritework by leonardo_dabepis (Discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-NECK", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/equipped-NECK.png b/Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/equipped-NECK.png new file mode 100644 index 0000000000000000000000000000000000000000..ce4e527400f155d092f564064b37b9a6fd13deb3 GIT binary patch literal 607 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU@XXVb`Ho)PG(@xm{>Y-zxQDW zk>mSwr*?&Ptx$M0VWC*NSXYyU7whhj_H9j})1S=R;xwtvyGtbe;L(K-6n6c{{$PJ0 zv>;S~#Z{oN-Nj(7Z5uBgTXTf>k>;b0h2asOZ62v9UX3{! zB)8m@QCf1zgccT7(Hy7tW{cFxY1eK}&-gJdP>p}_{#Gpu%Px(H=5AT7yH-sxy%hSZ zB;@Fw|K~4XOIx=0-9nWMzhCW|KiQ!`e#P~e@87SKzD{>|z`DaM`k&F+%y+ZDM0t11 zFh7)i@M+mnP4)v<^$fn{oQ%oyV2rBsWwz66IA~)~!~bP{_2#U1kNEakt5%>1OLf!@gfwqfP z%N&eTMB7>oG*y2LVZ>D1_nkZ77hUg2N2^cQ=$LQ+H)Gw z@#XZnbg!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000ie000ie0hKEb8vpVGweA)h=c>RI08mE6fXoW zx}XL@xy`#lo(6 zllNZ@cn~Bhm-~UX;V+U(&*%SQoZ8$Uk?D7`8^Q#={k`8tJTpKLtz{R;EeeKlY+Unv z&+keXUK@$H1*(GD*X}Fu>^Di#SCdG8_=N1}fB=i7n}AdY^mo(p*uS*pTHi5%;5`$w zvSR|#2uAR()k9>>81}4th`g#Tzn4C&#!{(gn0nLY+Js{Ry^RU;c_LmG9BF4G1h4s= z!S9cmYfTV1ULBW4mj~ZtJ8xj}d)^Vl69e`&k&WZdw@61WG`hDTPFhWT-s+HPJL zh&pMYuIgdt*UAE(G`Hg9^bZaW3c|oq{tV}cV$F;Scq&rD=HVt{$(OjeEJ^HK-)muD zt7r^4VK`m^>8A!rJtWZWO5^y-1iklF)iOtd!}p+Lh|%{;kHmOl`+> z{ZZJ1)mf@@tFL>E!q1}Yocs3+&f1=T#r8&cZWNok_sa8gV>K`XN)yxrr>*o}cJ8OS oTVs_lEB!wy9u^51xOWWv1&=&5X?=^%A^-pY07*qoM6N<$f?3eo#{d8T literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/meta.json new file mode 100644 index 00000000000..7f12698657f --- /dev/null +++ b/Resources/Textures/DeltaV/Clothing/Neck/Misc/prosecutorbadge.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "sprites by leonardo_dabepis (Discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-NECK", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/DeltaV/Clothing/Neck/mantles/cjmantle.rsi/equipped-NECK.png b/Resources/Textures/DeltaV/Clothing/Neck/mantles/cjmantle.rsi/equipped-NECK.png new file mode 100644 index 0000000000000000000000000000000000000000..9a881bf0dd0d24b2a35d5f4b346901bcaba2c084 GIT binary patch literal 1346 zcmV-I1-<%-P)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB600VkSL_t(|UhSH{Yg17a$8S@A;HaQ!X%}4_ zL_1_CZtg+?LjQq+75oQU3OX1lag2kYLjM7$1l+qxhYTtXF70Azql2SJZDYPSIggW< z_j=BIFE>y;7Xte3J@*V&ZF~ItJRC=U8~i?dr1=J ziAeKBVPk*%k_OEc)kuwpz>lM&UcKHNqmLjw$9yOVq!07ZiT~(%R(;jASzV}j)3w*n zUA0m*ZuIZ0`eKq0zjb`U3+!F| z>l&R8?s~aA0s-cKcDrt)^3d_MlYqeWIjpdTbvWMWWSpQXs4?JIQ zbluy{dH40xiK94eB5CWe544jYB*l<HW8v3Gm*`$YCiOZ36;6{LB5kCHxmSxz7E znQlN@a+AFBX&V0a^&w!MK8k!TjALl8KE(z-wY=9{io>6;Jq3ZP1iegS~FF*i5WKe0m-WqMSmd0ztMi2O7|m9$i&2LvjS zhwjzE$pSpg!#GBf{s0j`nt4ta%?gwhK!myt{M6BpK*rIJ@P1=q?7%fm66#j~yC)SO zQKR#Tu#OGQ)yuPnx57XZ#;G5H=f>-Xl8zbx1gQSTH$|O}Uqet2HPD1XT`0(h_anS& z4{C!L)XbsDLj{1$C)VFs!BQhwbPaM@+d6bl>er%143yV|1CTTqb zMU5uKQ`?KSA3@V5BLeX6{;b?|G>z&kX}nol6dN%#Im4T}MJB|F=G}7|{Rktup&p-9 zlh11)bliE%H#861-v}51BVYuKfDtePM!*OdfpG%=03&uuhB5S%XaE2J07*qoM6N<$ Ef*^o--~a#s literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Neck/mantles/cjmantle.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/Neck/mantles/cjmantle.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7fd93b7fd5b97f8fd15cad9174ba1618fa234c1c GIT binary patch literal 744 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 U)yR3|H~;_u07*qoM6N<$f@f8Te*gdg literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6ff72244d2c3e507ee9e791fb11826a1dc5a5f GIT binary patch literal 979 zcmV;^11$WBP)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB600Ik1L_t(oN9|R+N&`U@y?GduVAKS0jf$O$ zk(8Q3|3F9@KR^U)vGxP3EVLEHM#M%);UB0FEJZ`G6E%s*iVxz0#MLv)EUWHhW=SKs z7lxhLd+#~t-kF^x^33bNfA4_LZ3CwI#tc!;QKje_&s74*uj@6T=7C_8+=}q4cA&I1 zXmt4k1QI91d-xHjiitQS0sD(dV`;gY;esU97Gv|Z&2{#~8t-9}5@Cb``} zp3P=05q6(byhxDr3{3P6vuZ;Apj9Q-2RElwC=@7@$9HFbXL1(m4SrYq&D)a za>T)Sp6o101ppu%3Nsv3#zpWp+t={h<7MRV3)_>==M7EM=<>46aOUP0m=J7-$WZm` z`zvj4ZLpA`p(ItSRm$aZLY}4_h@a0g5RBcOO{+Q({T#eYh~qiPmzjA|98A|A>DaeI zRJ{1*ZMMJ2!(fJdJ{RyvKNFtU+0|$8szsu)Js6J<6=htdLnv!wD}GOa@DPgHIvj{F z7ytQS&M&88!@LLFm@5Hep%}Y}_-$t=8jr>a{?ixpCR8=$GmwtN8Kx7t{XLIU6`=gN z05ICoBmK|Up6^^?stR?C`??!i%J-7J4*ZD@d;-fKyUB0_YmNW_002ovPDHLkV1iZo B&shKf literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/OuterClothing/Coats/cjrobe.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..f7b9b21ebdba468b4db6d332a66132674c01058f GIT binary patch literal 1058 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 D_Phh$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..443dbf1af9775da318c591b41f8813205b7e22ee GIT binary patch literal 709 zcmV;$0y_PPP)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB6008|-L_t(oM`K_Z1*0J_8UmvsFu)^~bTJL9oek5P>L{P{CpE68#HHwVO0WbpOJX9i@45$iD~ zVim&Ffh-4EhHg1FM-gK-$qpdKP*T*8H%Dq r6RHb{38hgrqaiRF0;3@?yh8v0o7h!0tg)Lb00000NkvXXu0mjfp!7G| literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..cf49f4588a69013853e1b0e5505a5b2b01fec9d6 GIT binary patch literal 785 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV9d*Ob`Ho)PG(@xm{>aTthP&_ z#Ibtg4hbEPNk?OOB70_OOzd^rcrdBQ=*FF$pO-$nxAU&`h2p0&+$<%N1E*)vB zS)(9R^rYd?bT9uYKRpYVoyqT-8&M+jXVvm)KM!`w=cLF6@9?+Cc-H0i)aI31;}lbK z?XBKv=6Zo@oeL%|IALVT^~HOu%I5vG5A*NyRDP8Bv_0~upnKbz3g<;)OS8SQqP|S2 zu?!1+xBqj=B1R(&bLiX^rmfIwWhd+eWPjRBJCS@o8xZY z-}QyHZ$XC7ZKqc&fDyo1;1OBOz@VoL!i*J5?aP4C;pyq(7*Y}U_SQzOLk0p34>g(= zbxiJF(EUK|2b1hB>)#yj>^iICkEs_178D8z-q8}z)LgnW*CJZ0e%S@J>5sGf_&N}eermlwNsiF@Ta>8d9 z-1uL&@$Ri|Z^wDNQ>2f2AM^SaoAhrFOG@M6e_7Wj23_!oc;qQ__L7(LiZ>0{e`h|H zYu>rjKCe*I<^1Zpje9CWA5W3IuWh^{&agUbv|-wAAyQsCbAYGO?`$MDvg uQ?H`;{KWkZU(`LmN&ELeJ)O~hfZbtoblQ97(!0QrX7F_Nb6Mw<&;$T8JyaaTthP&_ z#Ibtg4hbEPNk?OOB70_OOzd^rcrdBQ=*FF$pO-$nxAU&`h2p0&+$<%N1E*)vB zS)(9R^rYd?bT9uYKRpYVoyqT-8&M+jXVvm)KM!`w=cLF6@9?+Cc-H0i)aI31;}lbK z?XBKv=6Zo@oeL%|IALVT^~HOu%I5vG5A*NyRDP8Bv_0~upnKbz3g<;)OS8SQqP|S2 zu?!1+xBqj=B1R(&bLiX^rmfIwWhd+eWPjRBJCS@o8xZY z-}QyHZ$XC7ZKqc&fDyo1;1OBOz@VoL!i*J5?aP4C;qB?-7*Y}U_SRmmLk1#k4>g(= ziKvSoRN}~MGJkO4?#nJBTwBC7@zDh5Uz4LM<~o_G$Isgm+js1P zBLgFgfCCzFKy$*8?k&D9QTNuJPg`;$L*S=R=AZ3RarzA>D{lR0TgCT)<%Zt%`?qVi z-&*qh_*tIc6Hmskw+gsfHRUPP_f&F-uM&RnwJxpr`|+6* zFK_Q}*cnQ{XI6Nds0;vvhH zf7Lrwj)n!zUK|y<_W!!G`M;|58|w4A#aq8HO>q5`n=YCC_xqxQPG>)}O-R`GKhJvO z!b8_K_K7=0|JM)DoU`Za+u8Q^>q-Q>6d_hPa5VCZ?TIUx`}AKsFsvCoUHx3vIVCg! E05ED~Z~y=R literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/meta.json new file mode 100644 index 00000000000..11ac46694ce --- /dev/null +++ b/Resources/Textures/DeltaV/Clothing/OuterClothing/Vests/clerkvest.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "sprites by leonardo_dabepis (Discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-OUTERCLOTHING", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/equipped-INNERCLOTHING.png new file mode 100644 index 0000000000000000000000000000000000000000..24c2af227bb3225ef1a887fbcb027fa911c53dd0 GIT binary patch literal 1719 zcmV;o21xmdP)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB600i$zL_t(|UhP{=PZU8AtrbWVVo1=4341^< za`8+^^e@PTUtr|K)fi(uni!QU2gQRwfP)Z!fJPJKz(KvB2jH+IViZHraZ^9$J zo!ObLo}FEcU1T#mGu{2FUe(mhP8A|S0t118z(8OiFc26B4E(1IRQ^S~XJ==l{{DWc zR;yC0)nt8rT}DSoy=+lUs#dQ?AZ%*tK^-6znwYqsa9OK;Qmv_R0P(ZtXz`tu1$bvy zmvqIS-JKnonVE(MDzOKmv9WPE)7>rm`}=Ybf3!-tkU)Hlg$}@?nEP7%Q?B4Jkizc+ z0|QA!*ymh4<$}vGSdSPmmL#NYF;0V@OMnRub}3t1Te7ycCfHJVUaLeF8IADM=J?>} z55PKKPjt@aEx`tSm3e1Ltr0S7}Bguz$BFTyervcGY4q# zou31ea5;JmHlO@(9Qz;z=gSnXZ{LZy?}M+p1V{pnG!r4SewhSt?X(==V?5SVMF16m zx5+xT*l&jvNq*GVivW{|b{O7FObr2*JjRdCJ116+AxNw)_}T>QOhCM_Jbm^kdD=_6 z25}tcF|I6e!PjCt6TpQ(et0b}XI~r>0mHG678*JhZ)G9emJtE%#xKLBux4N& zFc26B3<8(+ZzCE6#-_GgsnK<4ZeFjm#kSpGHdFy3Rj`?S)v1HjmHE z%?Wcu9TK1YX@;lP{m&Coe!xia;0W1l_cv@)qlJtO8+sQX;^tOqCh|VAy;u zj_+ml1!Z~DF3acD3>vMaPJ(GQIA3sWxN^L0ys48`7Zm}l&)bTlMh`*1z?GZ6X1UE{ zPXb1xKcJ|nbATNI=6=zxFc)LkC&aO7RVqymP(^^PpqT($od?W^9&Om0c6brsTZ?z` zu+JFk<3oh{IUp_cTHPpR-+6otrybq|aDjF;M*zPW*jfVel4jm{p9r_- N002ovPDHLkV1fg`A9(-( literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/cj.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..77371a3ba8c82b2b47d2bfbd3159a13792c60827 GIT binary patch literal 995 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 KMNUMnLSTZ`0gvGT literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..5dcb8e026ee553ee2026f27b8edb10f6232c786e GIT binary patch literal 967 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV9d*Ob`Ho)PG(@xm{>aTthP&_ z#Ibtg4hbEPNk?OOB70_OOzd^rcrdBQ=*FF$pO-$nxAU&`h2p0&+$<%N1E*)vB zS)(9R^rYd?bT9uYKRpYVoyqT-8&M+jXVvm)KM!`w=cLF6@9?+Cc-H0i)aI31;}lbK z?XBKv=6Zo@oeL%|IALVT^~HOu%I5vG5A*NyRDP8Bv_0~upnKbz3g<;)OS8SQqP|S2 zu?!1+xBqj=B1R(&bLiX^rmfIwWhd+eWPjRBJCS@o8xZY z-}QyHZ$XC7ZKqc&fDyo1;1OBOz@VoL!i*J5?aP4C@!!+MF{C2y?X3M?EQSKd7RxM> zyD_gKBUMqU?AC7{GqHUQy{)|orEAynKhloT%ur9-I<=^&wYTD*_MgwJ&v~kMPv5Dc zty8!1P}(Qe&$nlq7#}N`z`%(W{n2L<*1ThD`L4!k`Q5ykZ}0BaIQ#Qjm!;K>ja9$f z=W6Ko=1-Pd9B5Whmt1_;>i+Ay{4=>^-dYyKec4i-^kxx5$LAdf4w*AJoZz=u+&bZU zccIU2bBTuPo4e=R^K-1*Y;@g0JoYY<@J@nmIOTzaopF5LOqM*f^Y7Z>J+7uQ~G;=Q_a<^6`L zn*SS~m#*Ku@w~=m?u(z6Iv!465P5#yva>#$Gv%Z@hIdobH1BIDdTS%&RBanBYklhLovW_7sitgx3WisRr`Yu}2{L}rdleae~* z|Cr15UeDT8^Ok`j>(soKC?%QW literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/inhand-right.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/clerk.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7d37745187ab3867fdeb0e22655dceb99718e9 GIT binary patch literal 952 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 D52}=N literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..d04680f3ca65d0edec4b2d879fbca4607012024c GIT binary patch literal 983 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU@XXVb`Ho)PG(@xm{>Y-zxQDW zk>mSwr*?&Ptx$M0VWC*NSXYyU7whhj_H9j})1S=R;xwtvyGtbe;L(K-6n6c{{$PJ0 zv>;S~#Z{oN-Nj(7Z5uBgTXTf>k>;b0h2asOZ62v9UX3{! zB)8m@QCf1zgccT7(Hy7tW{cFxY1eK}&-gJdP>p}_{#Gpu%Px(H=5AT7yH-sxy%hSZ zB;@Fw|K~4XOIx=0-9nWMzhCW|KiQ!`e#P~e@87SKzD{>|z`DaM`k&F+%y+ZDM0t11 zFh7)i@M+mnP4)v<^$fn{oQ%oyV2rBsWwz66IA~)~!~bP{_2#U1kN*?YcQW5ud=0>l>0U~Yv zN-r)2X>ny8b^IWECsw3}<>0}iZ(M7b*bf>`ZoVZhz~y)CYI=rw=0@kO)0Ql9H7L^B zZjyQV&XM5PQ|-Myiq8F?|NHLk>V@qb;v5YOIFLgS)9&KzID_pmdew*T^?!O$agO`g zk*gOak8kmt;Kw7reWD+Ki{A6Fj{C30)|Xi5R~)@~aplb9BMchOx3^UrKi{`)@1dtt z^K|!FoO}EyaaSjc^Q2`eN3N{NeKu{yt%A(w-xjG?Z{F&^np<<%`l~A+S%lQob9|k0 zsndAbOpAkw8*it(Z>gxe`#VN!Dw~t!xnBnrMRm2W1bL~So8c11ApPmm`#B=JHqWhJ zH~IAzjj87@y!`Wh)ePHv%BMFe{asR0qS*14(Pqc)W69UeXP^D??oV9$hdC-sKfh*} zqIkaSzi7=hT^}#?Q~o)u8jGWrzx~W(=Ps(UR`{tpUjy&#vtif6?=J4*_^r3p_*DE8 zkr(C<7N7h3W6ARATKN@mPjw}eHRmq*Fp-@}fdL2lu${xBbkXF$$(D&?L31G1Diup5L*l%Vq2+hq{ y%=p3UMY-zxQDW zk>mSwr*?&Ptx$M0VWC*NSXYyU7whhj_H9j})1S=R;xwtvyGtbe;L(K-6n6c{{$PJ0 zv>;S~#Z{oN-Nj(7Z5uBgTXTf>k>;b0h2asOZ62v9UX3{! zB)8m@QCf1zgccT7(Hy7tW{cFxY1eK}&-gJdP>p}_{#Gpu%Px(H=5AT7yH-sxy%hSZ zB;@Fw|K~4XOIx=0-9nWMzhCW|KiQ!`e#P~e@87SKzD{>|z`DaM`k&F+%y+ZDM0t11 zFh7)i@M+mnP4)v<^$fn{oQ%oyV2rBsWwz66IA~)~!~bP{_2#U1kNymC>d*GaVx586#CacAgYdV1UXll||Em+#guIc*hb|Jy^#_|u{V zJAz}Dy4_y>_xS9OpANqh%+=AqRJ_^sYh1t9ef`GwxBg@{H3kFZEi_&hwxAY?HoA zU;b}qiTgVSv+q~xWUuOqd}>rbzdK`|tKVwtZ$eML$~UrpEY)yod=@+o1z$5fs|_#Gy+| z)^Foo_3gS9V~on`l^eMlzR4Qo{#qrJP#r7XAdod{-z~Ehx9&?cWP-)+N-%JndB*2T uhrC_?Rcu1HLT#wxQ7euHhiM#t7&rWup3(B$#{`&O7(8A5T-G@yGywn;ZoQHK literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/meta.json new file mode 100644 index 00000000000..322f9da00e0 --- /dev/null +++ b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpskirt/prosecutorred.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Heavily modified by leonardo_dabepis (Discord), original sprite taken from tgstation at commit https://github.com/tgstation/tgstation/commit/3a72dd925f7d6aeec620fe83bc4f88a3d7e5f693", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-INNERCLOTHING", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/equipped-INNERCLOTHING.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e475bdbe1be1521d64a5a124b31a3c54ea5727 GIT binary patch literal 1559 zcmV+y2I%>TP)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB600d7-L_t(|UhP^7g~QpHx2#)QP53R-9#65lYkMe6w_9k)^SeogxAL; zGxyC$Tl!uI=_K#HbMCo!?o8)i5kI^FUIDLwSHLUa74Qn2Q3Xn;(eCy2^`KIzNVQs( zR;wkQPDkeF=bda(Evi?VX5L#M#+}EJ#%c_^|?*;82&N+wDrb-4=Xu@OLeVQDO|kk6Pn`A1eTX z7~VYI+1Zh1vnlvA1u#QXr5W%Fx8mR~*^B(`B5=J!Z|n2&W> zpJo(+9~%MiC_E2OnjV2+W&}V0dK~l2b*>`V``GyAzOMKaqsT>tFB1*3G1lAXXPU4# z`4oXaQh;INm{)_Sp0lWWz8AXz>%@ z2N00Pn*<;RzAs`R-0dq-n$u7f0sV94|E(wt1{n&%te>|C!~r(m)F@q=B-8>#)#=}?zHlbsA{ZTTZ}GvAUIA@y0I*d8m`xHk zaXhB_@V?$}ns6~H$r^Y*9Kp?7clw4$anOpOej;Q7qYl95bNC)%iH?yZ#yHLifI$wx z1_zEPQQ~makHxtmOVK7ky{|dYO>tIz3cP*TmM@<_$*b4TwcK-?4=&&YZrY*p z79s!utis^)q(p#O8Ok*RAb|N?KB`uy^@7WMyB_FTp;9M7*5XXkuHY_)V~uUR$w|va zB>?O5HgVMGG0-n??XIg?$=0za0khE`kannZfE@umPTLWtF@(KB_UXvu+;RXmHbcxz zfEoj`nu{ABJNz}qgNOPuND)lnBE1jN;9!=>(sZP$1<1;KCuJXJ0kqjRPlMBNaTXv? zgNoc+bs4mYrBOZ$BhxfT5#Lz=8h@N3MD+?}A*|oSD{zJs_y^3V&=AQ*#y0=}002ov JPDHLkV1nJ{-6a43 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..03f703a26ccf83f715569b0cfc22840f2dfb1b9b GIT binary patch literal 902 zcmV;119|+3P)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB600F*9L_t(oN9|NGPQySDT!&bKNGJsekn9K0 z@BsdiFYp5@K0rZ!z!%c^38|>4Xk0;KOMpNq!cI^O95Y@==TZOz10m2{WaNcE322c?yMn@NPsL9O{Mv2(*9^#_LiLqATEQ z;3WJs&AAkShykqu(w#BT)dDz!ujg3DzSKkjq``gs{~Um*51=BnTiYN;vpM-x-uv_n c{2K;-0LZK71P8U)CjbBd07*qoM6N<$f=F?czyJUM literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..9b19bead358e0fc8be9ce1a23807753f7df8b751 GIT binary patch literal 955 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 KTJ?4N@c#m0(W=A% literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bf6ed67bc86a2668c33a6b1a00998ceb9793daa0 GIT binary patch literal 537 zcmV+!0_OdRP)MLMTa)5ZdG*2|^K(2#Q2RT8ZKyyzckxT@JzBX_o}|U4Hj_@7?eF zd4G+mR0;+uBMewNfDWJo{7-=M*fp7RI;1?8$%2=688io27z&emsR3Ld1Q8(ys{vk$ z)8!yBk8_az*i;3g7-0VGhzOA!%xuKr;juzZmw6AI#S%0JdkF5sKH%LAax=W67(x*M zXC5K#*;DYizT42$WHQk>Ww(HB(h9cy9JFzKu}m8Enj#2U05r$qg<_eSEiF2!8LC>X zO6I7GWJbyhMNkAG3qY6mE8<~eLXekBH`FGq)EL#>kK-+)Cb{zR0Adk?Sd3tCJo()- zw))bL&v#&Og}Nc|KTse=X8?;?co$Tjn?!D`+Uuz58nW5373db*A_Ub8fC-lyA=Xy5 zq`X)4{1h|Oe#}(^B;zMgyGy{8_affJuU9N8Va~Z)weqz+Q&{`rO(x@8ycUWrCQ7H75!7O6jL{bZwyMtq;Be zRnVCaBhgEJT+^>{Y#mc5_pKbKyX!tj`qaLXh=a?fbt>tBYuy#lhwQ%6mFWQoeIZzG z^EpI_L}2C0)#ZNCyX%Hto|QG1u97<2Je;nuG?u0sQ_{Z9y&KLi^5yfDqMu{<>9fDA zyfpscea_DJv&YKUz{cd|fzyHwuEVqKcl}d8eH+whyj|2&pj8wZ!)M^dEk0<(gBese8!@$(E`4;#H$Ddp3=Ezv4xa z|7S@j!l|~W&vxk<)$H32S=Tgb85=5Pj~_Vz(Yy#xN!h<&JfY8Ae`%1YB-R$=l{Aui ztXi38*EU7Wn^w^gnLTHoH%>*?xNvoy6@LeEcEr|7adMt(B@oE^2;oOG?S!$I$;xP6 zOkek~%=H%q_1vmjd{0j(2pmD9iO!>m=B?$U$+k28vDRiU@0FQF^7m#I+)s9W__(C! zlXJnncw5@z$8UN+-Z}0ETkdf6s9Hu?GvNzE!|i=T5uD*SWDR2!@fA@9E6u2dLq)Bs zYvM{dW$B@oR(9@R&?SQ*9Yz|T3$uIOm$mo`eBK)zOk+&a9;D6bOlyCUN`s}3Np%KG z-y50aLFc_$l|>D|XYoJZRll_hRDa>AK$|w=NwTqmJR{;=7su%sj$_p4RDZo)oUfOZ zM@RhU8)o)192#2U=5_n(PF-hm_d9@>>sqE)hn6Hd-@rQ}L$6csj139BJUsJRRcF6V z{?x|-qxGeg@7S0rgLL~9KDK!IR70b~jFVc;{Hv;Ou@dY-x3;7%>^IVSTI(p?e0|`6 z@8!V)gBM*D^BCEuQ%)^Cl!QX|Rl}Y`UgbUw6#=)qBV=1M4M(R2uJOGb9eAwBv(h3f z6JHcYgQU2$YfAn_?D85IBtT=UPfV~5a<2-UJzf_vjX zb}BcUzp~FxoAfo7KE;UCJd8znf}983y=CtBUUsE7yGWOO%meEMJihrry~ND&-ioc=WTmT^H189 z%dN zUWhGMba7s7N3J`lD<9bFcqy2ftZb?1y1P3u7^9AQMeLd`>YOnEe<y(|O2p6q(F5c|czWX>yMDCKUa|>APV4Q?6kE{0y&K+u2x6Ah&*WhY@ za7~<_$TvT+Ufz&Ru;7)NJLu{o ze3W9XfhfEz(SCdtJRpCgo7#RO;f+|Y7Lz8YC6iEMMSXH9av_tH6$^>B@yQiz@G{%J zSHsg)dYkkGe)t<>F-hUvzz2t|(a}aQaA}e|76oq6_f_}qzD!SiaS#%zDM~iSExaf>d#WdJal722 zp~cOiXx)X^QCYXx*>^I7v~7qV7p>6+OM| zP=xehMe{d1UF*&-6iccJeJrkbxeKS2#6R5aV=5V^V7xu-wH05h*ep(h!xhczbAWpv z1xZIv960poh{v;uJjEyEUN|S$@8vNI_J~r8)r<$VpA#t@I@U#oV#8qPCoZq{7C#L> zT;;wv^-#}Z#NghS;rRINhFq#I`vXKi$1Q5psb}E>cN%i9+66y*Ya(fvGCUgdTd#!N zp!uE>tM{)4I*%(+)f`u;7oV{~=9TelTq0g``yM&eeo6l@Fr?UY)ZZ={rjhZRT&g%J zn8t%L^Ea@#GKe_X)>Fo`*XfJqlM^LkIyr?3ocork7q0OsTv;gKoREenif}GCT7E5Pa@5eJ4&UOEx4~kP zh0#qD6xws9nDU_)oq-U`$-JlhZ>8kIY_5-291G<%Eh6PuMuzAQhIwU+QUlc>#TDC& z@Xtc%QHstJ6|r^?O`}XC#6E4y_#n?~B2pZ*JEJ`@lV@M8Srcu?*S7m)CA`_lm7+d$$`Dch%b_V-VebSrQ#xm)Y@*_OeZi9S+K$@jYBjjThs5A`wN<{m zGBsQQThpFf?Cvh?Gu63ZC3djs`W{Wz)p6Oxg{#N)2ouG4C8hWjcdJu@JLSmCjJ3Ff zPEwQK*;l`g9SeG&G$|i;P=p&^GkB|O9o*F4xL2dm;BjZE7?kFS8*#SA2X9}*D@Zs9 zQug!@x1sDCPp1yr&&?U%3-8hqfIw0hS3V*W_>iQbpK+bbpd zuhGw?Jgjsr4bp7;-GRMmt6Ki*dkKC_uM0A`_94h;L8+$iOX2Fc&$r2s>x;GDKZIwE z3F2Gs6^g`>zxB_3RJdb=nm#u~GQXS*9E*?#ZN4{A<@F7aX1`WxJxEnf)3y^gI?D8_ z3f0l5Sjj8S4@xZ|*Nr2`Vr+tEoyG$74%zIi_8wIi&;Ps)w|27l+EniIc$ef*m+y>7 z60!y9U=Y@%LeRt8b*6ejq8;!D7xN6tH0QB5D@25DAmFx>O*KjbE~O?!E~epDd%*8FV>nL5wTq$K{B26VietUX9K0(9(o-MiRq&2px2(uXd0h}T|2)dK zODDI_O>?lQ;Nz2b-XhGcvG~D4%dW(5$v`PXSO?N2urnPdgY2QS+UM&qBNdh2W!v)% zurj&n$ung|{Fr+<+;cg1+cUN8(;fL}tQ4_sac`Z~h_%CMYbU3C_u%W|w!)Sw;Y+fn zN?VM&Pmz~-IHS+p3{lUR))$Q@FnvBD^ahhn%=xPGa@!tUm%UV-SOR;<8>TLqpI4~Q zb^i-u?%rz6IaUn@9$b32Yw`T_xw03oKG$zl<-Jye89AW)zM(H>^CGzrWLHW54^eoY z_N=&>%qCn!oIW`FRby_GO;_}jv*Gu8Vxr!(?xtPhH(cvb+n$_tQye^FT=_v^{;c49 zFjcY5QNjOK*RAU6#baRKBE9J95%a+V{2}$Ydtf0^MeFf`_WO2u;R7!|#0ZLuGa_;z zzrU^WS-eta6>ex*(61C_-c03u*TKr!8iaQM=Nz2B*3h2UEm~E4$3rtZ{PmX|C*M~u zfqJYg&zHLwRPk3UW~MrqW;i>m*nIiUlfr9*PvTg}&=%B^CP!9>o{+q%Su|Ka{<=r) zuCm1RwU0ZalU}+9>_;fc^lS- z7tQoQpeR< zfwz%1cqXS8kv;U@#B-0`SM-Y1N5wKlu3$)5S^1i44F4edvhYLLnSm>xt3Hp+NDLWI zG(XaKe}RD2Og*WuRBoxT5~{oc58HXNskua0h3E9w{e!zL485cTs@C&e_gDFMQ7`1D z_=TSClfEru%--mqns{xxm-$`8*f!<%e8m<1qvMgEf}*z8YNcCw_ooST=caDG=rq*i zwrYra@DA3IjfXNgLrO13e!72uiX%beY1>UXX1Ve<=ikx1en)n!GLC+iXe%0P$tt*3 zbR7Id&zQv{F20pyA!Yx4oAQz~n3@r22ehp|G@xy@#-GHJJlvHDWDg=m+0We*Xlp?r z%_DxE1d=O-1twCQXml;e=O;A~FpaDQIfcf<@t(RAXPSNhgJK?FWI+mWC1J>rBZs*) z{jdOlJB396`?^Fcxm zbAvS*WGdDSckCwwFw%lJvsj*37|hq#SJ_uZ*@NK(Ltro%7#s;hBB6i=l<7}r5&WQZ zrpyM!4-6cINn+4ESu_ticmtC_^zdeBK_I|9_z(ZwJ@NQI;pxnuEC77K{0N>fgfblF z?hgCag2~eJ0YH8_^dBvl7C`q8Govs)ycr~lo)3l2lKB;aO#0K_)0^S884j5QqqtGr z0aYfjD&lWT9yh?7{Asa4ffLQ$bJGeS`)`^o8uc%-{^r}p%w{;hIs%ygiTgM0KVsih z2DI>aEY5@Ez2Tk#P7AWJK9=l3qLHziuS60-okFD`p#&nF2t}dM7$}BBLO~HkB0?3Z zhCxzP3BN!Y(3va(okZDy0>G7N01lamCXrE8btpkig#<-WRFP1kikb>kl|oWOkO)W; zQVsbFgfW8#R3*XfSFbjp$N&_Ij6tcA;3`lmg@k~j)Tm@AK?SV>MPe`rIF*W^!c~5F zLndL5c`)1wKssse1Sbm2lkT*+#s=Y7Z4(162vQmTm&C-4z@h>Mz#gE{$sWGUzosl` z?i6ztVS`VE8Ul%ct0C1@Q7AQ4^&ehuB3e-xOrRDwP!Vutl^-)3iNONl0MrsTDir|u zBTlR?gF;|=Ff2Sg+_WGY5a12VKd14)h9VPK1RQ}y0YKqM6c!HLNDCwayK$qS8^d4p zJ;*ew|No`Ev3#1Ckk+W{4Cf%?kPz*#W21$e?Ra6N- zGx#Su(}T+LB`_%3P5_SpS3rSoas`(EnJR_9d*ka&*~kMx8Nd_IXh=$2yo zK0vb5Q~xv*1mfY}c(!!(2Ym&EJ6HyIy&WGpIkpIiiH#Vm1C8@@1Dv*nU(fWr8pEvw z@$Iw6y^yOMIxVC1XwDr6OT)N2u`Ey% zwWnQ?%a$E}4#D#Z9us!Oao>UY=ZD<14&t)GmCek!+;QAvL7`}>ZQnqDGyrj)KD zJOPqq)RJp5`f+b+YxmFtrN*IVuPgC;c1ZLxUx3qS}wI4n; qFFABhdh4sl?6}IEg@H!0EeDP4?_v>|7h{1OgADYHaCth8!T$qmnggW( literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/inhand-right.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cj_white.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..deb205205ab91d09acd1729baa444204c3560f69 GIT binary patch literal 7879 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
xVuL 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 kbrf4712OWQUrly!^`%irUedqm2=0U1cD(f|Me literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..4e73693046fa1d1ad954add9430787349fb847e1 GIT binary patch literal 7183 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/inhand-right.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/cjformal.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..567d302dc529f82b62c390a392703de835c62b06 GIT binary patch literal 7415 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/inhand-left.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..5dcb8e026ee553ee2026f27b8edb10f6232c786e GIT binary patch literal 967 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV9d*Ob`Ho)PG(@xm{>aTthP&_ z#Ibtg4hbEPNk?OOB70_OOzd^rcrdBQ=*FF$pO-$nxAU&`h2p0&+$<%N1E*)vB zS)(9R^rYd?bT9uYKRpYVoyqT-8&M+jXVvm)KM!`w=cLF6@9?+Cc-H0i)aI31;}lbK z?XBKv=6Zo@oeL%|IALVT^~HOu%I5vG5A*NyRDP8Bv_0~upnKbz3g<;)OS8SQqP|S2 zu?!1+xBqj=B1R(&bLiX^rmfIwWhd+eWPjRBJCS@o8xZY z-}QyHZ$XC7ZKqc&fDyo1;1OBOz@VoL!i*J5?aP4C@!!+MF{C2y?X3M?EQSKd7RxM> zyD_gKBUMqU?AC7{GqHUQy{)|orEAynKhloT%ur9-I<=^&wYTD*_MgwJ&v~kMPv5Dc zty8!1P}(Qe&$nlq7#}N`z`%(W{n2L<*1ThD`L4!k`Q5ykZ}0BaIQ#Qjm!;K>ja9$f z=W6Ko=1-Pd9B5Whmt1_;>i+Ay{4=>^-dYyKec4i-^kxx5$LAdf4w*AJoZz=u+&bZU zccIU2bBTuPo4e=R^K-1*Y;@g0JoYY<@J@nmIOTzaopF5LOqM*f^Y7Z>J+7uQ~G;=Q_a<^6`L zn*SS~m#*Ku@w~=m?u(z6Iv!465P5#yva>#$Gv%Z@hIdobH1BIDdTS%&RBanBYklhLovW_7sitgx3WisRr`Yu}2{L}rdleae~* z|Cr15UeDT8^Ok`j>(soKC?%QW literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/inhand-right.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/clerk.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7d37745187ab3867fdeb0e22655dceb99718e9 GIT binary patch literal 952 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV9d*Ob`Ho)PG(@xm{>aTthP&_ z#Ibtg4hbEPNk?OOB70_OOzd^rcrdBQ=*FF$pO-$nxAU&`h2p0&+$<%N1E*)vB zS)(9R^rYd?bT9uYKRpYVoyqT-8&M+jXVvm)KM!`w=cLF6@9?+Cc-H0i)aI31;}lbK z?XBKv=6Zo@oeL%|IALVT^~HOu%I5vG5A*NyRDP8Bv_0~upnKbz3g<;)OS8SQqP|S2 zu?!1+xBqj=B1R(&bLiX^rmfIwWhd+eWPjRBJCS@o8xZY z-}QyHZ$XC7ZKqc&fDyo1;1OBOz@VoL!i*J5?aP4C@xjx@F{C2y?X3M?EQSKd7RxM> zyAd&`A|q8%sqEHoF}v2*-h|S%YkTz*Rtm z?-y>J?J<*f{;ZpPM%37=Z~_A-R`f@oDcP>5zn|~3&Tj2(Iq$#i`S$CN--)g4zxVDr zdH>@s`N_S%Y>t%gmfgB<W;nci+m2YW)8VTaUV#RuXkV9 zP-nx|KRIjF-LUU#Uw(Q${kr;B8<{q*O9$Vk{9H4A|1}LgopsYZUH9zWxo^um?saD_ zCS?7yI`zm%NP!U_`Vq)fJoo9TNfuri6$bMkt$53CaP-aFoX}}!0u_%n|Fq{`urA&~ zTqb$t9aV*E!V9|H=ic4^@7<##`RfW-ee~SVaO%+|%cftu|Mdlxtoh62+c1~mfWxZ4 zOxrF$!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000ie000ie0hKEb8vpWK77DBZU0I!mqb7)@k<(&JxW0_&CFC->AT@$C9aNjJSsg1!g)B2f*QZM zfTUicyu=7U8=UwwU)lrYqqI^?gkKW`T$cgR=;$bY{`g5fMvdQW0L#K?Kixsv-Shx! z%VF)it}iIQF9A@BQN`3An);?NzV{8#^z^iH95sHUpdE6MkFq%Ny>y%4mt6up_25)y zX{iYJ(Zc~+URtDBeFI(AT9jONgS4 zifVoiIVV|RXM>LKwgEyvKbPW{CE#G+4LbMX72SF>DDnaF=!gDc%EgyYm7eoYZj01F z9{teYuZWJTOMBb$r{f95_WPCwnw^=Uw)S>9HMdAOhQ{V|TQkKE*rXl!9rg9DdkimA zo~c3g2U-Gd$`%$D)nl%M0!Asv>pqN5BLc7{u>n3ikWzKjYu?WxIF1iy9Dn!gnC|j(2XH5Ni^bWU|1=Uc=-A zJAJrQDZzJj5(x1{1hBabHa3+b7=>3;=bNC+HJLQyW9fCQZ;)bIjP?L9&1W-eud~_I zsB-<7XdNH&rUPI^KqVZjmQG7RwU{@>^*Z}a-w8yUAl6-Gs`yV49PxT?>ZDgcg+rzI z&Z97DT&vGAU>UFsSOzQumI2FvWxz6E8L$lecMOOwMcMoQ{(f~inM$ST_{kF#+gE3# zCoG%D4?u7h@kx}Po*uCs;tqP$6?bvRhVLs9UJMNz8DK&J2Hh2EnjO z7j~X=5-);kN z@zW=I6NEC(6VjuxrujL3#(A~7@Og+jtYy9g*(5QIX(Go2!-`QTb!_SO%)Vz(013TN3ImS-=1Q N002ovPDHLkV1lje?7jd1 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/icon.png b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0d2266c7ff736f194c2cde2bab940aa2e7391054 GIT binary patch literal 868 zcmV-q1DpJbP)!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000ie000ie0hKEb8vp8t*Wl%MceETLAbp92>;#T}qWK@MLqDGz9$+`i;apaB{<U1UjTT!HJihfD$zwjoWV+w?C;E+6gGaPG=~)vXcUhJCBtB z)tVacVr^4eRr@$eu$zU*RU;lG9r@Q&pz*tE2igr7s|Sv^He_)1PasQc+K&S*1(XV; ufSP$4OKLz;Kz9P-By8>&1&jiJuD~~;2cX7Z7GrY&0000Y-zxQDW zk>mSwr*?&Ptx$M0VWC*NSXYyU7whhj_H9j})1S=R;xwtvyGtbe;L(K-6n6c{{$PJ0 zv>;S~#Z{oN-Nj(7Z5uBgTXTf>k>;b0h2asOZ62v9UX3{! zB)8m@QCf1zgccT7(Hy7tW{cFxY1eK}&-gJdP>p}_{#Gpu%Px(H=5AT7yH-sxy%hSZ zB;@Fw|K~4XOIx=0-9nWMzhCW|KiQ!`e#P~e@87SKzD{>|z`DaM`k&F+%y+ZDM0t11 zFh7)i@M+mnP4)v<^$fn{oQ%oyV2rBsWwz66IA~)~!~bP{_2#U1kN*?YcQW5ud=0>l>0U~Yv zN-r)2X>ny8b^IWECsw3}<>0}iZ(M7b*bf>`ZoVZhz~y)CYI=rw=0@kO)0Ql9H7L^B zZjyQV&XM5PQ|-Myiq8F?|NHLk>V@qb;v5YOIFLgS)9&KzID_pmdew*T^?!O$agO`g zk*gOak8kmt;Kw7reWD+Ki{A6Fj{C30)|Xi5R~)@~aplb9BMchOx3^UrKi{`)@1dtt z^K|!FoO}EyaaSjc^Q2`eN3N{NeKu{yt%A(w-xjG?Z{F&^np<<%`l~A+S%lQob9|k0 zsndAbOpAkw8*it(Z>gxe`#VN!Dw~t!xnBnrMRm2W1bL~So8c11ApPmm`#B=JHqWhJ zH~IAzjj87@y!`Wh)ePHv%BMFe{asR0qS*14(Pqc)W69UeXP^D??oV9$hdC-sKfh*} zqIkaSzi7=hT^}#?Q~o)u8jGWrzx~W(=Ps(UR`{tpUjy&#vtif6?=J4*_^r3p_*DE8 zkr(C<7N7h3W6ARATKN@mPjw}eHRmq*Fp-@}fdL2lu${xBbkXF$$(D&?L31G1Diup5L*l%Vq2+hq{ y%=p3UMY-zxQDW zk>mSwr*?&Ptx$M0VWC*NSXYyU7whhj_H9j})1S=R;xwtvyGtbe;L(K-6n6c{{$PJ0 zv>;S~#Z{oN-Nj(7Z5uBgTXTf>k>;b0h2asOZ62v9UX3{! zB)8m@QCf1zgccT7(Hy7tW{cFxY1eK}&-gJdP>p}_{#Gpu%Px(H=5AT7yH-sxy%hSZ zB;@Fw|K~4XOIx=0-9nWMzhCW|KiQ!`e#P~e@87SKzD{>|z`DaM`k&F+%y+ZDM0t11 zFh7)i@M+mnP4)v<^$fn{oQ%oyV2rBsWwz66IA~)~!~bP{_2#U1kNymC>d*GaVx586#CacAgYdV1UXll||Em+#guIc*hb|Jy^#_|u{V zJAz}Dy4_y>_xS9OpANqh%+=AqRJ_^sYh1t9ef`GwxBg@{H3kFZEi_&hwxAY?HoA zU;b}qiTgVSv+q~xWUuOqd}>rbzdK`|tKVwtZ$eML$~UrpEY)yod=@+o1z$5fs|_#Gy+| z)^Foo_3gS9V~on`l^eMlzR4Qo{#qrJP#r7XAdod{-z~Ehx9&?cWP-)+N-%JndB*2T uhrC_?Rcu1HLT#wxQ7euHhiM#t7&rWup3(B$#{`&O7(8A5T-G@yGywn;ZoQHK literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/meta.json new file mode 100644 index 00000000000..322f9da00e0 --- /dev/null +++ b/Resources/Textures/DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Heavily modified by leonardo_dabepis (Discord), original sprite taken from tgstation at commit https://github.com/tgstation/tgstation/commit/3a72dd925f7d6aeec620fe83bc4f88a3d7e5f693", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-INNERCLOTHING", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/ChiefJustice.png b/Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/ChiefJustice.png new file mode 100644 index 0000000000000000000000000000000000000000..6cba0e4a93f5f568d4ea91b8ef1b0845aea763a6 GIT binary patch literal 568 zcmV-80>}M{P)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB6003}FL_t&-S7T%V0@1*x|KG0eVc^nsVL+z8 z-a5p{$gO7gU%)XPqz(+8%!p!;$yf$v|9W+ofeEAwSrVoQM1xFY0GS}2zVtr`pwl3$ z;U>V0g_#E8gG^uo8-oLYtS9IOMv!KZJJ7ud;=f*B#|Qv96iQmwy+H8*00000NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB6002=*L_t&-S7T%V0v|rv{~#J2Z29z0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmYE+YT{E+YYWr9XB6002`-L_t&-S7T%V0v|rv{~#J2Z29z3;wK literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/Prosecutor.png b/Resources/Textures/DeltaV/Interface/Misc/job_icons.rsi/Prosecutor.png new file mode 100644 index 0000000000000000000000000000000000000000..997b29b2a446fecd8201e255aa482d1ef5e02c83 GIT binary patch literal 5005 zcmeHKc~leU7LT}K1Bk6vkk1Qi9XRa>i6isn&iMcs;Z~{f6#TA$mr4Wf4 zl!EFp1&O4;aoiA_b9aGt+RNCfRpVy&O+McgS@L+&<0n5QI|ZJ38a)pSIWaMkxHPX4 z8+_TYe3RzAs%+bHvK^Q2Jn4*bJ-Yj5xkqo$^E&)m(awgNE0=6?`+!*fNw@%+`Mjq5tjbo!PXPQ6UZABc#kDev1~ z?yzBT-bala7MxsA+Po&r-CwwItyS3%ZF|3|UG>{u%>Jgu&8_534m&?fUKg`+%n`cN zZ425){2IPKbF1ja&u3Db2OHZStZ~iJ@(uJ%{+WB_6^|PG6`z#PD4p*~&0N2(9i3C< zXO|xIaluYsUh%eov8hgT4)1m=Pf_SPp!xZ1s{o?Et5)+;YOhG9-~S^mBWvH^>=e6gtQM*}iz6&vo`(t!OucK-Q?s34 zy~l2B-n?g%CO4DE(N0d-(UTJ(^P|`#lM502TMG-v6i)hw74}W7^4eCH4E>IL%IZaJ zE?E=pxtpa|Eh27N-V1!P#c_dms_m?=vr^I=m$W}X(z9imcO%^-xq-7<@^Xqk&peiB zH4WOcswQWSTie+zWO=8yt*9}o>B4y1>4#GczSGt`|G-dN*kY*5%QPOV-(nwI60U=! zd)*yvpqlow`{ChhvzL^vYqq~8E*{fBc>&#~1P&pNipm+J9iKc zm##0%>+HEzX(W;t4<60GG4R9ht?DHY5Z5n@rWbZurJQQ@tmG-P@7}3CS4LZV&8V4U zyU@v|+rTfaj;}M&otN%*b}QakStk9^yQ3og(4#GZ;>*)YcKLQctK08yt9aDUPdwM1 zydlu3`_p^UIOC@emOgyoS~9fsOH|g(&aTPX49^JU8G;p z8QL0d@87iI(l^27zc$PnzaQT7!eY!~a^j^Q{-`IB#;7qLpCAlDz^VN_F8ez-@d~@v zP3&~Lg#kG&Yphpo+dDsdyWfc>**4bouG3G8e!O+Mdr_{uRJkxO?fSEip4nbsuzHDW za8AM5itWXZM2eW%ZNGH=c1_pzG`>yO=#|f2_JzB3ahT>%?)xgw`U4$aQx2p}^0Vu( zxwda#L3&^Bv)Yy;52Xzc|NXMw%Rhv5-~Rj9$<8e05sJrLkLuvcsW|xyhgBli4HQT1 zz2vWUEeXsUkgPAhfM*s&5RT7Fju-}-GG;2}P9e2{{OBJu{qB1_oVz)X%X6z%>00Cts{;dEb9ancnBnw4&H0F&`Q8HVDGQ9ydHC zuB48=|9JDnc2Ux;Slf2o2Rr}N(^gbLjN{sB)M0~(=dfpMjK@o+b#1*G$3J^CCc}w; zGr8^K)d@!Ym|wA1!IoW9qIdY*P1vDuMqq;ndwxD8A8O0 zs1ed2iVv3qdG*3X$TBgQ%sz&438s3R4Q1fyvk3dkxEDC z)w*F7fF5)`tf4b$47y51AMK$deB%Mha6*6Tp$i3ni0Hwn4v*6!sBb)~CR|2S$dM6$ zO`KL~E=P{gQ6;JZP#uWMd?Td4L>e^WVUi#UQ)$dzKt)f8VS#}P~}H2>tY*)oL!Wf}#*dpx{BUyE_}=Ddb#~C*yON zEWs#>KrIHk5>}4R%0wjxR5A`rz>^~g#1n8>AR9Rfs5o+n$7HZz4won3aph(zIU@AK zwJI2FC#HgS3rY3NLapzDX8h8~re`7lu^=3^m*k)aZFa6CGsG2j|nLZV@H6bk0YaKpZ` zV}H^NGSEEW;y|doj0tg=d<23~*d0%E&vkD{ZI$S{{z*^Kh3g`&50u5@` ziZXwAt6bm2Cq$#BeE^a{3^p_(8J9t&4;M=}O^jF7deHw%4-Ye7)QACoLpCtFz$B!P zjKX2PK(2q~HM|dhWe5u8U68lZ_nlnt5Ti#KNf^Jzu3 TKc9665l9l><>K + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/Resources/Textures/DeltaV/Interface/Paper/paper_heading_warrant.svg.200dpi.png b/Resources/Textures/DeltaV/Interface/Paper/paper_heading_warrant.svg.200dpi.png new file mode 100644 index 0000000000000000000000000000000000000000..d13d8cf76b7f251b4c1064e87cea2230f43df73b GIT binary patch literal 10022 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 RbU^?B002ovPDHLkV1kb2nQ{OC literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Devices/pda.rsi/pda-clerk.png b/Resources/Textures/DeltaV/Objects/Devices/pda.rsi/pda-clerk.png new file mode 100644 index 0000000000000000000000000000000000000000..6f690e235d826c957098322cbea4a474f77d7b21 GIT binary patch literal 1022 zcmV0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmY3labT3lag+-G2N400K5iL_t(oM`K_Z1*0J_8UjRyfQ6aaePCq)ihAdNQ9aHO-U#cMLy& zeqmr|=K;&}a0)RzetCsq%bs~4E?zrW2zm{u;Ntzc3}3%~XJAmkqWact25xRn22JUB z6iF_2K4Oe!Aj$zC%S&5J7;Zhhgkh+fydFb$bq~Ya504lYPW{AC(P#iy1ByBvQ3F>) zlmkGjkDWdM*CZk)1ZKZ^^$v&;;$L>}1&SgZKui!2?EpSOUJUcl#afOP6JsZe8ltn| zr}v*3U>IfsI=`d-0?7`bY6!rh;MkQZ;DkvGAldXF(+fOsRVE@M;`1KRRo73+YxZl5F_#>vo5P652C!yg8QXIx4Q+&|wiy!m*CLGm9_MiW;M=_@9K<5cq4Wehj4aDQju zU%41CQsfJd0Qf?zFcNAF<^TWy07*qoM6N<$g23v+W&i*H literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Devices/pda.rsi/pda-prosecutor.png b/Resources/Textures/DeltaV/Objects/Devices/pda.rsi/pda-prosecutor.png new file mode 100644 index 0000000000000000000000000000000000000000..e44dcea1b57c088bcd901ae4ef1344c790bcd572 GIT binary patch literal 6141 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 aJIy%T7g?1U4 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Misc/stamps.rsi/stamp-notary.png b/Resources/Textures/DeltaV/Objects/Misc/stamps.rsi/stamp-notary.png new file mode 100644 index 0000000000000000000000000000000000000000..b726cab3d3aa4c490adc09b14135bb1b8d658072 GIT binary patch literal 777 zcmV+k1NQuhP)0NRq`}3|WktD3OguvB6@DGT7X?^QGqAx!pUHWUFi}l!e&% zTKEsxDqBh^Qj(p$uZ^bbJ!Wbo&h6ay*K^MEcFuFaKb12~w>Au>RdAw{5p6!cpw&MU zpoI=b7}X8eo}QhE@$dM!#i!~`zv}h>zCTA(GUXcJYY-kXY^NYRCOoxLuoZ6#w;NeK zDSRLta^!%*mr75R`AKo6%x{XFSaclxs;8Fu!HFMiWF1quPdI4iibmx;>L!7dH8(4@ zOJ+ANQ6`C?k)X&jISTYkwIs8@ec^B440-Vw^0!&V5l4osctfHVrE5xRTJ)5BIaXEf zzw>m{g9GL6fe6$+dfsaf)Ney+%kw@DJ+E{GH4kuZRsDI%Y4~0At*RE>ht_pCy{Kx5 z9XQ*7&U;&T^lzy~razsAmlJ4?L)$epE|#;ZtaE$^u{C+3E7;wGUfJKe^aYNfXiVEe z>Zkw!010qNS#tmY3labT3lag+-G2N400BWsL_t(oM`K_Z1*0J_8UmvsFd6~_90H8w z+Mg(7{a@lgBf|^E{|xir9VOcw7IGW_vfP%9i$RRxFM~M49|i^>pIk?f=JJgK&H00000NkvXX Hu0mjfH4R;e literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/icon.png b/Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3cf56d453711e1d07d02997fa223579b8f31a149 GIT binary patch literal 434 zcmV;j0ZsmiP)J=&Ll)CgG(?|+_o$Ghwf9~^iw`8Z+=bka=iZR#Y|ryVp0Y*G z`UluOfM)F?!nOPC6*33FO;p{o1R)5>SP@dS z2cPu*-w>Qibbt!&tYpiBARxE`-E`{F_3ab?62MxxfQd%_mjswELp6>z3J_zu5Qz>D z1PbnT9ExDRP;1_5Tt-|Fsb2v>P@DSiA9@8Yh_#<#Ql)c2X#EX2AhdtSx)3aRKnH>? zkZcRVnuxZ6V2@;R5V%KwCIE2|P!fc(P`V01iVH7BQ!zoLJ!3qU10pR+XR=i(1poj507*qoM6N<$f@Zw2pa1{> literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/inhand-left.png b/Resources/Textures/DeltaV/Objects/Specific/Justice/gavel.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..a41d27bcc71f367c6771ae5b670d87dc72dc4068 GIT binary patch literal 11051 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 NgQu&X%Q~loCICE+PhJ23 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Specific/Justice/gavelblock.rsi/meta.json b/Resources/Textures/DeltaV/Objects/Specific/Justice/gavelblock.rsi/meta.json new file mode 100644 index 00000000000..5abad9b4225 --- /dev/null +++ b/Resources/Textures/DeltaV/Objects/Specific/Justice/gavelblock.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprites sourced from https://github.com/tgstation/tgstation/pull/8495", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + } + ] +} diff --git a/Resources/Textures/DeltaV/Objects/Specific/Justice/trialtimer.rsi/meta.json b/Resources/Textures/DeltaV/Objects/Specific/Justice/trialtimer.rsi/meta.json new file mode 100644 index 00000000000..8081065c329 --- /dev/null +++ b/Resources/Textures/DeltaV/Objects/Specific/Justice/trialtimer.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Original screen timer sprite by brainfood1183 (Github) for Space Station 14, modified by Leonardo_dabepis (Discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "trialtimer" + } + ] +} diff --git a/Resources/Textures/DeltaV/Objects/Specific/Justice/trialtimer.rsi/trialtimer.png b/Resources/Textures/DeltaV/Objects/Specific/Justice/trialtimer.rsi/trialtimer.png new file mode 100644 index 0000000000000000000000000000000000000000..34c8f1b90a973a28041bc16e327ca95415305509 GIT binary patch literal 1170 zcmV;D1a13?P)aQ>CJn4l0N^WT@iMLQxP$sbH7t&{nYOlDsCZkfh-yMT)E7;!to9 zUHlsS4|Ek=6$C*ML>!&{TBOALnnH`TFWlT8=e=`zIRT`!!Az$o0hpG{GpVG!nqQMc z?~pJ;6#*3H*h|^P9J;QbM+8KFh>Ka>&vje_1xjVd@fiYSpcMrwtoYSeYoHF^wGMehIe zbo7~Ne|k6x^uBuD=L8Vi2kJG?`#tr%`WX;>0j{l6rJ-WRi(u z7lb^fyTAIrs;;g9_|MJC@_&41Tb|o?T9xJD^RGEv4Y+Rnlp_yrZpkYbj=}9)XOusK zp_>w7Hu2*3pP$CHM0$DfOU)}1p$q&t)c0?kg2_}U@=u-~)*`paq(}EgphZZI?+QPe z>oOVjk7xHl;ukJB2*yEzz@II!@S~(F@?Ho5QsA47$wYTD^@w9Q2ixgE;Q7FOA9m&2 zDveV3`|eeoFCYj4;4Fye(IE1KN4_uuLvzq0dKP$boL6LbkAKL0F5T>$F_?_&rFjyC zqX=ZZejmVJBuAn#oB<0Ml4t6Ju<;T|&cYy|&_vN!ONXL|64A2`&0<)k0(cm)CJo(Q zYPkT(vxq#C7+EAcWkoVB0;awaNji`xX`;UEOtMruStm*-KPLADPeesj>{foUvK_qyWS;X0t2s$SOWf zLWo{HuPPd-6#kz3z8=7wSy}vC22hhi%}SYNi%51)Ij#fD3k#lBI|*9U1SPT7jUNl} z`ilkAnFYfQA3lF)Q2Ku$YGqdmPf;7(6@ID{+!=9r@s4s^wHd2$tTR`3fuGs}!$BW* zM$Ml8MM@leE7qqA{9FyVcIh;Xrygu>xUJnsCmi`~|3~2gw{HAgA5bTE|K&Mx6s}*~ zQpf$}p@c!dU0vQBNqBX5l*<70VeR-SC$tD{N3@8%#v~EC#BUqhtZx)B3K#{90!9I& kfKk9GU=%P4{2dDX1|sUKK8xh*;Q#;t07*qoM6N<$g0DRnGXMYp literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/assembly.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/assembly.png new file mode 100644 index 0000000000000000000000000000000000000000..056fcc5c14180f45674a4b128b840a76a31ef1f4 GIT binary patch literal 1645 zcmV-z29o)SP)!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000id000id0mpBsWB>pJqe(ghw%Oc5L5H zw=4?ypa19`>5dooqlYCP5%Z248XB@p+o7-jZ34)3K&L$M(z{$Y9ENR~d%kV=frEXe zOUm%bh-*tZttZ@q_T1M`FW=QiW)N$YnuKNr0%}53Qer!{JHpZxW$cCb4}u5VGCult zz4q2}a?!K8no;xlteRiRw%qE=t9rS1N{NM2p45ee%A0%gl@FkU0RSnAk}l;^fm&s) zioR0=cJj~<-MnEe0)WSAx3}+H`Eo9R-mI`tuGrbIn`btJ#^j9%V4xWv(2OV1o3;76 zue}mlAY*AZ0C3}A0))5--t!2Aw{+WiYB_IqijSFF+TbS5D00%U`*9e7MDGv%q@Ne& z(-3z7_~z4)>)?^y=)=Wg@oyY&ECL(Gn~?wZW!BOgtE1S;ICz2%MKB((k<2a*=h?rC zG6^#i>Av<6pfwF)^We3y)niJ3C7*M4(i! zvIuBt*t`O@3GlBc!8nYfWilCJV0a3&-Y7wQqZF^Fap+Q2l@=El>G#J@(C1GbVPlqp zTekNawveNIHWgOat7pLvkGqLh8*hTp$w6#DOMC+lG*<|!CLS*s@{x~6_3uf&bDsJ$ zPj~Oq2OGu{ipvq1)A-}_K1$XaPvuVc0HHW;-o(3eZjSDEX}9mBj=(rwxN#P)^=hJB z3Q%&mc+4`Ns0rGwL@bwTM=uQz57WHXD$ywQYh#eyBRLGu#g*V&(X(9vUn^r0LZx&2=R^BZcntE<2tx; z$ch)9aTx)GOtomch+HcOtb^y`dbiKdYME7m>yIPvJ^A*h2UJNaI;g(&%(+zY^sk34 z?V+yu1=9(jV07FUxiR3BNoGgvcl(~+i(bad7c{-^nKyo%PZy>?o35R&y7l+C1>rXQ z@L10BHbi;0`Zu^(cb1QT`$OfIWKreDVVnJ!*gc&^9G(7{*y&~|z}p{aTK$-G5^64s z2Mpd3cDkLSV4kca&t*CRB0gdOqLpq|1>%!S^nmlBtkXxSDBo_a^XIhwN1M&!_0#Hi rfb(1b8AAv5MyjcWq|{gC?)Yg=ABppUv000000NkvXXu0mjfO|dJ^ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/bolted_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/bolted_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..6857f2a24154b06497367e4b2474465b750393e2 GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJa8DP!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000XT000XT0n*)m`~Uz28A(JzR9Hu?S6fURWfVR$%yw9Im%>tZ z#oDE$Af*XyYKT^A6ctl7u`vxMHokg^`lLSSQ;o(nHjTbn-+VERP4q!Av0gCs(xz=B zY5}`7i%r>H7Iw=5yDaR$UYzeA&g|^$?1D{CGMSnGT)yv||1NcRcNa;Q-rims9Ua9d zWwTlFE*6FAwumH2)ZE-GVs&+O(b(9S_*NJ^5{b~`p@L{Ub;C;o0|VsO9X7SLngnhp z5|o^srQzXWdUW$LeSJxz=XZI8e(18irq6?|8DV=`$3ns&Aq@@=76A^WuU_z}De<&M z0iP;tj$g=_1lIDi>KC*e{TBC#N+{!lN}f`SE8@RlL#e$M zXssAtRiP)gX!MV%Q zxP!d$Pz$|sf0GysP7w?mfy8XqEkHUsY@ca@4kQK9T+V}dq)3Hg<{QQiT zN+q?_Y*MR6V0zw|uGJ(uanTdM5!Lu{_rH3KtI3rV1ni=!YGQFN?l0t)^LW=psi8z1 z#NY@2R&#W}69Htb)q9(+Wf$iBc-t}3+1z?LiCC7W!q2e+u+qWXbnqD7cCYoU7gZQm zbf+T$21gK(um(f+T!G-m`kIxnlXptSoYYusRx`g#2Ss0%jegc!v;XK)*4HRoie6Ur{blP zV^g$!?_8^$#FeoOJz0MTu`QE`FJGrvGE_kpvBH$5=(%s->Fev$vqEMr8W|ZOEJM(9 ztgwG=zUe%0(A$p---Ynpm=6xW=N2+iQ_cnDX80On2NUo4j)a^XmWCr{(R~@ zef7)<@oyKU?Ga-nV?^%=H=26%T`Cz5YAg9GJ9aiwu*Xd_U%nFrE^MZ@U6nHdvBKfB z87uTzr}5oyyn_2nvCJ_*a*-}BrRafuhS4f`RCU#b#z#}s6Y){3P@X}xF@RXqRmyeG z_&7c6(s#&ygTeIBk{Qc!Z)I>%#+7`uRu_D(Md_egIS}EaFTK>>-cAwy$#ry4i~e8H z1=fZJsm{#Y-tI)=xeX!m%Pu;W{g?1<7Yx1*9T?*Edc|NYb+Tb?j)94v(zLbLG^8otXiG=lxxE2YvWpLP6+t_5Mtra9>Du~Xj zR*|(xK#$C=c5YwuRlA?Un+tCcuD?!vxc|K`j%bpUsiWei%h%$WOTQm?#KU~IZY*}A z){Y)u=uW>PlPs3f9}gXP8}G8sh%0~-FHXLYp+nEU^-Cm?9{O^qa6Ruf&f^Y(-SCsM zb5-vKQ$;0v?uVaqXJQ$R!TEH};iT6FI>q^rE3uvGGl&xr>tO{Xs>OgWz=18}f+$Gnm4H}}Tnxf( z3|{R}YHhD|aAk0DIkjHTaZiLKlg8=jc8lL{EOyrG`G4STl?ehIlk)%o002ovPDHLk FV1n3VX|ezS literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closed_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closed_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..c78d01c42d084dd5be78e8a33a599a90cc86107f GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJa8DPP>^Ss#&mpghvZkX~#s0-h3N2b6`K?}O)meqDd+l#VI$hWM`6MlQ q&#%(rqf#%I&Hk(pG?9U!&gT+u#1#>y1s3nVf%u-TelF{r5}E)5_cy%& literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closing.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closing.png new file mode 100644 index 0000000000000000000000000000000000000000..fd27f05b3a2cc24421e7756fbdca2d77b94cac00 GIT binary patch literal 3014 zcmV;%3pw!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000XT000XT0n*)m`~Uz6{7FPXRCr$PoLy`j)fLCju4l8mS=+=8 zwn>6Fn0z!wIEW~G6e>tcDrg0v3QASfj|Wshz*EZuJX8b_ii%L_Q$dxgJ`|y*?Mn$# zfix9Si=a`{kJu@uwH1+=;Mh(!!S>p_jz2p8J3i~{**iNkJ9B4OO0KkuHr}1z|D1E@ z-aB{xv$4+3&IK~t(9lo}|LSfljQB#wnspU1I<$D;XTUzMqwziVCb7NznYjI;5jY-24 z5N!cC;@#KJQ{f-KrOAmR?Y=%~{&zH5z@?Lis9+L5vvoaPTAY}OxaMu;iiVnL=(s9H z)0gIGeCm?W5S5nZl?h5G8bp_?dCQ2iur}>T|EK`pwsEy6LKIq%{G)^C1vk!N^JE-F z8eV<(f6FlT*5pE; z)Wy-(=&2SlnM{t=O#vnfvo*;>s&SQlB}x%$Db`H^no_k{2^A(UuCZ4>N-d%QSPR#( zp~rEri&~3$1`NxwN2vwH7v1jFzgTP1Ap0I(3yA#@vD&$BbLlH`kJF_^#a$F2RzbKJ zLkm-j6O&meerX7bBKe$gIr*x>>C#e(`_H#?%03iSi;5|+lE(1+1sa_>Kd~DJq#@>=0>BD`e}kr|Lu?a>ShuSrLt8XWNN`0exh#Mw{KtC ziijFsFFbQ1tl4!yu~;Ny&CV3HA76(FII^68>C|*;QE_|o)1Th3wV67)(?nk^-w6ss zi;9VrUVs0DNWo=42PD7SkUh~mPTd1dG(5k2S3=huKv)QFvbtbt4&WtI6sN&&il-}L zbZJp>in0>I)`6AHnWn6hU{fu03;!bq^lUst?eUqu^TFji+VS7^R_$k zP6g1drLC*GsV;Uy|BmkVWyUO>(wGVV5qwB>W6WYoew&- z$TxdXgmJo5``u6uIKms@q82ibZ$s+VVrN1}?20|T@_83z4)9`6k7cu2vH!EM;Jyvy zMT{3Hha8K=D3!9dLJ9@zE?KoY{Bm1NYr4$s>FJ@~-d^8Yybha)m6@A1ZKA%uKJitf zv9XcD_R70?;$%JUq>^9Gr?e=Iv+r%SH2QUr;bX;M)JRu%9+Wxp4veRLrbM&;GvlNI*atK$u`)h zE>}>8S6=qS%dGCT%_3l3I^2$pp5JIoeo!rLOvI0ypJ0nCVffTzw?4K%EU&z)Cw}|m zKVge4XKK%c3tjq+9CthP@_*5pHX;Rz5 zq*CFE5nl}2;EA{MR^9u<7fc;(I(68&=^anLHhtu^CwVyFUK^$sCni|93Py{=qYjV! z{OrtJ6kd7oz~UDdRJRU07w?@qQ&?Kum>B*r2NdCvhe0VKuROdT@(Xzo?=|aCaaA=4 zQ;RE8Ov129!>LFHFNsIws&{ zPYMR{%6sv|OTDXOG2m-W9T=0V*5Q|%&*%RmyMZ`nQ=4xs_N!sp|1ZbNO!?-I@}_)H zue_TlesQ?#Fa`B5_ITxl=vRjy?mWepE`3cA%v$USWpjg*7S&dS?EjZzWu|NL%^r9)I{a|qO2eX>zXQ+yJAG$;YZ=a!n<`}gzZ@$w z@ptB84p{oR5L1wDuRH`n2wvyUpBFqNU$+iBS0u*P!q(!28Rw-RmVr@t<>84xb?OxT z>l;Vu58ph%DJU&Lb?LBk@!p|@ro{_W3_%#D#&e?`rc*c+ue_Tl9?a|;8%6wGThEp9 z5LAaBF72?e{2h3JZs>3Jt!2$k<@g*7JvxYR4Zu@$1*GrvdXd+to$%>)$O)eh?jgxT{SaPR&nFf->Xw zqzCoNd-23~nTf{>w?n~`1Lmao)!~qlW4$dw;i=ey^)8Unu zkBQ{N8O)dJP7dWTbX4NXX8?aL3@vWVJNGQD{NpO14zIlIiAVAgJnucB*Xh#X#I^6! z@aMwN;+2UUh&dom^X6=54GV4)Y|y`R^6kgbt;5buH?@f8a#fDJu(UWa<=Bmf_B_;H zjK%T|v~cyw&qni~{QXU3j``OGgBAdu`0UzNBTjMgc>15-`xzzvec-3NU;O>cI(3wB zpWE{+_-sYt4YDw`I5FkTIOE`Rd!I>t|MeeF9{(`ia?4J~UrqArmG|O_|NPLA)I!f~ zGgGgBZyy{OxHlVAhhHv|5B8bdv?u~QmaEa?#FpYkhm$eO%_71>5T6NdpSNpKCEw364ECw>fn{S>(BX#1ShaKnf1<4k_`5#tCAgtS6=0bmszrCb_&?FRHMU<%M929;nn0K zaA&DTi&rMtNIuwc`zj!8ue{0=uS#&(I=pb90|r@91oKSbGqzeSUYVSHVb1mQW36G^ z(-ClMtM!0%F6U}ZD%DM;!;d{(=CUoG9nyZa_!*`-R@t8Ze`FkwiUtWPNdN!<07*qo IM6N<$f(|R_lK=n! literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closing_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/closing_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..2a71f76d5d0c792fe84b136920ab32a386dfc7a5 GIT binary patch literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^2|(UR&i(je0cL#ec*0}-@j8|{(iQzwzWT#=l!&5f jT;0h840aHhFykh_!rG~;5AeP$1@S#y{an^LB{Ts5_a?jl literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/deny_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/deny_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..7c56263f83958a17893b3db0b04ce3078c15cea0 GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^2|(x;TbZ%z1lzVbEa*5x0l` zFLCLtQfk)goBm*9Wqa5)W5IyH?gg7O+Vq@#{gzqI_j{ICbSF<}<0|vo?Y_6yOll7; z+AsO(r`@v>Kf7}$KR*umYV~i&zP&s*_xJv-=38t1deYzEyLbMqy6^o$Z`IbavsGXD zr!(F8`6z;|L6RYjVFqIYc7~Z}LvrZvRZ(vk567Q>-*~3QX2MKG<^wzo#tdf|3@{iQ zO7s8d*3Gv+{xi?r|HRuDl15mS!8LAhWr_IppL3FmClFnFq60fUCY M)78&qol`;+0G5h<`v3p{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/emergency_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/emergency_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..817f2fb3f95c53ee8720a7c5be418b6208a6a7e6 GIT binary patch literal 588 zcmV-S0<-;zP)EX>4Tx04R}tkv&MmKpe$iQ?*4Z4t5Z6$WV2$AS$ApR-p(LLaorMgUO{|(4-+r zad8w}3l4rPRvlcNb#-tR1i=pwM<*vm7b)?7X`w}o2gm(*ckglc4iIW3rdb_hfTr7K zG9DAtnN>0H3ISaRVg@5Jvy3@OO2Bh`-NVP%yC~1{KKJM7QL`2Ud?N8IGfbO!gLrDw zHaPDShgm^ZiO-2gO}ZfQBiEG%zj4mHEbz>*nM%$Rhl#~}8!K(h3Z_OpNgPo%o$`fr zgH_I3oV8MgHSft^7|QA^%Uq{9h&UFp1PLM(R8T|-HlnoZq*zGOe$2x^;QA$UDdZ}G zkz)a6Xpmh$_#gc4*2+zcHN#J&iAq7)K38aGjOH1{N)-j{YiSY zrA3Z_-fiIGx}_<5z~v6m|76If>`H!`LM{iqpV2pEfWBLxd#%x1b04Py{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2j&6>2?sl(`5Ny4002lyL_t(&-tEhw4S+xZ1i>Rg zVKDSSX!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000id000id0mpBsWB>pGE=fc|R9Hu2l$DkJ&j19EA3tUS(MSL+ zPDQ{7G7D(mKV&nR{59CAXa{jdMeB1jfG{sFF9Q<~I}35TXrRhZ=^q1nu+zXA{6-EQ z2cRboS_Z|^i(lc!gA+iJoiM}q-+vjVGcf$ak{hV%7MS@<8D#%~5+XPXUVi*RRZB=Q zZ1AK3Qd~_=_!)T0_TFhLvO*FXq^L)>jF>?00DRu(8F?A(7-GQ@mZel z2WCMbl0uDQ#b7(3U~nWtioHaE0W6Y^z#M>7HdA00(OSWFLc!ok1N5v7_X+)lhX7+d zw*tKF2a-U_jx=c#!fXb4*y$ZJ10)Rq0UsAD!@lDmh>k~UC2#nT-^s0)n q)rNy34NxOblWWF+hXCV1ch3Qm166kfD&%4S0000!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000XT000XT0n*)m`~Uz7`Qe5tL#>V816AmNaND41B3qi{KP&D>X` z?9xg$JW~7j?=M5}AvjGLmXFXfkuQ<%^Mm>wqaf6@A+#>WM=Lf`+LLs)$hZc z3A53d_Q_*iC31vf_jbjHiSY^J5{Iv*NmXI_(DNIm;D0=PrN-v{y_;APax{3l0zhFl zpgr8ggIki%67Gr_7W^>VN#V+TFdsd*?eG~*tkm+%uYQuc?|ZMoCm7=+LZ1ELHY68b z7utHezW-Bh1Dpj6u|&b_>grOi4&FNQ-$-0ceZ_EPP#Yc|GzM?PK-~V+>u+qFyPV## zb!)>-#mV4?uP85lc@uf=iyPTopepTTF1`JpyViB2=F@jR`|~%T4o?D)An$>;m~t={ z7MD}-qjDZ_F)psSvfs8m*!={0HSe_>AARxF@v-x5*<8~U7I^;s_~*r%9xb*R89tK} z?PPa9|MvXxx1R^B84}DXP~ybIIAdI>uT>ne_Bvm6vEtWd9&7~2C7n)B&P`9WE-x-D z!KbNll^w9bf55I-M_hHqg^6(m`zkI;+$uiG1aLx7 z6OtgdfZoqXK*vp)(5%bJQzerdhzk=VgmFn4SLP%0s4VK?VQZx~+(v^A_v)(E55F$< z{?jlp|Axmneq9K@HKzPD40}OfPksv3aiQE`v0?11Za>JD zM`Z;3^AEwIXC?SG9f@C;FUY}%>q6bM5d6Vq;<3kV*_JIP76jE6fR2l5#9+Sag3oQ) z@bJfu1v{U;ej|Bz;1ap>q3Jd`Am;`Od@|w{>ozV2z30W@LWcuP`pMtuS9PT={z&9#wO|TzQF&0D7NV z-2$c7;rl2Bf)7E5pDS0c5S9$7#EpsZ#JI%et7&{>9?E4XUxHGjC0L4@8kg&pN+ojs z{CV=PCq5>>`^F&xe6`Dz*?IVOJR!@)`hRx~>Yn=5wU-aRul(NVg# zbZ+Ne&7`9*OUUQdJ3;LyH~SEeQJjE4KiJG zY+I%E!0FTED-CqVb9az|@x${KTW3o4m{@O9-FtOhYu2sF>-7VBOCP--U!Es0zl#)>j!< z#y6OZ7oAUJhI#qHX=-bq34VBvP~`O_2Wts;=sgsVO-+!)g&HJN9N)4 z%{9Jh)$qxoH~0Sdx38B{slqx^zWMCMiNdG=#GhJDw@`-@h>T&Uapc@432y*NKX0x*MwFV(Y7JLk`;w#dxG% z*wf3Fb9^M|BqCy_F=3XC4K^$dWGoyPFl~fcI@^PzGc}!8?j%qF!<8FD0#v)97!Uu0 z$=r%QCosiF0w&A~8*1`s(%E?TLYh2I1zIkc7#~wE5NsV!)7y)xo{onP@<7mPa@{7s z9f_(1(J(it0ux`>Ku|Fo&=!IZ*!k&CD!0HWm{@R3xrFfy^VKvdIvySfWLXmENPr@~ za^xWVJ5C6DDKCB>_TrugpDUzYFvCWG$ls)%=)cZa(*)>Zk`m?Vpc92MHKmmVnc`Q~ zYi$i4_C$GlCKK$Y+F-iM(*cijamAGbVIz}=wke(5PB-g^Wx|#Wx8;I~@zHTf0#n6B z=HVYWaG+98rT>rA)rCejT6uovz!ei~ui|p~!-MRc!&(-Rhkx(f>y!XQGvt3Gy=sQ8BULhjB>?Q^iH*;mur~LT6gg#3xxmD=*tm8dK%Z z^}ysjJQw}HYjWiC0N-%ILE=bKr_uSM9x+_5YEbb2xJl8M7W5!U%}0 z|95qOC*S7Gfh(q}z3!Yt5}4d3JO(ngRG9uh>OP5yRvxfbXAYubV!;Y~Q^nux#f_=r zBJ-#@A0Rh!C8g8Kt4O+HVo3=57XnFPsy=hWKsoA7p zNn)ye5qYo?5LN&08YtCy0au$hT6W1UuB zz7A&&Trq99K;0xURa``$eVzW_wJYhg@~U%Zu9!CS5!Ah|bAV3&&zDV6gM!J$!5*9+ zP!(59jB6N|q%c)nL>_Ds*6IIsnt04%6Ro`5mY+F@iW!AVQkW_(a!lAVG)_&t$^BQ< z%6I0*-jv($GY4xq7bJ~|%>^~*1ESt)Y}(nJHL$UJBi5}sAFviqh+6rzz^i8r4?7XF z7NljZ{90hv8-}<2-UrqHZ;UccdY2Hi@^V0u##ANXdSG%M{%1?s)&CtPv2)!eG||f6 z7BeQ+!|Qf8H2=$|*})0yq>Jk=p=t+`W95JG^sB0Xxng2TsLS2Z-F@vW`1~KUCV7uk zY2~li3-LIl=W)c!mjjR_F-$9;BqkQ5dU*xPmZ7Hlf7gtwwDNK3@NK!(iwNNV^7NI= hB{lEJ9YdC<{|{Hfjpj5jG@Aeb002ovPDHLkV1hK%O4I-V literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/opening_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/opening_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..84933bd5ed9cd40a972aee792b227f9aec95f233 GIT binary patch literal 284 zcmeAS@N?(olHy`uVBq!ia0vp^2|(X)s_s z#KIwr!I-V$V11^#dUpKLjjy-9DY|#Kuw+Jjzzl{&rWQ^CH3uAwt;hGhNWR~>|B3$l qhyP2a-~C|qG6v`^C}^l(vC57yE3)EC^YOwKkf5ilpUXO@geCx+nr^EA literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/panel_closing.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/panel_closing.png new file mode 100644 index 0000000000000000000000000000000000000000..db7be0bc4a0ec0b2bc29e8718fb6b71796846f16 GIT binary patch literal 445 zcmeAS@N?(olHy`uVBq!ia0vp^2|(qk=b{5eiK-()1~xQ&@cMV`(mao8yQ?TZq;#^Y}m${ zacWZ!Yev-i>$j948lYsxftl|YY`yljZkp{(pFL*+-lj#WWzI6YweB*{ESZG)8eLCP zH-4D=_wruJUKQWqugks*3w-~bxAmsS_S>R@6K&4#1!`fty>^f8^xkc+O+xqazTJA; z{=7~2>uGDRIhyR%SJ)ONH}BrkKUz=f@~-S!d-avVtb5`KJrkcF_ZOUaf4N)v?bouY zpX0AZna`Cr-@$dKByUdGcPkF5{Og%j`&-%%FXZlavSVWw{8-KzzB@7SM0TXvt!o+A zif+H$q2jsc@9*!WwR0M*e5Y<-(ETyu&`qBj{lx9nl5Os{*Qk05m8bu?%XoF&`KQ?? l*%zfe7FQS8+W~`WRsIyAi(3!btSA5lf~TvW%Q~loCIEIM%9sEE literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/panel_open.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/panel_open.png new file mode 100644 index 0000000000000000000000000000000000000000..24eb2aedc2248aeb772b38f63ff992254e7aaec0 GIT binary patch literal 315 zcmV-B0mS}^P)G_@Zv*NK(#C83< z0hCg#mPY_q%Og#e`P2l!*GQEjpT`0MYBKbMv^%3TIE=g7KF`WXCR28pn>(x2n zemoXytpJ?bfcIZ;wOEjBHdt%rI!S!%PGhZ=2c^1AoGrxJR_5RoDx&OEP+E*gAHf&mPbH>ZE8FCH9e&*rpCoP%1 zIy_fR`1DT4EhW}ImG2+Fy>#^EcBOlIu{N4r8M|lHdv8DdMa^XX`Q)41s%D;5@l3t_ z>U!DiCu(!NfiicFek|lsbn*16WPNgF)9u86nlDcO+<9uZb*sRm>zlTKo#3wDtk_cV zGUiQg0fX*;t18(yxo?DbZh3Nv5#oCg`Gddm{r7*~nV;{o)~0;#=kiD}oLj`YgzrYV zCx61j+EYJuRBRcZ$AIaEWtl7E0M--(oM3v-T6o|50rvB z?(X|$_9K~q!b>Jme`5^XKVF&j%`2QtMsN-@c!MQ;uYX{&xPXV-MV4h*a7^*H)mTo% z^duKBlw8QrI7#Az6a!+!k42gRM*{jVXw(2^)BtAG0A@rO5W6r+TTo*dR0c>itn&u= ziYhf*#29dhKzXbye)sb`x`T#9jF|@skRQx^J~1)&r}u;k?=m8#VH_qLszE1c7I|*U z-vi17+kNaSpCz%9yQ#rS&sN2x0`#dRVZ$Zo3 z(YozxD(tDJ*Nd^#9ngM11*`#hZL|qqUX-aA#5S}G^!n=WLLU@GQ4~c{6dSK|xP5Tx z!-H@vnhtn%y49-Lc3NyR!WG{&^FjpmIbAy+o5nPrx)V}}E%fz`bB+BtcI@^)8^rTf zBx((Ky3EXU1aLM2IGxVm^KA+58-UdY;QHA(FXNaPN!aD?zV8}<6&DioA6qwm%&S`B zG(?rf)v;@BC^IYu=$f%ZGhhqXw5SF!qXsa;V!%*uXSl{qZh&O*G5ePMUQntINQ83i z$upoRb}H)fv5TKDu*ZP$-hvmY3!Atq6ENBh(WYFFM67|7l05p#?E1nmayZKasmvEs z4%uF#@2=U$hCc&#<3^>qaoRUjD5t(Q@!@5>eLn%YPa&y@Wk6F&Jf;Amr=S&p`TF~H zKQmyzZBbK@-3j_NfaCqFrZteLVgLD`ViBgsl+FQ!832*%0DhkaTq4i015y-4Q4~c{ f6h%=KHvsSpwHV1KmpgiI00000NkvXXu0mjf++aJ5 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_broken.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_broken.png new file mode 100644 index 0000000000000000000000000000000000000000..fb5d774588ae44eab5608571cb6aafad7375e158 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(DFD66%%n7hj|c25u0=Hbzuz>&Md dbBcZ?)Aw7<0^jOhxdW|Y@O1TaS?83{1ORW&Jrn={ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_damaged.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_damaged.png new file mode 100644 index 0000000000000000000000000000000000000000..f16a028dee5bbe41a7f4e35f686043e8a112ce4e GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeK3?y%aJ*@^(YymzYu0Z<#e`9lQK{p_au_VYZ zn8D%MjWi%9!PCVtL_+fI!HvAl4m=D8Hh=XH6ZQR;XyVo{y01gP^_0k+pXD$8l*-N4 z&iUk!V5<=?maE{?*yyS)-udN6;H*Pi5*L(-Fs)pAdDY$x8SUGCM{GTG-~v& dN}IerjGt7Q1>7HnEC$-e;OXk;vd$@?2>`@EK-2&L literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_open.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Glass/justice.rsi/sparks_open.png new file mode 100644 index 0000000000000000000000000000000000000000..630eabb976ecf11fa59ba29f03502b02bde399aa GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^2|(GM)~O;5D{Ad0LZe;7N97KJC6BX-upNVgWUu;=WLfz+qP_d4j_bJ3vh=hfa5r9 z0qVN81qdO4*#ozUc?-;6LK?t17pG~m0|2;<_}}aJ8%Xzkw*de?p>!O_N2;HSWO<%5 ub^zoJEX!gGaL3n-QrC61fn;4*wm#k_G(h}nBOLz#0000!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000id000id0mpBsWB>pIk4Z#9R9HvFS6fdLK@>h)wioC{C~_%; zB1vt8L`@6{nixgJM2#jsYWxMh^5n1JQGb9j_~_-u2MCEVAtXeD5-JyoK%`oX zQ^~j_Nzl;HK)&Vc@e=tMTMfa$zyL(`f#Xe0WuTvHYmi-EhmnyHxZ1uAFF&i6Mjo6E zlCf8d9$T!7O$AEk(d|>VE@$#8G>83U!n3IYSVds)M$%CPcqN%NB6VJ<_12Wfwsv+Q zx4A>wb-ulR*B0~%)vyTxRG3)!Wx(!BG!ha)f0?Ii`*zqKUZJ}!0_=yDSVY8(>*(k( zUACb&a|VJ8L&Qdh(YA+qjtWj>@KPf@yigA!iS1%Z!k-xl5trFQ+a4TrY8-WcY|!m` zP+>L+f&VFv3FMXHk??d(ARO5LPN>GbOrV;FIL5|Xjs*@J3Eo!OE%Xovcu(;#LgD*{ z-qQ0zJPolHV83`8G7QFAv{A7HVwm5*&YF5_b`+Z#$3785v>|`}Q~+g$da7t82uPIE z_gw{U23jFKR=Mpm+utmgK-5LWgdBntLX ztqx1jI2uLi>gpn7=0<1fLG&*~RaID8T7nO^Cg8>0=YVY#x#vs-Vr|CE?pcjMOSc}G zjmk>UJk^c~Xv#Tu#fXEuCY8#U_2W+y^t+$_$ul2wP(SN40M4j6=$;Qlx>R`qahn5x zo8#mj{Q2o=xa`%dZ$D+QuhRv$92Opt^{~1O_x*9x==lA9=$EBca{qaqjdfIf@#n)X&_hK{0o8ZGxjRwQD7fk5F$`;_166E8 zu^#YuL^noxT{{fJQG8To*UAAx0N0y|UD-X1YRKF4;LTSgQ7zn94WEqvHm!!ZJ)OJ_ zn8RpW#%niz;02M71dQW~<#%iJMVrmy?Z@in%lfTf#)yFr*Gl2_E9XX| b^pN`tggBXyxtD+e00000NkvXXu0mjf4R4AJ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/bolted_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/bolted_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..6857f2a24154b06497367e4b2474465b750393e2 GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJa8DP1uy!EP)!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000XT000XT0n*)m`~Uz121!IgR9HvFS8YoaQ4~JAj_&HNo35!@ zqzNmgAVLTgMOhhCP(&CM{er&sL;6@hAfi6@^1%WlFhK;Ve8H`D3oP=rw%qk)r&hOl z?r_GtcV=f+3p%ju%suBk=eg&eJLg_sdwYAH4C(6XqKSzKJW@8B7619XQ2i6}`FvDc zTPv{I+S+Jxa#B2N96XUo(AnlqG5B&eOnrTQ6g3=n*VkJFzAY_L>c6sB* z!_31<@X_RV8}{K?ogfi1oV^6W-7w(qGk%EeN80hiGiS$+y%FLcbes{kWfE8hRoGU= z05-_U;>QbWU1kl(QsmZ&I=XqZM%03rFea1W{Ur!sRx)cZFxD?Do7=TiVG@YNnG^*6 zmtgsKL?DyR{WH!xB2dcrqEv>C1l(o_9qSu+1xt-%`KS)orpCvH1v5ktd8VwF$8Haq z-wXa6v%idmv0_-zSs8f!G*v)OO|zLL&w}Yk4y)?H{ObgS%PM{2E}RsSk$%!b7X3YPL>-Tve#s=@MPV>^6sr3`F@~(rt1NF zA;K*X2vAE)3nh$S&ZvPpCna-Mha^ISdgpT%SNkzYjwVZ-9*oa zh?2Q2ENcl4U5q-OVmKo7d@S==6=JN<$u&pQV^`{lTe-Cj)PA7q-AHW5)?cjg za6j;x?ceIfnGnJa1nbS>)pobj4S~tnaP>^Ss#&mpghvZkX~#s0-h3N2b6`K?}O)meqDd+l#VI$hWM`6MlQ q&#%(rqf#%I&Hk(pG?9U!&gT+u#1#>y1s3nVf%u-TelF{r5}E)5_cy%& literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closing.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closing.png new file mode 100644 index 0000000000000000000000000000000000000000..2a33b5d48af43b76c044ea70b1f28fee76866d9b GIT binary patch literal 2683 zcmV->3WW8EP)!NdSiF@JuQxt>)LH z;5!2FVH87%%FMQwvWq!%jh{!VrFe*oUft_D#y~-}8Q|+9o@Ewyi06sZTaG1ok9dTY zE@~=<%0ep35u%e$i7Zwz1O2ti%oCDdLEsS6K5r;wB;0T**=% zr!@f^8KjVe1O*jrLWhGmWs_#s*_UYemQf}TqrZhJI5~bjqkKyV+Z*If7a)OG7;K;Q+qHe3EO&1vqN^jb@c90TDU;PR%W zDF?vSE-?0N$y{zo0a|`d13oT*!8|a05A?5lvuf_+{0Ycy(-YkRhetq^>cbm<+Gc0@ ziLXu;00009a7bBm000XT000XT0n*)m`~Uz5u}MThRCr$PoZoL$MHI)+wzu7d{s4-! z6w>k|tx#em8WJ=b1+57hMPq`|_~5gzKKbZhz@ra7Y7FX=;sa<(FiK*Ypae>&&`N{~ zg@PrtKzI9Vy=Sgxdv&3&1ugUkZb~|#fNt;LH4(=;lWG}4)09+ z|4v2=a^dQakoAdwOI^>EmM|u^xawtXV|~>$bgaw3?EE53KbjXBlG4(;wgJ{O)Qc`x z_0lBn!s?WtMkWP#f6qpdge0_J@Q23!5!^azHciG!gyHDPD@7Q2_IIU4=AwwcEv-Te z_C_qWwWyfHLbgc2M=xxI51(BRt{TpxJ-4uw!XK3|ms)gORmY1P7ZavP!0r1u9o0rz zX<7N<*BHd1k7X?Y9{(gYN?q7v}CHc5|T5Yq!y6?TnksTV2`6-x6-tTZg=$O zU`-ll-@`P4xIZFRJBJ=GyoL8TS6WnDt{Fd!VX>(tj7coy6^5WBf=>u;V0>`Z{NPv1SB1F&dcR;;B_9%K>PWvH~}Z71({*R zrIs-6o|~=E(YFTRe(_F_4J|4ruJlGmW<&^9{2YKmxRjfQzR?z#SSmgjaWw}3E(Cjn zE?8Iv(UK{N+u&I4dRdGsEjq4BR9r3PnCWyHQXe#J7whu2x(4_(`zPe)ml8W0elOjv zOoU4<7*NhFS_MgWfUUU5%+9(rjP%aH^txTa9DoH63EF?Hjk&0F@p}f)6+6`58(zsf5JFrEc1LE%bMY)q}X*U#CKv?(|F>g!U zxTxAnEM(WtF;tWcT6irU0O8*Mfxh-4W0r-gL#rSr`j60uR5Qjb66Uh;a@}f_gUhj#r*-?!i1g1&u#FV8S2yC#6mXpwzxW?a!~`ZaT1h+ zuZss>r(KRJ z7cmK|)5C1aTd;Aw@+O{mx{Y~HimRhiE+w2F$VAm5e;Sq#cf#U}Y%v7Mw^UrOyv`FJ zb{oglQ7ISo$Za;&qS}gxQkQpb@E&CIOOQzg(}4}Iyv`GkwrnbY{qPxNF9r7SxH_V6 z&z?OCt^Sb+y$3z}Cx&lD)-o|w>h9zIf8JJN;&tMB=#S^+>O$!!yUM4|(s!aD6oO^P zjvd0AFKfVSwspu{{QJtO%S8fhYcXMJS3x#|k9DCZ{@S%`aPGAs`1Y-@Y*!yzpUlO- zT^AE(!5d0qYYh*2*drP%* z|37alF*^<~KZ_uq58%ayS6=xH81uv<@0p7i;l+jq_++sG)?aQc>5P@=h{7E@5M-e6 z9$(+3+3CnyRC56L|MRvI^Y-!C!m|jGY$>?Z!%Z*Ut&5)cFzY#b;9$y1`u548jDbx`2Qi7q9m|wp+gemkY!ClwawKT#l{fLk^9diF4|q-* zS4UJXYC!glsacV9ax7P(#l#y#!6&B&#Xx)x;5`ukj_Z}zdE)sHA~&30i>f0Emj^<& zjZ+d#w5Wowx|=BB^!=oT1dvai{=tn|HpW_&CthZ8zq~CSCR}8lxzi;4IaK0kF=Z0# z#CRG!@~NwWZNn?C^2Bo%7ma>-TRL=H;-Ebcy_%E+8jdQ_V#-7|1|QiaN0PR^@+QZQ z{K%046IX``7g=bK6-n^#1T1m1m@+B&!kioB%UW&Q)3L#AZNUT5Q&Z}1tWw<(DjiYm p>6}ZpcydTb)e>cxrnYi>`oA(9fB?(0zd8T_002ovPDHLkV1kIOCo=#5 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closing_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/closing_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..2a71f76d5d0c792fe84b136920ab32a386dfc7a5 GIT binary patch literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^2|(UR&i(je0cL#ec*0}-@j8|{(iQzwzWT#=l!&5f jT;0h840aHhFykh_!rG~;5AeP$1@S#y{an^LB{Ts5_a?jl literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/deny_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/deny_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..7c56263f83958a17893b3db0b04ce3078c15cea0 GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^2|(x;TbZ%z1lzVbEa*5x0l` zFLCLtQfk)goBm*9Wqa5)W5IyH?gg7O+Vq@#{gzqI_j{ICbSF<}<0|vo?Y_6yOll7; z+AsO(r`@v>Kf7}$KR*umYV~i&zP&s*_xJv-=38t1deYzEyLbMqy6^o$Z`IbavsGXD zr!(F8`6z;|L6RYjVFqIYc7~Z}LvrZvRZ(vk567Q>-*~3QX2MKG<^wzo#tdf|3@{iQ zO7s8d*3Gv+{xi?r|HRuDl15mS!8LAhWr_IppL3FmClFnFq60fUCY M)78&qol`;+0G5h<`v3p{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/emergency_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/emergency_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..817f2fb3f95c53ee8720a7c5be418b6208a6a7e6 GIT binary patch literal 588 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/opening_unlit.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/opening_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..84933bd5ed9cd40a972aee792b227f9aec95f233 GIT binary patch literal 284 zcmeAS@N?(olHy`uVBq!ia0vp^2|(X)s_s z#KIwr!I-V$V11^#dUpKLjjy-9DY|#Kuw+Jjzzl{&rWQ^CH3uAwt;hGhNWR~>|B3$l qhyP2a-~C|qG6v`^C}^l(vC57yE3)EC^YOwKkf5ilpUXO@geCx+nr^EA literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/panel_closing.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/panel_closing.png new file mode 100644 index 0000000000000000000000000000000000000000..db7be0bc4a0ec0b2bc29e8718fb6b71796846f16 GIT binary patch literal 445 zcmeAS@N?(olHy`uVBq!ia0vp^2|(qk=b{5eiK-()1~xQ&@cMV`(mao8yQ?TZq;#^Y}m${ zacWZ!Yev-i>$j948lYsxftl|YY`yljZkp{(pFL*+-lj#WWzI6YweB*{ESZG)8eLCP zH-4D=_wruJUKQWqugks*3w-~bxAmsS_S>R@6K&4#1!`fty>^f8^xkc+O+xqazTJA; z{=7~2>uGDRIhyR%SJ)ONH}BrkKUz=f@~-S!d-avVtb5`KJrkcF_ZOUaf4N)v?bouY zpX0AZna`Cr-@$dKByUdGcPkF5{Og%j`&-%%FXZlavSVWw{8-KzzB@7SM0TXvt!o+A zif+H$q2jsc@9*!WwR0M*e5Y<-(ETyu&`qBj{lx9nl5Os{*Qk05m8bu?%XoF&`KQ?? l*%zfe7FQS8+W~`WRsIyAi(3!btSA5lf~TvW%Q~loCIEIM%9sEE literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/panel_open.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/panel_open.png new file mode 100644 index 0000000000000000000000000000000000000000..24eb2aedc2248aeb772b38f63ff992254e7aaec0 GIT binary patch literal 315 zcmV-B0mS}^P)G_@Zv*NK(#C83< z0hCg#mPY_q%Og#e`P2l!*GQEjpT`0MYBKbMv^%3TIE=g7KF`WXCR28pn>(x2n zemoXytpJ?bfcIZ;wOEjBHdt%rI!S!%PGhZ=2c^1AoGrxJR_5RoDx&OEP+E*gAHf&mPbH>ZE8FCH9e&*rpCoP%1 zIy_fR`1DT4EhW}ImG2+Fy>#^EcBOlIu{N4r8M|lHdv8DdMa^XX`Q)41s%D;5@l3t_ z>U!DiCu(!NfiicFek|lsbn*16WPNgF)9u86nlDcO+<9uZb*sRm>zlTKo#3wDtk_cV zGUiQg0fX*;t18(yxo?DbZh3Nv5#oCg`Gddm{r7*~nV;{o)~0;#=kiD}oLj`YgzrYV zCx61j+EYJuRBRcZ$AIaEWtl7E0M--(oM3v-T6o|50rvB z?(X|$_9K~q!b>Jme`5^XKVF&j%`2QtMsN-@c!MQ;uYX{&xPXV-MV4h*a7^*H)mTo% z^duKBlw8QrI7#Az6a!+!k42gRM*{jVXw(2^)BtAG0A@rO5W6r+TTo*dR0c>itn&u= ziYhf*#29dhKzXbye)sb`x`T#9jF|@skRQx^J~1)&r}u;k?=m8#VH_qLszE1c7I|*U z-vi17+kNaSpCz%9yQ#rS&sN2x0`#dRVZ$Zo3 z(YozxD(tDJ*Nd^#9ngM11*`#hZL|qqUX-aA#5S}G^!n=WLLU@GQ4~c{6dSK|xP5Tx z!-H@vnhtn%y49-Lc3NyR!WG{&^FjpmIbAy+o5nPrx)V}}E%fz`bB+BtcI@^)8^rTf zBx((Ky3EXU1aLM2IGxVm^KA+58-UdY;QHA(FXNaPN!aD?zV8}<6&DioA6qwm%&S`B zG(?rf)v;@BC^IYu=$f%ZGhhqXw5SF!qXsa;V!%*uXSl{qZh&O*G5ePMUQntINQ83i z$upoRb}H)fv5TKDu*ZP$-hvmY3!Atq6ENBh(WYFFM67|7l05p#?E1nmayZKasmvEs z4%uF#@2=U$hCc&#<3^>qaoRUjD5t(Q@!@5>eLn%YPa&y@Wk6F&Jf;Amr=S&p`TF~H zKQmyzZBbK@-3j_NfaCqFrZteLVgLD`ViBgsl+FQ!832*%0DhkaTq4i015y-4Q4~c{ f6h%=KHvsSpwHV1KmpgiI00000NkvXXu0mjf++aJ5 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_broken.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_broken.png new file mode 100644 index 0000000000000000000000000000000000000000..fb5d774588ae44eab5608571cb6aafad7375e158 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(DFD66%%n7hj|c25u0=Hbzuz>&Md dbBcZ?)Aw7<0^jOhxdW|Y@O1TaS?83{1ORW&Jrn={ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_damaged.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_damaged.png new file mode 100644 index 0000000000000000000000000000000000000000..f16a028dee5bbe41a7f4e35f686043e8a112ce4e GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeK3?y%aJ*@^(YymzYu0Z<#e`9lQK{p_au_VYZ zn8D%MjWi%9!PCVtL_+fI!HvAl4m=D8Hh=XH6ZQR;XyVo{y01gP^_0k+pXD$8l*-N4 z&iUk!V5<=?maE{?*yyS)-udN6;H*Pi5*L(-Fs)pAdDY$x8SUGCM{GTG-~v& dN}IerjGt7Q1>7HnEC$-e;OXk;vd$@?2>`@EK-2&L literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_open.png b/Resources/Textures/DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi/sparks_open.png new file mode 100644 index 0000000000000000000000000000000000000000..630eabb976ecf11fa59ba29f03502b02bde399aa GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^2|(GM)~O;5D{Ad0LZe;7N97KJC6BX-upNVgWUu;=WLfz+qP_d4j_bJ3vh=hfa5r9 z0qVN81qdO4*#ozUc?-;6LK?t17pG~m0|2;<_}}aJ8%Xzkw*de?p>!O_N2;HSWO<%5 ub^zoJEX!gGaL3n-QrC61fn;4*wm#k_G(h}nBOLz#0000Y-zxQDW zk>mSwr*?&Ptx$M0VWC*NSXYyU7whhj_H9j})1S=R;xwtvyGtbe;L(K-6n6c{{$PJ0 zv>;S~#Z{oN-Nj(7Z5uBgTXTf>k>;b0h2asOZ62v9UX3{! zB)8m@QCf1zgccT7(Hy7tW{cFxY1eK}&-gJdP>p}_{#Gpu%Px(H=5AT7yH-sxy%hSZ zB;@Fw|K~4XOIx=0-9nWMzhCW|KiQ!`e#P~e@87SKzD{>|z`DaM`k&F+%y+ZDM0t11 zFh7)i@M+mnP4)v<^$fn{oQ%oyV2rBsWwz66IA~)~!~bP{_2#U1kN3SB;ar4dD zl(c<0dPo19GgM$;c%<|*o_Dh@x9{qbZd4J4$Z?D><`!W`mAJ-O6 z`p@|J`OMuj=IwU<8@J=k^SoD>vs?{IziTefh7iU39PMeOf%}qEP*p zc*fVx2l?QRNAd>}^G_wy;`cnftN1y#yZ6~Ce0#r2+9UV6<5$L8&%T7)ZC?t!I$ z*M0X=z2BafU{Kqjb|-_|=nG>}|AzhdL(L~NS^Qex@OA4EREPbDXNhBUXJzqU^*ii8 QFk%@zUHx3vIVCg!08QzehX4Qo literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/direction_justice.png b/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/direction_justice.png new file mode 100644 index 0000000000000000000000000000000000000000..ef94a9998f3367c89c30de82e90cbf633de39a8a GIT binary patch literal 926 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Storage/closet.rsi/cj_door.png b/Resources/Textures/Structures/Storage/closet.rsi/cj_door.png new file mode 100644 index 0000000000000000000000000000000000000000..f406e398073313aa73094d1239530fa0c9f747c6 GIT binary patch literal 5840 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Storage/closet.rsi/cj_open.png b/Resources/Textures/Structures/Storage/closet.rsi/cj_open.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba72a5bccf8a611fd93933b9fe00fbc53cdec3e GIT binary patch literal 5529 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 EZ{JG(3;+NC literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Storage/closet.rsi/clerk_open.png b/Resources/Textures/Structures/Storage/closet.rsi/clerk_open.png new file mode 100644 index 0000000000000000000000000000000000000000..ab865e6cbe5b83f38babec92d33e6a41c2e9694e GIT binary patch literal 5588 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 Date: Wed, 7 Aug 2024 04:36:59 +0800 Subject: [PATCH 018/135] New Trait: Parkour Training (#670) # Description **Parkour Training** is a 3-point Physical trait that increases your table climbing speed (and all other climbables), and crawling speed, and reduces the cooldown on laying down/standing up. Inspired by the SS13 trait called Freerunning, expanding on it by including new mechanics around the Laying Down system. Stats (Adjustable): - 30% faster table climbing speed - 25% faster crawling speed - Cooldown on laying down/standing up reduced from 2.5 seconds to 2 seconds ## Media ![image](https://github.com/user-attachments/assets/09237d2f-667b-473a-98ad-71bd19bce6c3) # Changelog :cl: Skubman - add: Add Parkour Training, a 3-point trait that makes you faster with climbing tables and crawling. --------- Signed-off-by: Angelo Fallaria --- .../Assorted/LayingDownModifierComponent.cs | 22 +++++++++++++++++++ .../Assorted/LayingDownModifierSystem.cs | 22 +++++++++++++++++++ .../Climbing/Systems/ClimbSystem.cs | 7 +++++- .../Components/ClimbDelayModifierComponent.cs | 16 ++++++++++++++ Resources/Locale/en-US/traits/traits.ftl | 5 +++++ Resources/Prototypes/Traits/skills.yml | 11 ++++++++++ 6 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 Content.Server/Traits/Assorted/LayingDownModifierComponent.cs create mode 100644 Content.Server/Traits/Assorted/LayingDownModifierSystem.cs create mode 100644 Content.Shared/Traits/Assorted/Components/ClimbDelayModifierComponent.cs diff --git a/Content.Server/Traits/Assorted/LayingDownModifierComponent.cs b/Content.Server/Traits/Assorted/LayingDownModifierComponent.cs new file mode 100644 index 00000000000..22660ff4487 --- /dev/null +++ b/Content.Server/Traits/Assorted/LayingDownModifierComponent.cs @@ -0,0 +1,22 @@ +using Robust.Shared.GameStates; + +namespace Content.Server.Traits.Assorted; + +/// +/// This is used for traits that modify values related to the Laying Down system. +/// +[RegisterComponent] +public sealed partial class LayingDownModifierComponent : Component +{ + /// + /// What to multiply the cooldown of laying down and standing up by. + /// + [DataField] + public float LayingDownCooldownMultiplier = 1f; + + /// + /// What to multiply the speed multiplier when lying down by. + /// + [DataField] + public float DownedSpeedMultiplierMultiplier = 1f; +} diff --git a/Content.Server/Traits/Assorted/LayingDownModifierSystem.cs b/Content.Server/Traits/Assorted/LayingDownModifierSystem.cs new file mode 100644 index 00000000000..dc6dcd2de3b --- /dev/null +++ b/Content.Server/Traits/Assorted/LayingDownModifierSystem.cs @@ -0,0 +1,22 @@ +using Content.Server.Traits.Assorted; +using Content.Server.Standing; + +namespace Content.Shared.Traits.Assorted.Systems; + +public sealed class LayingDownModifierSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + } + + private void OnStartup(EntityUid uid, LayingDownModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var layingDown)) + return; + + layingDown.Cooldown *= component.LayingDownCooldownMultiplier; + layingDown.DownedSpeedMultiplier *= component.DownedSpeedMultiplierMultiplier; + } +} diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index 8f6e8046aa4..521f5ace99d 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Physics; using Content.Shared.Popups; using Content.Shared.Stunnable; +using Content.Shared.Traits.Assorted.Components; using Content.Shared.Verbs; using Robust.Shared.Audio.Systems; using Robust.Shared.Physics; @@ -216,7 +217,11 @@ public bool TryClimb( if (ev.Cancelled) return false; - var args = new DoAfterArgs(EntityManager, user, comp.ClimbDelay, new ClimbDoAfterEvent(), + var climbDelay = comp.ClimbDelay; + if (user == entityToMove && TryComp(user, out var delayModifier)) + climbDelay *= delayModifier.ClimbDelayMultiplier; + + var args = new DoAfterArgs(EntityManager, user, climbDelay, new ClimbDoAfterEvent(), entityToMove, target: climbable, used: entityToMove) diff --git a/Content.Shared/Traits/Assorted/Components/ClimbDelayModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/ClimbDelayModifierComponent.cs new file mode 100644 index 00000000000..c04657a4875 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/ClimbDelayModifierComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies climbing speed. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class ClimbDelayModifierComponent : Component +{ + /// + /// What to multiply the climbing delay by. + /// + [DataField, AutoNetworkedField] + public float ClimbDelayMultiplier = 1f; +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 528517684c4..3439ffcdc97 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -84,6 +84,11 @@ trait-description-Voracious = Nothing gets between you and your food. Your endless consumption of food and drinks is twice as fast. +trait-name-ParkourTraining = Parkour Training +trait-description-ParkourTraining = + Whether as a hobby, lifestyle, or professional training, you are trained in the discipline of parkour. + You're faster with climbing, crawling, lying down, and getting up. + trait-name-LightStep = Light Step trait-description-LightStep = You move with a gentle step, making your footsteps quieter. diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index 6d10886e8fa..1a4242aff80 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -87,6 +87,17 @@ foodDelayMultiplier: 0.5 drinkDelayMultiplier: 0.5 +- type: trait + id: ParkourTraining + category: Physical + points: -3 + components: + - type: ClimbDelayModifier + climbDelayMultiplier: 0.70 + - type: LayingDownModifier + layingDownCooldownMultiplier: 0.8 + downedSpeedMultiplierMultiplier: 1.25 + - type: trait id: LightStep category: Auditory From 8400f6c06baef4c34f5c29fdb9754683928c4c7a Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 20:37:26 +0000 Subject: [PATCH 019/135] Automatic Changelog Update (#670) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6263b7d4005..e0226cd7bf7 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5001,3 +5001,11 @@ Entries: Slash or Piercing damage or be a melee weapons generalist. id: 6225 time: '2024-08-06T19:50:20.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add Parkour Training, a 3-point trait that makes you faster with + climbing tables and crawling. + id: 6226 + time: '2024-08-06T20:37:00.0000000+00:00' From 93ece39fc2bb998e3b9c593f2d63b4be5281ef18 Mon Sep 17 00:00:00 2001 From: WarMechanic <69510347+WarMechanic@users.noreply.github.com> Date: Wed, 7 Aug 2024 06:47:49 +1000 Subject: [PATCH 020/135] Cherry-Pick "EMP Grenade Actually Sabotages Power" From Wizden (#516) ## About the PR EMP has been changed to target APC-powered-devices (most electrical devices) as well as batteries to disable them. This means EMP can interfere with autolathes, airlocks, atmos devices, substations and SMES. The power draw of a single EMP grenade now cuts out a substation, and the disabling effect prevents further recharge until it subsides. EMP duration now also stacks, which creates a novel way to quietly black out the station by attacking engineering SMES with 3 EMP grenades (6tc EMP bundle) to black out the station for 3 minutes. Edit, here's a detailed changelog of the PR, Functionality: - EMP disable has been generalised to kill and prevent further function of every device/battery by interrupting recharge - As a result of the above, some hard coded interactions have been culled - EMP disable duration now stacks with multiple EMP blasts - EMP is now capable of draining from gravity generators - The Charger system has been slightly reworked to facilitate communication between batteries and chargers Results: - EMP grenade can disable basically every powered machine, most notably doors - EMP grenade has had its power drain upped to 2.7MW, which is slightly more than a substation and 1/3 a SMES - EMP grenade can now instantly kill substations - EMP grenade can now instantly kill gravity generators - 3 EMP grenades (6tc) can be used to kill SMES and disable recharge for 3 minutes with no evidence on the power monitor. ## Why / Balance EMP at 2tc has a relatively low value-proposition when compared to C4 which is also 2tc. While EMP can probably black out one (or two if you're lucky) APCs and can be used as a defensive option against Stun/Lasers. C4 can be used to cut wires, substations, SMES, generators, doors, reinforced walls, people and the list probably continues. New EMP can be used to soft-bomb station power in an explosion that isn't globally alarming (salv boom). Targeting the captain's office directly may let you crowbar in and steal the locker but it leaves ephemeral evidence in the form of everything electrical shimmering blue. Opting to bomb substations blacks out a wider area, providing several degrees of separation from your target. That is to say, new EMP grenade favours map knowledge and rewards better stealth. ## Technical details - `C.S/.../EmpSystem.cs` uses TryComp to turn on/off charging for `C.S/Power/Components/PowerNetworkBatteryComponent` - `C.S/Power/EntitySystems/PowerReceiverSystem.cs` listens to `EmpPulseEvent` to turn off. Requests to turn back on are additionally intercepted by `EmpSystem.cs` and cancelled. - `C.S/.../GravityGeneratorSystem.cs` listens to `EmpPulseEvent` and converts energy consumption to a normalised charge - `C.S/Power/EntitySystems/ApcSystem.cs` no longer toggles its breaker, but still listens to `EmpPulseEvent` for updating visuals. - `C.S/Power/EntitySystems/ChargerSystem.cs` was refactored to add a `ChargingComponent` flag to power cells instead of `ActiveCharger` on itself. Battery and Charger communicate through this flag. Listens to `EmpPulseEvent` for updating its state machine. New `ChargerUpdateStatusEvent` allows batteries to update the charger's status. - `C.S/Power/EntitySystems/BatterySystem.cs` can now be disabled, and checks for disabling before updating its charge. Raises `ChargerUpdateStatusEvent` when hearing `EmpDisabledRemoved` to tell its charger to start charging again. - `C.S/Power/PowerWireAction.cs` checks for `EmpDisabledComponent` before turning power back on. - `C.S/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs` and `C.S/VendingMachines/VendingMachineSystem.cs` had redundant `EmpPulseEvent` listeners culled. - `Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml` buffed EMP grenade. ## Media https://www.youtube.com/embed/rSVph6OIg1s?si=8o4bx9Vx16B6usuu - outdated video demonstrating changes on a wizden map https://www.youtube.com/embed/B3iPhLcfs-0?si=trB1HY2ccjMf96Bj - electrical anomaly crit with updated emp - [x] I have added screenshots/videos to this PR showcasing its changes ingame, **or** this PR does not require an ingame showcase **Changelog** :cl: - tweak: EMP Grenades can now disable basically any electrical device, and stack in disable duration. --------- Signed-off-by: VMSolidus Co-authored-by: VMSolidus --- .../EntitySystems/GasThermoMachineSystem.cs | 2 +- .../Atmos/Portable/SpaceHeaterSystem.cs | 2 +- .../Unit/EntitySystems/DisposalUnitSystem.cs | 2 +- Content.Server/Emp/EmpSystem.cs | 33 ++-- .../Gravity/GravityGeneratorSystem.cs | 26 +++ .../Components/ActiveChargerComponent.cs | 10 -- .../Power/Components/ChargingComponent.cs | 19 +++ .../Power/EntitySystems/ApcSystem.cs | 19 ++- .../Power/EntitySystems/BatterySystem.cs | 32 +++- .../Power/EntitySystems/ChargerSystem.cs | 149 ++++++++++++++---- .../EntitySystems/PowerReceiverSystem.cs | 38 ++++- Content.Server/Power/PowerWireAction.cs | 4 + .../Systems/SurveillanceCameraSystem.cs | 19 --- .../VendingMachines/VendingMachineSystem.cs | 11 -- .../Objects/Weapons/Throwable/grenades.yml | 2 +- 15 files changed, 273 insertions(+), 95 deletions(-) delete mode 100644 Content.Server/Power/Components/ActiveChargerComponent.cs create mode 100644 Content.Server/Power/Components/ChargingComponent.cs diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs index 9b61044f03e..720fd5b5b91 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs @@ -143,7 +143,7 @@ private bool IsHeater(GasThermoMachineComponent comp) private void OnToggleMessage(EntityUid uid, GasThermoMachineComponent thermoMachine, GasThermomachineToggleMessage args) { - var powerState = _power.TogglePower(uid); + var powerState = _power.TryTogglePower(uid); _adminLogger.Add(LogType.AtmosPowerChanged, $"{ToPrettyString(args.Session.AttachedEntity)} turned {(powerState ? "On" : "Off")} {ToPrettyString(uid)}"); DirtyUI(uid, thermoMachine); } diff --git a/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs b/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs index fff15f696c4..8094b0e1a66 100644 --- a/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs +++ b/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs @@ -98,7 +98,7 @@ private void OnToggle(EntityUid uid, SpaceHeaterComponent spaceHeater, SpaceHeat if (!Resolve(uid, ref powerReceiver)) return; - _power.TogglePower(uid); + _power.TryTogglePower(uid); UpdateAppearance(uid); DirtyUI(uid, spaceHeater); diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index f9403f33b9d..d6647bbf2eb 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -235,7 +235,7 @@ private void OnUiButtonPressed(EntityUid uid, SharedDisposalUnitComponent compon _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(player):player} hit flush button on {ToPrettyString(uid)}, it's now {(component.Engaged ? "on" : "off")}"); break; case SharedDisposalUnitComponent.UiButton.Power: - _power.TogglePower(uid, user: args.Session.AttachedEntity); + _power.TryTogglePower(uid, user: args.Session.AttachedEntity); break; default: throw new ArgumentOutOfRangeException($"{ToPrettyString(player):player} attempted to hit a nonexistant button on {ToPrettyString(uid)}"); diff --git a/Content.Server/Emp/EmpSystem.cs b/Content.Server/Emp/EmpSystem.cs index 7c1a6f9b5db..3a1d2d28196 100644 --- a/Content.Server/Emp/EmpSystem.cs +++ b/Content.Server/Emp/EmpSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Explosion.EntitySystems; +using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.Radio; -using Content.Server.SurveillanceCamera; using Content.Shared.Emp; using Content.Shared.Examine; using Robust.Shared.Map; @@ -22,8 +22,6 @@ public override void Initialize() SubscribeLocalEvent(OnRadioSendAttempt); SubscribeLocalEvent(OnRadioReceiveAttempt); - SubscribeLocalEvent(OnApcToggleMainBreaker); - SubscribeLocalEvent(OnCameraSetActive); } /// @@ -75,7 +73,19 @@ public void DoEmpEffects(EntityUid uid, float energyConsumption, float duration) if (ev.Disabled) { var disabled = EnsureComp(uid); - disabled.DisabledUntil = Timing.CurTime + TimeSpan.FromSeconds(duration); + // couldnt use null-coalescing operator here sadge + if (disabled.DisabledUntil == TimeSpan.Zero) + { + disabled.DisabledUntil = Timing.CurTime; + } + disabled.DisabledUntil = disabled.DisabledUntil + TimeSpan.FromSeconds(duration); + + /// i tried my best to go through the Pow3r server code but i literally couldn't find in relation to PowerNetworkBatteryComponent that uses the event system + /// the code is otherwise too esoteric for my innocent eyes + if (TryComp(uid, out var powerNetBattery)) + { + powerNetBattery.CanCharge = false; + } } } @@ -91,6 +101,11 @@ public override void Update(float frameTime) RemComp(uid); var ev = new EmpDisabledRemoved(); RaiseLocalEvent(uid, ref ev); + + if (TryComp(uid, out var powerNetBattery)) + { + powerNetBattery.CanCharge = true; + } } } } @@ -115,16 +130,6 @@ private void OnRadioReceiveAttempt(EntityUid uid, EmpDisabledComponent component { args.Cancelled = true; } - - private void OnApcToggleMainBreaker(EntityUid uid, EmpDisabledComponent component, ref ApcToggleMainBreakerAttemptEvent args) - { - args.Cancelled = true; - } - - private void OnCameraSetActive(EntityUid uid, EmpDisabledComponent component, ref SurveillanceCameraSetActiveAttemptEvent args) - { - args.Cancelled = true; - } } /// diff --git a/Content.Server/Gravity/GravityGeneratorSystem.cs b/Content.Server/Gravity/GravityGeneratorSystem.cs index b0c4bb56ff3..ec5646457e2 100644 --- a/Content.Server/Gravity/GravityGeneratorSystem.cs +++ b/Content.Server/Gravity/GravityGeneratorSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Administration.Logs; using Content.Server.Audio; using Content.Server.Power.Components; +using Content.Server.Emp; using Content.Shared.Database; using Content.Shared.Gravity; using Content.Shared.Interaction; @@ -28,6 +29,8 @@ public override void Initialize() SubscribeLocalEvent(OnInteractHand); SubscribeLocalEvent( OnSwitchGenerator); + + SubscribeLocalEvent(OnEmpPulse); } private void OnParentChanged(EntityUid uid, GravityGeneratorComponent component, ref EntParentChangedMessage args) @@ -289,5 +292,28 @@ private void OnSwitchGenerator( { SetSwitchedOn(uid, component, args.On, session:args.Session); } + + private void OnEmpPulse(EntityUid uid, GravityGeneratorComponent component, EmpPulseEvent args) + { + /// i really don't think that the gravity generator should use normalised 0-1 charge + /// as opposed to watts charge that every other battery uses + + ApcPowerReceiverComponent? powerReceiver = null; + if (!Resolve(uid, ref powerReceiver, false)) + return; + + var ent = (uid, component, powerReceiver); + + // convert from normalised energy to watts and subtract + float maxEnergy = component.ActivePowerUse / component.ChargeRate; + float currentEnergy = maxEnergy * component.Charge; + currentEnergy = Math.Max(0, currentEnergy - args.EnergyConsumption); + + // apply renormalised energy to charge variable + component.Charge = currentEnergy / maxEnergy; + + // update power state + UpdateState(ent); + } } } diff --git a/Content.Server/Power/Components/ActiveChargerComponent.cs b/Content.Server/Power/Components/ActiveChargerComponent.cs deleted file mode 100644 index f3d863c9e43..00000000000 --- a/Content.Server/Power/Components/ActiveChargerComponent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Content.Shared.Containers.ItemSlots; -using Content.Shared.Power; - -namespace Content.Server.Power.Components -{ - [RegisterComponent] - public sealed partial class ActiveChargerComponent : Component - { - } -} diff --git a/Content.Server/Power/Components/ChargingComponent.cs b/Content.Server/Power/Components/ChargingComponent.cs new file mode 100644 index 00000000000..db7c14f7082 --- /dev/null +++ b/Content.Server/Power/Components/ChargingComponent.cs @@ -0,0 +1,19 @@ +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Power; + +namespace Content.Server.Power.Components +{ + [RegisterComponent] + public sealed partial class ChargingComponent : Component + { + /// + ///References the entity of the charger that is currently powering this battery + /// + public EntityUid ChargerUid; + + /// + ///References the component of the charger that is currently powering this battery + /// + public ChargerComponent ChargerComponent; + } +} diff --git a/Content.Server/Power/EntitySystems/ApcSystem.cs b/Content.Server/Power/EntitySystems/ApcSystem.cs index 95b5d74a945..f345c9e88ea 100644 --- a/Content.Server/Power/EntitySystems/ApcSystem.cs +++ b/Content.Server/Power/EntitySystems/ApcSystem.cs @@ -7,6 +7,7 @@ using Content.Shared.APC; using Content.Shared.Emag.Components; using Content.Shared.Emag.Systems; +using Content.Shared.Emp; using Content.Shared.Popups; using Robust.Server.GameObjects; using Robust.Shared.Audio; @@ -37,6 +38,7 @@ public override void Initialize() SubscribeLocalEvent(OnEmagged); SubscribeLocalEvent(OnEmpPulse); + SubscribeLocalEvent(OnEmpDisabledRemoved); } public override void Update(float deltaTime) @@ -163,7 +165,7 @@ public void UpdateUIState(EntityUid uid, private ApcChargeState CalcChargeState(EntityUid uid, PowerState.Battery battery) { - if (HasComp(uid)) + if (HasComp(uid) || HasComp(uid)) return ApcChargeState.Emag; if (battery.CurrentStorage / battery.Capacity > ApcComponent.HighPowerThreshold) @@ -190,15 +192,16 @@ private ApcExternalPowerState CalcExtPowerState(EntityUid uid, PowerState.Batter return ApcExternalPowerState.Good; } - + private void OnEmpPulse(EntityUid uid, ApcComponent component, ref EmpPulseEvent args) { - if (component.MainBreakerEnabled) - { - args.Affected = true; - args.Disabled = true; - ApcToggleBreaker(uid, component); - } + EnsureComp(uid, out var emp); //event calls before EmpDisabledComponent is added, ensure it to force sprite update + UpdateApcState(uid); + } + + private void OnEmpDisabledRemoved(EntityUid uid, ApcComponent component, ref EmpDisabledRemoved args) + { + UpdateApcState(uid); } } diff --git a/Content.Server/Power/EntitySystems/BatterySystem.cs b/Content.Server/Power/EntitySystems/BatterySystem.cs index 0a0f2068b58..1c5d83b094d 100644 --- a/Content.Server/Power/EntitySystems/BatterySystem.cs +++ b/Content.Server/Power/EntitySystems/BatterySystem.cs @@ -1,5 +1,6 @@ using Content.Server.Cargo.Systems; using Content.Server.Emp; +using Content.Shared.Emp; using Content.Server.Power.Components; using Content.Shared.Examine; using Content.Shared.Rejuvenate; @@ -20,6 +21,7 @@ public override void Initialize() SubscribeLocalEvent(OnBatteryRejuvenate); SubscribeLocalEvent(CalculateBatteryPrice); SubscribeLocalEvent(OnEmpPulse); + SubscribeLocalEvent(OnEmpDisabledRemoved); SubscribeLocalEvent(PreSync); SubscribeLocalEvent(PostSync); @@ -85,7 +87,7 @@ public override void Update(float frameTime) { if (!comp.AutoRecharge) continue; if (batt.IsFullyCharged) continue; - SetCharge(uid, batt.CurrentCharge + comp.AutoRechargeRate * frameTime, batt); + TrySetCharge(uid, batt.CurrentCharge + comp.AutoRechargeRate * frameTime, batt); } } @@ -100,9 +102,21 @@ private void CalculateBatteryPrice(EntityUid uid, BatteryComponent component, re private void OnEmpPulse(EntityUid uid, BatteryComponent component, ref EmpPulseEvent args) { args.Affected = true; + args.Disabled = true; UseCharge(uid, args.EnergyConsumption, component); } + // if a disabled battery is put into a recharged, + // allow the recharger to start recharging again after the disable ends + private void OnEmpDisabledRemoved(EntityUid uid, BatteryComponent component, ref EmpDisabledRemoved args) + { + if (!TryComp(uid, out var charging)) + return; + + var ev = new ChargerUpdateStatusEvent(); + RaiseLocalEvent(charging.ChargerUid, ref ev); + } + public float UseCharge(EntityUid uid, float value, BatteryComponent? battery = null) { if (value <= 0 || !Resolve(uid, ref battery) || battery.CurrentCharge == 0) @@ -157,6 +171,18 @@ public bool TryUseCharge(EntityUid uid, float value, BatteryComponent? battery = return true; } + /// + /// Like SetCharge, but checks for conditions like EmpDisabled before executing + /// + public bool TrySetCharge(EntityUid uid, float value, BatteryComponent? battery = null) + { + if (!Resolve(uid, ref battery, false) || TryComp(uid, out var emp)) + return false; + + SetCharge(uid, value, battery); + return true; + } + /// /// Returns whether the battery is at least 99% charged, basically full. /// @@ -165,6 +191,10 @@ public bool IsFull(EntityUid uid, BatteryComponent? battery = null) if (!Resolve(uid, ref battery)) return false; + // If the battery is full, remove its charging component. + if (TryComp(uid, out _)) + RemComp(uid); + return battery.CurrentCharge / battery.MaxCharge >= 0.99f; } } diff --git a/Content.Server/Power/EntitySystems/ChargerSystem.cs b/Content.Server/Power/EntitySystems/ChargerSystem.cs index db16dfa008e..ae6b024162e 100644 --- a/Content.Server/Power/EntitySystems/ChargerSystem.cs +++ b/Content.Server/Power/EntitySystems/ChargerSystem.cs @@ -1,13 +1,16 @@ using Content.Server.Power.Components; +using Content.Server.Emp; using Content.Server.PowerCell; using Content.Shared.Examine; using Content.Shared.Power; using Content.Shared.PowerCell.Components; +using Content.Shared.Emp; using JetBrains.Annotations; using Robust.Shared.Containers; using System.Diagnostics.CodeAnalysis; using Content.Shared.Storage.Components; using Robust.Server.Containers; +using Content.Shared.Whitelist; namespace Content.Server.Power.EntitySystems; @@ -28,6 +31,11 @@ public override void Initialize() SubscribeLocalEvent(OnInsertAttempt); SubscribeLocalEvent(OnEntityStorageInsertAttempt); SubscribeLocalEvent(OnChargerExamine); + + SubscribeLocalEvent(OnUpdateStatus); + + SubscribeLocalEvent(OnEmpPulse); + SubscribeLocalEvent(OnEmpDisabledRemoved); } private void OnStartup(EntityUid uid, ChargerComponent component, ComponentStartup args) @@ -40,21 +48,58 @@ private void OnChargerExamine(EntityUid uid, ChargerComponent component, Examine args.PushMarkup(Loc.GetString("charger-examine", ("color", "yellow"), ("chargeRate", (int) component.ChargeRate))); } + private void StartChargingBattery(EntityUid uid, ChargerComponent component, EntityUid target) + { + bool charge = true; + + if (HasComp(uid)) + charge = false; + else + if (!TryComp(target, out var battery)) + charge = false; + else + if (Math.Abs(battery.MaxCharge - battery.CurrentCharge) < 0.01) + charge = false; + + // wrap functionality in an if statement instead of returning... + if (charge) + { + var charging = EnsureComp(target); + charging.ChargerUid = uid; + charging.ChargerComponent = component; + } + + // ...so the status always updates (for insertin a power cell) + UpdateStatus(uid, component); + } + + private void StopChargingBattery(EntityUid uid, ChargerComponent component, EntityUid target) + { + if (HasComp(target)) + RemComp(target); + UpdateStatus(uid, component); + } + public override void Update(float frameTime) { - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out _, out var charger, out var containerComp)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var charging)) { - if (!_container.TryGetContainer(uid, charger.SlotId, out var container, containerComp)) + if (!TryComp(charging.ChargerUid, out var chargerComponent)) continue; - if (charger.Status == CellChargerStatus.Empty || charger.Status == CellChargerStatus.Charged || container.ContainedEntities.Count == 0) + if (charging.ChargerComponent.Status == CellChargerStatus.Off || charging.ChargerComponent.Status == CellChargerStatus.Empty) continue; - foreach (var contained in container.ContainedEntities) - { - TransferPower(uid, contained, charger, frameTime); - } + if (HasComp(charging.ChargerUid)) + continue; + + if (!TryComp(uid, out var battery)) + continue; + + if (Math.Abs(battery.MaxCharge - battery.CurrentCharge) < 0.01) + StopChargingBattery(charging.ChargerUid, charging.ChargerComponent, uid); + TransferPower(charging.ChargerUid, uid, charging.ChargerComponent, frameTime); } } @@ -71,7 +116,7 @@ private void OnInserted(EntityUid uid, ChargerComponent component, EntInsertedIn if (args.Container.ID != component.SlotId) return; - UpdateStatus(uid, component); + StartChargingBattery(uid, component, args.Entity); } private void OnRemoved(EntityUid uid, ChargerComponent component, EntRemovedFromContainerMessage args) @@ -79,7 +124,7 @@ private void OnRemoved(EntityUid uid, ChargerComponent component, EntRemovedFrom if (args.Container.ID != component.SlotId) return; - UpdateStatus(uid, component); + StopChargingBattery(uid, component, args.Entity); } /// @@ -112,6 +157,11 @@ private void OnEntityStorageInsertAttempt(EntityUid uid, ChargerComponent compon args.Cancelled = true; } + private void OnUpdateStatus(EntityUid uid, ChargerComponent component, ref ChargerUpdateStatusEvent args) + { + UpdateStatus(uid, component); + } + private void UpdateStatus(EntityUid uid, ChargerComponent component) { var status = GetStatus(uid, component); @@ -126,15 +176,6 @@ private void UpdateStatus(EntityUid uid, ChargerComponent component) component.Status = status; - if (component.Status == CellChargerStatus.Charging) - { - AddComp(uid); - } - else - { - RemComp(uid); - } - switch (component.Status) { case CellChargerStatus.Off: @@ -146,7 +187,7 @@ private void UpdateStatus(EntityUid uid, ChargerComponent component) _appearance.SetData(uid, CellVisual.Light, CellChargerStatus.Empty, appearance); break; case CellChargerStatus.Charging: - receiver.Load = component.ChargeRate; + receiver.Load = component.ChargeRate; //does not scale with multiple slotted batteries _appearance.SetData(uid, CellVisual.Light, CellChargerStatus.Charging, appearance); break; case CellChargerStatus.Charged: @@ -157,6 +198,42 @@ private void UpdateStatus(EntityUid uid, ChargerComponent component) throw new ArgumentOutOfRangeException(); } } + + private void OnEmpPulse(EntityUid uid, ChargerComponent component, ref EmpPulseEvent args) + { + // we don't care if we haven't been disabled + if (!args.Disabled) + return; + + // if the recharger is hit by an emp pulse, + // stop recharging contained batteries to save resources + if (!_container.TryGetContainer(uid, component.SlotId, out var container)) + return; + + foreach (var containedEntity in container.ContainedEntities) + { + if (!SearchForBattery(containedEntity, out _, out _)) + continue; + + StopChargingBattery(uid, component, containedEntity); + } + } + + private void OnEmpDisabledRemoved(EntityUid uid, ChargerComponent component, ref EmpDisabledRemoved args) + { + // if an emp disable subsides, + // attempt to start charging all batteries + if (!_container.TryGetContainer(uid, component.SlotId, out var container)) + return; + + foreach (var containedEntity in container.ContainedEntities) + { + if (!SearchForBattery(containedEntity, out _, out _)) + continue; + + StartChargingBattery(uid, component, containedEntity); + } + } private CellChargerStatus GetStatus(EntityUid uid, ChargerComponent component) { @@ -178,13 +255,28 @@ private CellChargerStatus GetStatus(EntityUid uid, ChargerComponent component) if (container.ContainedEntities.Count == 0) return CellChargerStatus.Empty; - if (!SearchForBattery(container.ContainedEntities[0], out _, out var heldBattery)) - return CellChargerStatus.Off; + var statusOut = CellChargerStatus.Off; - if (Math.Abs(heldBattery.MaxCharge - heldBattery.CurrentCharge) < 0.01) - return CellChargerStatus.Charged; + foreach (var containedEntity in container.ContainedEntities) + { + // if none of the slotted items are actually batteries, represent the charger as off + if (!SearchForBattery(containedEntity, out _, out _)) + continue; - return CellChargerStatus.Charging; + // if all batteries are either EMP'd or fully charged, represent the charger as fully charged + statusOut = CellChargerStatus.Charged; + if (HasComp(containedEntity)) + continue; + + if (!HasComp(containedEntity)) + continue; + + // if we have atleast one battery being charged, represent the charger as charging; + statusOut = CellChargerStatus.Charging; + break; + } + + return statusOut; } private void TransferPower(EntityUid uid, EntityUid targetEntity, ChargerComponent component, float frameTime) @@ -201,11 +293,11 @@ private void TransferPower(EntityUid uid, EntityUid targetEntity, ChargerCompone if (!SearchForBattery(targetEntity, out var batteryUid, out var heldBattery)) return; - _battery.SetCharge(batteryUid.Value, heldBattery.CurrentCharge + component.ChargeRate * frameTime, heldBattery); + _battery.TrySetCharge(batteryUid.Value, heldBattery.CurrentCharge + component.ChargeRate * frameTime, heldBattery); // Just so the sprite won't be set to 99.99999% visibility if (heldBattery.MaxCharge - heldBattery.CurrentCharge < 0.01) { - _battery.SetCharge(batteryUid.Value, heldBattery.MaxCharge, heldBattery); + _battery.TrySetCharge(batteryUid.Value, heldBattery.MaxCharge, heldBattery); } UpdateStatus(uid, component); @@ -223,3 +315,6 @@ private bool SearchForBattery(EntityUid uid, [NotNullWhen(true)] out EntityUid? return true; } } + +[ByRefEvent] +public record struct ChargerUpdateStatusEvent(); \ No newline at end of file diff --git a/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs b/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs index 048fda23553..2157a53a53d 100644 --- a/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Administration.Logs; using Content.Server.Administration.Managers; using Content.Server.Power.Components; +using Content.Server.Emp; using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Examine; @@ -11,6 +12,7 @@ using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Utility; +using Content.Shared.Emp; namespace Content.Server.Power.EntitySystems { @@ -38,6 +40,9 @@ public override void Initialize() SubscribeLocalEvent>(OnGetVerbs); SubscribeLocalEvent>(AddSwitchPowerVerb); + SubscribeLocalEvent(OnEmpPulse); + SubscribeLocalEvent(OnEmpEnd); + _recQuery = GetEntityQuery(); _provQuery = GetEntityQuery(); } @@ -131,7 +136,7 @@ private void AddSwitchPowerVerb(EntityUid uid, PowerSwitchComponent component, G { Act = () => { - TogglePower(uid, user: args.User); + TryTogglePower(uid, user: args.User); }, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png")), Text = Loc.GetString("power-switch-component-toggle-verb"), @@ -192,5 +197,36 @@ public bool TogglePower(EntityUid uid, bool playSwitchSound = true, ApcPowerRece return !receiver.PowerDisabled; // i.e. PowerEnabled } + + public bool TryTogglePower(EntityUid uid, bool playSwitchSound = true, ApcPowerReceiverComponent? receiver = null, EntityUid? user = null) + { + if (HasComp(uid)) + return false; + + return TogglePower(uid, playSwitchSound, receiver, user); + } + + public void SetLoad(ApcPowerReceiverComponent comp, float load) + { + comp.Load = load; + } + + private void OnEmpPulse(EntityUid uid, ApcPowerReceiverComponent component, ref EmpPulseEvent args) + { + if (!component.PowerDisabled) + { + args.Affected = true; + args.Disabled = true; + TogglePower(uid, false); + } + } + + private void OnEmpEnd(EntityUid uid, ApcPowerReceiverComponent component, ref EmpDisabledRemoved args) + { + if (component.PowerDisabled) + { + TogglePower(uid, false); + } + } } } diff --git a/Content.Server/Power/PowerWireAction.cs b/Content.Server/Power/PowerWireAction.cs index 785eac91dba..374c1c41acb 100644 --- a/Content.Server/Power/PowerWireAction.cs +++ b/Content.Server/Power/PowerWireAction.cs @@ -1,6 +1,7 @@ using Content.Server.Electrocution; using Content.Server.Power.Components; using Content.Server.Wires; +using Content.Shared.Emp; using Content.Shared.Power; using Content.Shared.Wires; @@ -78,6 +79,9 @@ private void SetPower(EntityUid owner, bool pulsed) return; } + if (EntityManager.TryGetComponent(owner, out var emp)) + return; + power.PowerDisabled = false; } } diff --git a/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs b/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs index 410ba9f7540..ec3d33157ab 100644 --- a/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs +++ b/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs @@ -1,7 +1,6 @@ using Content.Server.DeviceNetwork; using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Systems; -using Content.Server.Emp; using Content.Server.Power.Components; using Content.Shared.ActionBlocker; using Content.Shared.DeviceNetwork; @@ -59,9 +58,6 @@ public override void Initialize() SubscribeLocalEvent(OnSetName); SubscribeLocalEvent(OnSetNetwork); SubscribeLocalEvent>(AddVerbs); - - SubscribeLocalEvent(OnEmpPulse); - SubscribeLocalEvent(OnEmpDisabledRemoved); } private void OnPacketReceived(EntityUid uid, SurveillanceCameraComponent component, DeviceNetworkPacketEvent args) @@ -400,21 +396,6 @@ private void UpdateVisuals(EntityUid uid, SurveillanceCameraComponent? component _appearance.SetData(uid, SurveillanceCameraVisualsKey.Key, key, appearance); } - - private void OnEmpPulse(EntityUid uid, SurveillanceCameraComponent component, ref EmpPulseEvent args) - { - if (component.Active) - { - args.Affected = true; - args.Disabled = true; - SetActive(uid, false); - } - } - - private void OnEmpDisabledRemoved(EntityUid uid, SurveillanceCameraComponent component, ref EmpDisabledRemoved args) - { - SetActive(uid, true); - } } public sealed class OnSurveillanceCameraViewerAddEvent : EntityEventArgs diff --git a/Content.Server/VendingMachines/VendingMachineSystem.cs b/Content.Server/VendingMachines/VendingMachineSystem.cs index 7c9aed188fe..36fa69313e3 100644 --- a/Content.Server/VendingMachines/VendingMachineSystem.cs +++ b/Content.Server/VendingMachines/VendingMachineSystem.cs @@ -49,7 +49,6 @@ public override void Initialize() SubscribeLocalEvent(OnEmagged); SubscribeLocalEvent(OnDamage); SubscribeLocalEvent(OnVendingPrice); - SubscribeLocalEvent(OnEmpPulse); SubscribeLocalEvent(OnActivatableUIOpenAttempt); @@ -496,15 +495,5 @@ private void OnPriceCalculation(EntityUid uid, VendingMachineRestockComponent co args.Price += priceSets.Max(); } - - private void OnEmpPulse(EntityUid uid, VendingMachineComponent component, ref EmpPulseEvent args) - { - if (!component.Broken && this.IsPowered(uid, EntityManager)) - { - args.Affected = true; - args.Disabled = true; - component.NextEmpEject = _timing.CurTime; - } - } } } diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml index 1cad73e30ea..f25023b4541 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml @@ -314,7 +314,7 @@ sprite: Objects/Weapons/Grenades/empgrenade.rsi - type: EmpOnTrigger range: 4 - energyConsumption: 50000 + energyConsumption: 2700000 - type: DeleteOnTrigger - type: Appearance - type: TimerTriggerVisuals From b6b21da48d04d2ea6ee5d3062da853a5424647c6 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 20:48:10 +0000 Subject: [PATCH 021/135] Automatic Changelog Update (#516) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e0226cd7bf7..c66b99d2ea1 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5009,3 +5009,11 @@ Entries: climbing tables and crawling. id: 6226 time: '2024-08-06T20:37:00.0000000+00:00' +- author: WarMechanic + changes: + - type: Tweak + message: >- + EMP Grenades can now disable basically any electrical device, and stack + in disable duration. + id: 6227 + time: '2024-08-06T20:47:49.0000000+00:00' From 81ad859c46fc48ca3b19e8165454bda5ad52f8f1 Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Wed, 7 Aug 2024 00:22:11 +0300 Subject: [PATCH 022/135] Admeme Language Commands (Attempt 2) (#565) # Description #562 but using commands instead of tricks. Less user-friendly but makes you look like a hacker when you use them :trollface:

Media

![image](https://github.com/user-attachments/assets/818b6226-aea8-4f9a-b30d-5df39b8041e6) ![image](https://github.com/user-attachments/assets/f3c40feb-f84d-4083-bc9a-44f7b1dfb30d) ![image](https://github.com/user-attachments/assets/31827207-4903-4df1-9074-eb060d0cf63c) (ignore the missing locale, I fixes)

# Changelog :cl: - add: Admin tooling: added several admin commands to help manipulate entities' languages. --------- Signed-off-by: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> --- .../Language/Commands/AdminLanguageCommand.cs | 75 +++++++++ .../Commands/AdminTranslatorCommand.cs | 155 ++++++++++++++++++ Resources/Locale/en-US/language/commands.ftl | 18 ++ 3 files changed, 248 insertions(+) create mode 100644 Content.Server/Language/Commands/AdminLanguageCommand.cs create mode 100644 Content.Server/Language/Commands/AdminTranslatorCommand.cs diff --git a/Content.Server/Language/Commands/AdminLanguageCommand.cs b/Content.Server/Language/Commands/AdminLanguageCommand.cs new file mode 100644 index 00000000000..f02d9c7f401 --- /dev/null +++ b/Content.Server/Language/Commands/AdminLanguageCommand.cs @@ -0,0 +1,75 @@ +using Content.Server.Administration; +using Content.Shared.Administration; +using Content.Shared.Language; +using Content.Shared.Language.Components; +using Content.Shared.Language.Systems; +using Robust.Shared.Toolshed; +using Robust.Shared.Toolshed.Syntax; +using Robust.Shared.Toolshed.TypeParsers; + +namespace Content.Server.Language.Commands; + +[ToolshedCommand(Name = "language"), AdminCommand(AdminFlags.Admin)] +public sealed class AdminLanguageCommand : ToolshedCommand +{ + private LanguageSystem? _languagesField; + private LanguageSystem Languages => _languagesField ??= GetSys(); + + [CommandImplementation("add")] + public EntityUid AddLanguage( + [CommandInvocationContext] IInvocationContext ctx, + [PipedArgument] EntityUid input, + [CommandArgument] ValueRef> @ref, + [CommandArgument] bool canSpeak = true, + [CommandArgument] bool canUnderstand = true + ) + { + var language = @ref.Evaluate(ctx)!; + + if (language == SharedLanguageSystem.UniversalPrototype) + { + EnsureComp(input); + Languages.UpdateEntityLanguages(input); + } + else + { + EnsureComp(input); + Languages.AddLanguage(input, language, canSpeak, canUnderstand); + } + + return input; + } + + [CommandImplementation("rm")] + public EntityUid RemoveLanguage( + [CommandInvocationContext] IInvocationContext ctx, + [PipedArgument] EntityUid input, + [CommandArgument] ValueRef> @ref, + [CommandArgument] bool removeSpeak = true, + [CommandArgument] bool removeUnderstand = true + ) + { + var language = @ref.Evaluate(ctx)!; + if (language == SharedLanguageSystem.UniversalPrototype && HasComp(input)) + { + RemComp(input); + EnsureComp(input); + } + // We execute this branch even in case of universal so that it gets removed if it was added manually to the LanguageKnowledge + Languages.RemoveLanguage(input, language, removeSpeak, removeUnderstand); + + return input; + } + + [CommandImplementation("lsspoken")] + public IEnumerable ListSpoken([PipedArgument] EntityUid input) + { + return Languages.GetSpokenLanguages(input); + } + + [CommandImplementation("lsunderstood")] + public IEnumerable ListUnderstood([PipedArgument] EntityUid input) + { + return Languages.GetUnderstoodLanguages(input); + } +} diff --git a/Content.Server/Language/Commands/AdminTranslatorCommand.cs b/Content.Server/Language/Commands/AdminTranslatorCommand.cs new file mode 100644 index 00000000000..8a7984bc36b --- /dev/null +++ b/Content.Server/Language/Commands/AdminTranslatorCommand.cs @@ -0,0 +1,155 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Server.Administration; +using Content.Shared.Administration; +using Content.Shared.Language; +using Content.Shared.Language.Components; +using Content.Shared.Language.Components.Translators; +using Content.Shared.Language.Systems; +using Robust.Server.Containers; +using Robust.Shared.Toolshed; +using Robust.Shared.Toolshed.Syntax; +using Robust.Shared.Toolshed.TypeParsers; + +namespace Content.Server.Language.Commands; + +[ToolshedCommand(Name = "translator"), AdminCommand(AdminFlags.Admin)] +public sealed class AdminTranslatorCommand : ToolshedCommand +{ + private LanguageSystem? _languagesField; + private ContainerSystem? _containersField; + + private ContainerSystem Containers => _containersField ??= GetSys(); + private LanguageSystem Languages => _languagesField ??= GetSys(); + + [CommandImplementation("addlang")] + public EntityUid AddLanguage( + [CommandInvocationContext] IInvocationContext ctx, + [PipedArgument] EntityUid input, + [CommandArgument] ValueRef> @ref, + [CommandArgument] bool addSpeak = true, + [CommandArgument] bool addUnderstand = true + ) + { + var language = @ref.Evaluate(ctx)!; + // noob trap - needs a universallanguagespeakercomponent + if (language == SharedLanguageSystem.UniversalPrototype) + throw new ArgumentException(Loc.GetString("command-language-error-this-will-not-work")); + + if (!TryGetTranslatorComp(input, out var translator)) + throw new ArgumentException(Loc.GetString("command-language-error-not-a-translator", ("entity", input))); + + if (addSpeak && !translator.SpokenLanguages.Contains(language)) + translator.SpokenLanguages.Add(language); + if (addUnderstand && !translator.UnderstoodLanguages.Contains(language)) + translator.UnderstoodLanguages.Add(language); + + UpdateTranslatorHolder(input); + + return input; + } + + [CommandImplementation("rmlang")] + public EntityUid RemoveLanguage( + [CommandInvocationContext] IInvocationContext ctx, + [PipedArgument] EntityUid input, + [CommandArgument] ValueRef> @ref, + [CommandArgument] bool removeSpeak = true, + [CommandArgument] bool removeUnderstand = true + ) + { + var language = @ref.Evaluate(ctx)!; + if (!TryGetTranslatorComp(input, out var translator)) + throw new ArgumentException(Loc.GetString("command-language-error-not-a-translator", ("entity", input))); + + if (removeSpeak) + translator.SpokenLanguages.Remove(language); + if (removeUnderstand) + translator.UnderstoodLanguages.Remove(language); + + UpdateTranslatorHolder(input); + + return input; + } + + [CommandImplementation("addrequired")] + public EntityUid AddRequiredLanguage( + [CommandInvocationContext] IInvocationContext ctx, + [PipedArgument] EntityUid input, + [CommandArgument] ValueRef> @ref) + { + var language = @ref.Evaluate(ctx)!; + if (!TryGetTranslatorComp(input, out var translator)) + throw new ArgumentException(Loc.GetString("command-language-error-not-a-translator", ("entity", input))); + + if (!translator.RequiredLanguages.Contains(language)) + { + translator.RequiredLanguages.Add(language); + UpdateTranslatorHolder(input); + } + + return input; + } + + [CommandImplementation("rmrequired")] + public EntityUid RemoveRequiredLanguage( + [CommandInvocationContext] IInvocationContext ctx, + [PipedArgument] EntityUid input, + [CommandArgument] ValueRef> @ref) + { + var language = @ref.Evaluate(ctx)!; + if (!TryGetTranslatorComp(input, out var translator)) + throw new ArgumentException(Loc.GetString("command-language-error-not-a-translator", ("entity", input))); + + if (translator.RequiredLanguages.Remove(language)) + UpdateTranslatorHolder(input); + + return input; + } + + [CommandImplementation("lsspoken")] + public IEnumerable ListSpoken([PipedArgument] EntityUid input) + { + if (!TryGetTranslatorComp(input, out var translator)) + return []; + return translator.SpokenLanguages; + } + + [CommandImplementation("lsunderstood")] + public IEnumerable ListUnderstood([PipedArgument] EntityUid input) + { + if (!TryGetTranslatorComp(input, out var translator)) + return []; + return translator.UnderstoodLanguages; + } + + [CommandImplementation("lsrequired")] + public IEnumerable ListRequired([PipedArgument] EntityUid input) + { + if (!TryGetTranslatorComp(input, out var translator)) + return []; + return translator.RequiredLanguages; + } + + private bool TryGetTranslatorComp(EntityUid uid, [NotNullWhen(true)] out BaseTranslatorComponent? translator) + { + if (TryComp(uid, out var handheld)) + translator = handheld; + else if (TryComp(uid, out var implant)) + translator = implant; + else if (TryComp(uid, out var intrinsic)) + translator = intrinsic; + else + translator = null; + + return translator != null; + } + + private void UpdateTranslatorHolder(EntityUid translator) + { + if (!Containers.TryGetContainingContainer(translator, out var cont) + || cont.Owner is not { Valid: true } holder) + return; + + Languages.UpdateEntityLanguages(holder); + } +} diff --git a/Resources/Locale/en-US/language/commands.ftl b/Resources/Locale/en-US/language/commands.ftl index ba2b3160094..65959e3f28f 100644 --- a/Resources/Locale/en-US/language/commands.ftl +++ b/Resources/Locale/en-US/language/commands.ftl @@ -14,3 +14,21 @@ command-language-entry = {$id}. {$language} - {$name} command-language-invalid-number = The language number must be between 0 and {$total}. Alternatively, use the language name. command-language-invalid-language = The language {$id} does not exist or you cannot speak it. + +# toolshed + +command-description-language-add = Adds a new language to the piped entity. The two last arguments indicate whether it should be spoken/understood. Example: 'self language:add "Canilunzt" true true' +command-description-language-rm = Removes a language from the piped entity. Works similarly to language:add. Example: 'self language:rm "GalacticCommon" true true'. +command-description-language-lsspoken = Lists all languages the entity can speak. Example: 'self language:lsspoken' +command-description-language-lsunderstood = Lists all languages the entity can understand. Example: 'self language:lssunderstood' + +command-description-translator-addlang = Adds a new target language to the piped translator entity. See language:add for details. +command-description-translator-rmlang = Removes a target language from the piped translator entity. See language:rm for details. +command-description-translator-addrequired = Adds a new required language to the piped translator entity. Example: 'ent 1234 translator:addrequired "GalacticCommon"' +command-description-translator-rmrequired = Removes a required language from the piped translator entity. Example: 'ent 1234 translator:rmrequired "GalacticCommon"' +command-description-translator-lsspoken = Lists all spoken languages for the piped translator entity. Example: 'ent 1234 translator:lsspoken' +command-description-translator-lsunderstood = Lists all understood languages for the piped translator entity. Example: 'ent 1234 translator:lssunderstood' +command-description-translator-lsrequired = Lists all required languages for the piped translator entity. Example: 'ent 1234 translator:lsrequired' + +command-language-error-this-will-not-work = This will not work. +command-language-error-not-a-translator = Entity {$entity} is not a translator. From 48c0770ff49c622491ded7ae9591e77842304e8b Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 21:22:38 +0000 Subject: [PATCH 023/135] Automatic Changelog Update (#565) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index c66b99d2ea1..e3de08a18b0 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5017,3 +5017,11 @@ Entries: in disable duration. id: 6227 time: '2024-08-06T20:47:49.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Add + message: >- + Admin tooling: added several admin commands to help manipulate entities' + languages. + id: 6228 + time: '2024-08-06T21:22:11.0000000+00:00' From 04d01f687fb479d7f86e2df81cce6b9285dcbad6 Mon Sep 17 00:00:00 2001 From: SleepyScarecrow <136123749+SleepyScarecrow@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:51:21 -0400 Subject: [PATCH 024/135] Added Penlights (#567) # Description Added in penlights that spawn in Medical Staff PDAs. --- # TODO - [x] EyeCheck system - [x] Add in the bloody pens. ---

Media

https://github.com/user-attachments/assets/dc746aa2-782e-4d86-b9ef-9e012343fb87

--- # Changelog :cl: Tilkku - add: Added Pen Lights - add: Eye Examination --------- Signed-off-by: SleepyScarecrow <136123749+SleepyScarecrow@users.noreply.github.com> Co-authored-by: VMSolidus --- .../PenLight/UI/PenLightBoundUserInterface.cs | 47 +++++++ .../Eye/PenLight/UI/PenLightWindow.xaml | 11 ++ .../Eye/PenLight/UI/PenLightWindow.xaml.cs | 78 ++++++++++++ .../EyeProtection/EyeProtectionSystem.cs | 2 +- Content.Server/Medical/PenLightSystem.cs | 118 ++++++++++++++++++ Content.Shared/Medical/PenLightComponent.cs | 33 +++++ Content.Shared/Medical/PenLightUiKey.cs | 9 ++ Content.Shared/Medical/PenLightUserMessage.cs | 24 ++++ .../en-US/medical/components/penlight.ftl | 11 ++ .../Entities/Objects/Devices/pda.yml | 54 ++++++++ .../Entities/Objects/Tools/penlight.yml | 90 +++++++++++++ .../Objects/Tools/cmopenlight.rsi/meta.json | 17 +++ .../Tools/cmopenlight.rsi/world-on.png | Bin 0 -> 4345 bytes .../Objects/Tools/cmopenlight.rsi/world.png | Bin 0 -> 4325 bytes .../Objects/Tools/penlight.rsi/meta.json | 17 +++ .../Objects/Tools/penlight.rsi/world-on.png | Bin 0 -> 253 bytes .../Objects/Tools/penlight.rsi/world.png | Bin 0 -> 234 bytes 17 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 Content.Client/Eye/PenLight/UI/PenLightBoundUserInterface.cs create mode 100644 Content.Client/Eye/PenLight/UI/PenLightWindow.xaml create mode 100644 Content.Client/Eye/PenLight/UI/PenLightWindow.xaml.cs create mode 100644 Content.Server/Medical/PenLightSystem.cs create mode 100644 Content.Shared/Medical/PenLightComponent.cs create mode 100644 Content.Shared/Medical/PenLightUiKey.cs create mode 100644 Content.Shared/Medical/PenLightUserMessage.cs create mode 100644 Resources/Locale/en-US/medical/components/penlight.ftl create mode 100644 Resources/Prototypes/Entities/Objects/Tools/penlight.yml create mode 100644 Resources/Textures/Objects/Tools/cmopenlight.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tools/cmopenlight.rsi/world-on.png create mode 100644 Resources/Textures/Objects/Tools/cmopenlight.rsi/world.png create mode 100644 Resources/Textures/Objects/Tools/penlight.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tools/penlight.rsi/world-on.png create mode 100644 Resources/Textures/Objects/Tools/penlight.rsi/world.png diff --git a/Content.Client/Eye/PenLight/UI/PenLightBoundUserInterface.cs b/Content.Client/Eye/PenLight/UI/PenLightBoundUserInterface.cs new file mode 100644 index 00000000000..c4887531151 --- /dev/null +++ b/Content.Client/Eye/PenLight/UI/PenLightBoundUserInterface.cs @@ -0,0 +1,47 @@ +using Content.Shared.Medical; +using JetBrains.Annotations; +using Robust.Client.GameObjects; + +namespace Content.Client.Eye.PenLight.UI +{ + [UsedImplicitly] + public sealed class PenLightBoundUserInterface : BoundUserInterface + { + [ViewVariables] + private PenLightWindow? _window; + + public PenLightBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } + + protected override void Open() + { + base.Open(); + _window = new PenLightWindow + { + Title = EntMan.GetComponent(Owner).EntityName, + }; + _window.OnClose += Close; + _window.OpenCentered(); + } + + protected override void ReceiveMessage(BoundUserInterfaceMessage message) + { + if (_window == null + || message is not PenLightUserMessage cast) + return; + + _window.Diagnose(cast); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_window != null) + _window.OnClose -= Close; + + _window?.Dispose(); + } + } +} diff --git a/Content.Client/Eye/PenLight/UI/PenLightWindow.xaml b/Content.Client/Eye/PenLight/UI/PenLightWindow.xaml new file mode 100644 index 00000000000..149b8a13828 --- /dev/null +++ b/Content.Client/Eye/PenLight/UI/PenLightWindow.xaml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/Content.Client/Eye/PenLight/UI/PenLightWindow.xaml.cs b/Content.Client/Eye/PenLight/UI/PenLightWindow.xaml.cs new file mode 100644 index 00000000000..809a569fa47 --- /dev/null +++ b/Content.Client/Eye/PenLight/UI/PenLightWindow.xaml.cs @@ -0,0 +1,78 @@ +using Content.Client.UserInterface.Controls; +using Content.Shared.Damage; +using Content.Shared.IdentityManagement; +using Content.Shared.Medical; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.XAML; +using System.Text; + + +namespace Content.Client.Eye.PenLight.UI +{ + [GenerateTypedNameReferences] + public sealed partial class PenLightWindow : FancyWindow + { + private readonly IEntityManager _entityManager; + private const int LightHeight = 150; + private const int LightWidth = 900; + + public PenLightWindow() + { + RobustXamlLoader.Load(this); + + var dependencies = IoCManager.Instance!; + _entityManager = dependencies.Resolve(); + } + public void Diagnose(PenLightUserMessage msg) + { + var target = _entityManager.GetEntity(msg.TargetEntity); + + if (target == null || !_entityManager.TryGetComponent(target, out var damageable)) + { + NoPatientDataText.Visible = true; + ExamDataLabel.Text = string.Empty; + return; + } + + NoPatientDataText.Visible = false; + + + string entityName = Loc.GetString("pen-light-window-entity-unknown-text"); + if (_entityManager.HasComponent(target.Value)) + entityName = Identity.Name(target.Value, _entityManager); + + var sb = new StringBuilder(); + sb.AppendLine(Loc.GetString("pen-light-window-entity-eyes-text", ("entityName", entityName))); + + // Check if Blind and return early if true + if (msg.Blind == true) + { + sb.AppendLine(Loc.GetString("pen-light-exam-blind-text")); + ExamDataLabel.Text = sb.ToString(); + SetHeight = LightHeight; + SetWidth = LightWidth; + return; + } + // EyeDamage + if (msg.EyeDamage == true) + sb.AppendLine(Loc.GetString("pen-light-exam-eyedamage-text")); + + // Drunk + if (msg.Drunk == true) + sb.AppendLine(Loc.GetString("pen-light-exam-drunk-text")); + + // Hallucinating + if (msg.SeeingRainbows == true) + sb.AppendLine(Loc.GetString("pen-light-exam-hallucinating-text")); + + // Healthy + if (msg.Healthy == true) + sb.AppendLine(Loc.GetString("pen-light-exam-healthy-text")); + + ExamDataLabel.Text = sb.ToString(); + + SetHeight = LightHeight; + SetWidth = LightWidth; + } + } +} \ No newline at end of file diff --git a/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs b/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs index 2d54c03b51b..744483cfb82 100644 --- a/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs +++ b/Content.Server/Eye/Blinding/EyeProtection/EyeProtectionSystem.cs @@ -11,7 +11,7 @@ public sealed class EyeProtectionSystem : EntitySystem { [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!; [Dependency] private readonly BlindableSystem _blindingSystem = default!; - + public override void Initialize() { base.Initialize(); diff --git a/Content.Server/Medical/PenLightSystem.cs b/Content.Server/Medical/PenLightSystem.cs new file mode 100644 index 00000000000..f48a84d0476 --- /dev/null +++ b/Content.Server/Medical/PenLightSystem.cs @@ -0,0 +1,118 @@ +using Content.Server.DoAfter; +using Content.Server.PowerCell; +using Content.Shared.Damage; +using Content.Shared.DoAfter; +using Content.Shared.Drugs; +using Content.Shared.Drunk; +using Content.Shared.Eye.Blinding.Components; +using Content.Shared.Interaction; +using Content.Shared.Medical; +using Content.Shared.Mobs.Systems; +using Content.Shared.Traits.Assorted.Components; +using Robust.Server.GameObjects; +using Robust.Shared.Player; +using Robust.Shared.Timing; + +namespace Content.Server.Medical; +/// +/// This stores the eye exam system for +/// +public sealed class PenLightSystem : EntitySystem +{ + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly PowerCellSystem _powerCell = default!; + [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; + /// + public override void Initialize() + { + SubscribeLocalEvent(OnAfterInteract); + SubscribeLocalEvent(OnDoAfter); + } + + private void OnAfterInteract(EntityUid uid, PenLightComponent component, AfterInteractEvent args) + { + if (args.Handled + || args.Target is not { } target) + return; + + args.Handled = TryStartExam(uid, target, args.User, component); + } + + private void OnDoAfter(Entity uid, ref PenLightDoAfterEvent args) + { + if (args.Handled + || args.Cancelled + || args.Target == null + || !_powerCell.HasDrawCharge(uid, user: args.User)) + return; + + OpenUserInterface(args.User, uid); + Diagnose(uid, args.Target.Value); + args.Handled = true; + } + + + /// + /// Actually handles the exam interaction. + /// + public bool TryStartExam(EntityUid uid, EntityUid target, EntityUid user, PenLightComponent? component = null) + { + if (!Resolve(uid, ref component)) + return false; + + return _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.ExamSpeed, new PenLightDoAfterEvent(), + uid, target, uid) + { + BlockDuplicate = true, + BreakOnUserMove = true, + BreakOnTargetMove = true, + BreakOnHandChange = true, + NeedHand = true + }); + } + private void OpenUserInterface(EntityUid user, EntityUid penlight) + { + if (!TryComp(user, out var actor) + || !_uiSystem.TryGetUi(penlight, PenLightUiKey.Key, out var ui)) + return; + + _uiSystem.OpenUi(ui, actor.PlayerSession); + } + + /// + /// Runs the checks for the different types of eye damage + /// + private void Diagnose(EntityUid penlight, EntityUid target) + { + if (!_uiSystem.TryGetUi(penlight, PenLightUiKey.Key, out var ui) + || !HasComp(target)) + return; + // Blind + var blind = _entityManager.HasComponent(target); + + // Drunk + var drunk = _entityManager.HasComponent(target); + + // EyeDamage + var eyeDamage = false; + if (TryComp(target, out var eyeDam)) + { + eyeDamage = eyeDam.EyeDamage > 0 && eyeDam.EyeDamage < 6; //6 means perma-blind + } + + // Hallucinating + var seeingRainbows = _entityManager.HasComponent(target); + + // Healthy + var healthy = !(blind || drunk || eyeDamage || seeingRainbows); + + _uiSystem.SendUiMessage(ui, new PenLightUserMessage(GetNetEntity(target), + blind, + drunk, + eyeDamage, + healthy, + seeingRainbows + )); + } +} diff --git a/Content.Shared/Medical/PenLightComponent.cs b/Content.Shared/Medical/PenLightComponent.cs new file mode 100644 index 00000000000..50dacae3dc8 --- /dev/null +++ b/Content.Shared/Medical/PenLightComponent.cs @@ -0,0 +1,33 @@ +using Content.Shared.DoAfter; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; +namespace Content.Shared.Medical; + +/// +/// This for penlights; a tool used to check for eye damage. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause] +public sealed partial class PenLightComponent : Component +{ + /// + /// Cooldown Time, exams take a bit + /// + [AutoPausedField] + public TimeSpan? NextExamTime; + + /// + /// The min time between exams + /// + [DataField] + public TimeSpan ExamDelay = TimeSpan.FromSeconds(3); + + /// + /// How long the doafter for the exam takes + /// + [DataField(required: true)] + public float ExamSpeed { get; set; } + +} + +[Serializable, NetSerializable] +public sealed partial class PenLightDoAfterEvent : SimpleDoAfterEvent { } \ No newline at end of file diff --git a/Content.Shared/Medical/PenLightUiKey.cs b/Content.Shared/Medical/PenLightUiKey.cs new file mode 100644 index 00000000000..52fc6ce3401 --- /dev/null +++ b/Content.Shared/Medical/PenLightUiKey.cs @@ -0,0 +1,9 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Medical; + +[Serializable, NetSerializable] +public enum PenLightUiKey : byte +{ + Key +} diff --git a/Content.Shared/Medical/PenLightUserMessage.cs b/Content.Shared/Medical/PenLightUserMessage.cs new file mode 100644 index 00000000000..42502b2171b --- /dev/null +++ b/Content.Shared/Medical/PenLightUserMessage.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Medical; +[Serializable, NetSerializable] +public sealed class PenLightUserMessage : BoundUserInterfaceMessage +{ + public readonly NetEntity? TargetEntity; + public bool? Blind; + public bool? Drunk; + public bool? EyeDamage; + public bool? Healthy; + public bool? SeeingRainbows; + + public PenLightUserMessage(NetEntity? targetEntity, bool? blind, bool? drunk, bool? eyeDamage, bool? healthy, bool? seeingRainbows) + { + TargetEntity = targetEntity; + Blind = blind; + Drunk = drunk; + EyeDamage = eyeDamage; + Healthy = healthy; + SeeingRainbows = seeingRainbows; + } +} + diff --git a/Resources/Locale/en-US/medical/components/penlight.ftl b/Resources/Locale/en-US/medical/components/penlight.ftl new file mode 100644 index 00000000000..f0639ad7381 --- /dev/null +++ b/Resources/Locale/en-US/medical/components/penlight.ftl @@ -0,0 +1,11 @@ +penlight-off = The pen light is off. +pen-light-exam-title = Pen Light +pen-light-window-entity-eyes-text = {$entityName}'s conditions: +pen-light-window-no-patient-data-text = No patient data. +pen-light-window-entity-unknown-text = unknown + +pen-light-exam-blind-text = The patient's eyes are glassy and unfocused. They can't follow the light at all. +pen-light-exam-drunk-text = The patient's eyes are slow to follow the light, droopy. +pen-light-exam-eyedamage-text = The patient's eyes are partially focused, though they struggle to look at the light for too long. +pen-light-exam-hallucinating-text = The patient's eyes are wandering around, with dilated pupils. They don't focus on the light. +pen-light-exam-healthy-text = The patient follows the light perfectly with no stuttering. \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index 0f68afefe69..2c28f60da58 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -151,6 +151,12 @@ - type: Pda id: MedicalInternIDCard state: pda-internmed + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#717059" accentVColor: "#447987" @@ -534,6 +540,12 @@ - type: Pda id: CMOIDCard state: pda-cmo + penSlot: # Fancy Pen Light + startingItem: CMOPenLight + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#d7d7d0" accentHColor: "#447987" @@ -550,6 +562,12 @@ - type: Pda id: MedicalIDCard state: pda-medical + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#d7d7d0" accentVColor: "#447987" @@ -568,6 +586,12 @@ - type: Pda id: ParamedicIDCard state: pda-paramedic + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#d7d7d0" accentVColor: "#2a4b5b" @@ -583,6 +607,12 @@ - type: Pda id: ChemistIDCard state: pda-chemistry + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#d7d7d0" accentVColor: "#B34200" @@ -917,6 +947,12 @@ - type: Pda id: PsychologistIDCard state: pda-medical + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#d7d7d0" accentVColor: "#447987" @@ -1002,6 +1038,12 @@ - type: Pda id: BrigmedicIDCard state: pda-brigmedic + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#A32D26" accentHColor: "#d7d7d0" @@ -1079,6 +1121,12 @@ - type: Pda id: SeniorPhysicianIDCard state: pda-seniorphysician + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#d7d7d0" accentHColor: "#447987" @@ -1129,6 +1177,12 @@ - type: Pda id: SyndicateIDCard state: pda-syndi-agent + penSlot: # Pen Lights + startingItem: PenLightBase + priority: -1 + whitelist: + tags: + - Write - type: PdaBorderColor borderColor: "#891417" - type: Icon diff --git a/Resources/Prototypes/Entities/Objects/Tools/penlight.yml b/Resources/Prototypes/Entities/Objects/Tools/penlight.yml new file mode 100644 index 00000000000..7f8a9b262c0 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Tools/penlight.yml @@ -0,0 +1,90 @@ +- type: entity + name: Pen Light + parent: Pen + id: PenLightBase + description: A pen-sized light, used by medical staff. + components: + - type: HandheldLight + addPrefix: false + - type: Sprite + sprite: Objects/Tools/penlight.rsi + layers: + - state: world + - state: world-on + shader: unshaded + visible: false + map: [ "light" ] + - type: Item + sprite: Objects/Tools/penlight.rsi + heldPrefix: off + - type: PointLight + enabled: false + mask: /Textures/Effects/LightMasks/cone.png + autoRot: true + radius: 2 + netsync: false + - type: PenLight + examSpeed: 3 #time in seconds + - type: Appearance + - type: UserInterface + interfaces: + - key: enum.PenLightUiKey.Key + type: PenLightBoundUserInterface + - type: ToggleableLightVisuals + - type: ContainerContainer + containers: + cell_slot: !type:ContainerSlot {} + - type: PowerCellSlot + cellSlotId: cell_slot + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellSmall + - type: Tag + tags: + - Flashlight + - Write + - Pen + +- type: entity + name: Chief Medical Officer's Pen Light + parent: PenLightBase + id: CMOPenLight + description: A pen-sized light, this one belonging to the Chief Medical Officer. When you get promoted you get a better pen. + components: + - type: HandheldLight + addPrefix: false + - type: Sprite + sprite: Objects/Tools/cmopenlight.rsi + layers: + - state: world + - state: world-on + shader: unshaded + visible: false + map: [ "light" ] + - type: Item + sprite: Objects/Tools/cmopenlight.rsi + heldPrefix: off + - type: PointLight + enabled: false + mask: /Textures/Effects/LightMasks/cone.png + autoRot: true + radius: 2 + netsync: false + - type: PenLight + examSpeed: 1.5 #time in seconds + - type: Appearance + - type: ToggleableLightVisuals + - type: PowerCellSlot + cellSlotId: cell_slot + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellSmall + - type: Tag + tags: + - Flashlight + - Write + - Pen diff --git a/Resources/Textures/Objects/Tools/cmopenlight.rsi/meta.json b/Resources/Textures/Objects/Tools/cmopenlight.rsi/meta.json new file mode 100644 index 00000000000..8f4b8ba253f --- /dev/null +++ b/Resources/Textures/Objects/Tools/cmopenlight.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "MistakeNot4892, https://github.com/NebulaSS13/Nebula/blob/dev/icons/obj/lighting/penlight.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "world" + }, + { + "name": "world-on" + } + ] +} diff --git a/Resources/Textures/Objects/Tools/cmopenlight.rsi/world-on.png b/Resources/Textures/Objects/Tools/cmopenlight.rsi/world-on.png new file mode 100644 index 0000000000000000000000000000000000000000..fbd87cad2035e7c2b6594b9c55a43c83c01d4fcc GIT binary patch literal 4345 zcmeHKe^3*577r*1Mew9rZ7sc9mSUCOCfUt~BpU)^KoV<^gIK}C(ar8RVTEMl?n(lR zR;4W-Erk}!w8vcQ&3U~tcic&>cPF)qq{X(LKZ>UwwXI{h+Up6_AJgic+WT(8&$-Ur zFmwHn%p|+}eth10pYMBbvbziN^Ah3~#wiqv1iLM#5MB}a8>@uBVs-TmcpCC2a?`rU(KVEces%1+ zy+3n!O?5mw5ZY`1>)P%k@4wuY8r_hY5`EIxw5#)9AFfh0{Vuoih1No5+wf<}7uWpp zw{5ip4}^r&X6yQGwU?3?Hau0YuO(|2n|CCiy7SY5)%~|-eV|-Z_X>IR-uAx43+288 zhu%DIZoa8)ihabJxi0`SzojlZ9xZ-OO1P|64ia1n$zZYFXJBF|K$eZ9}7s% zR#=)8b8hFZAJwl`E%2;+s5B<~s~Mrcb=yzpuDHFvuq^Sj?oC;re7xntp&7OAme<`U zlV08UVpD$ToziWqho<4VdBr7#btiZCCLBbrrkn$4b(x|?}m z@a#Pow<|mLHyl1Y)177KrTt$d&goaGJIpV?r79g#SXUinZ4CpjEtyw;_DJpp3Is3!tbv z-^o;$GbR?z%8bhhQV_rkBpL~ND|{jqw4h;J3f{|N4T^+Kq;d;d>?lC2yZ{hVO{%q6 zZjh@a(9Ad_Ltx!hVb1aq2>4_{%OuH9X*7XAKpoJjdBLN>O(v5@OK1oJgBF-r<&)?j z<`Yw7hzLdw5E+5r2{q{Bhz&>=EAisrlU^@PVeGHJHAh?=? zIJ91;WoUxL7%gGMNJF|Cqto?9%*E>UxX#VecselwVwJ$buB0m_W+g+h5Q-&rgwBBL zFhI~Qj5IO^%*3z&BN!t|695Ll^(g^8$AvL5%!{tifh%nh(b7%=bP%S}HS_6ffoVbqC z8z?P-X`y6-J7v zCFAMt`oGZ?H~umOeDEJo0KO{KoVj}wzGf+1kLBekq7+U=*_Chayay%s_-!SkLNPle zf1_F+o&6vbswBH3SM`NzZlWpLoJ@QRMSJWy+0Npg!87|3qVf2cQ^PYhhT@%PR6nmx zZ0y|eMpSEs|Gs){)Xr-meSG)KSCpq!`JIio9}c{D4df}?#1pG+?JL{K?OWfU<8X+r zZ`kUNKljMWMNQ5n$-<}oH--+#Vp4a=iCFon|43Cvb(FdXD`}5hgkV=$Ay7Gb?WIu-S7Tv z-lkUHYx7ssH*9XdQ_!FPFXQSwI?wlf{Azlz^WF~0zWYys!JHQubxnPW=H5%+B0ps@(mL0&d>W*GCIBrY&x*`vAMTbqa!{wM!01 zmD}MMNeL!$VAEc^t7nPfWJC2Iu>IH#^sjq<%hu`cUH4Ss?Czz~qNCRvBY)2`OD=D{ zA@f4pmY;S!q|5U^l3$-$_RoyokGkDw%a`A2@HWl7(!H+qvrjjC@@7W6xc_DGjNvzr zKE1cH_hkKJ4^4Xmdz{Rop4ij7!v0*{>9>@PpZ4@!I5y|Z&601vm{XNAKVu^{XgII$ zh;509=g-*&aw}@bj0uI;wve@{-fPI)3r%z6CQbX0FkHe7EG)8y{w0 z-kf#hXlK`lQ^ZoYtRB5KbH=4CgVbI zSsRjXY&uYa)Lnn{+bpYf%G=AIdb5A9|9JmrckSo<2Xx)JL^K*TMomUJ;wLDZ%|?(kLDM+2z?JnOm5bpa zr9gui#&80Kk4Rxvl0&G5$@%1F)sA6MkB-C_40}AI@F6A10_1~;abbcol0+~_q)IZ!D2_(`Hcmf1K5Sl7*RchRl6>d+} zsE0;@UkZj3UXbi@mZ~I|dwDNdZr_48N;kli5Ok1B7 zWL^^3#A6W!NWhqUxXs7WxY<%D=*;+*6K8`ozqEF;`K#L|b;8P%0MkH93Tp%?n4N8Def?ySVw2#4oATqew zW+HLU!Z0|`7cq=rrh#ZPC!hqLT_#6@9NbPR$oT;g4*3%bjc~TC%5BGJBRM9i3UI0j z9bgYgAwiBRW2zb{2&z?1q0u&mh3PpZ{k9J0Ov=tU`OQAcN7C7l2+10n{gj$wc%zT&*3(+g~KTy%~=I2Z!wYLcyvV; z)hHJMWq!ybh_fDuIX}TGI~pX`ei8E<#v|U)b{X=b249SoVBxU)spm=77#-XtA25J^9lUW z!GdR9t3EmV(W!R~`v$vi^;c|7%Z~53d2?vzy!(b^l^XI-J9WGCa%bbSr^v8&Mfx(X zZ!gQu&*@+WKNUr?& ZbY#lxhAUee&Y=iA+~t+dBTF0G{tH1$57+h>xLAI(1#IcCj#wmJ%lA!R zfkWhagFx-!tRp(}zWvft;wY58@aaf^VwSC9qr|!vT^6?E!dgpbC}{BCo_YP(w^d)6 xKCyJ|-daCD%h;*o-eh|w1x{uI24;f>?lqg@zvaAKupj7j22WQ%mvv4FO#sKoSf2m@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/penlight.rsi/world.png b/Resources/Textures/Objects/Tools/penlight.rsi/world.png new file mode 100644 index 0000000000000000000000000000000000000000..4cf616bf959f0b7b8905868edf5cdb484cb863b5 GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C^*N{ z#WAE}&fBX8c^edXSOa|K9C;YSXuiRx*JR<5f=x>sXZ(qq()`n3vy{J^8>pV)L41Su zu`}UbnX~yS+CT3Vclyd|VKRM{xA>9thCMsiq_Vz5j0Rj>jF-*<-@ zeTmsegyx;!rmfae$yf39$OVO0)rXoS=C#;1d0!URTO1)UE&c94)>?lbc8(;?10eS^ ZFz`# Date: Tue, 6 Aug 2024 21:51:47 +0000 Subject: [PATCH 025/135] Automatic Changelog Update (#567) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e3de08a18b0..b3218a908e1 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5025,3 +5025,11 @@ Entries: languages. id: 6228 time: '2024-08-06T21:22:11.0000000+00:00' +- author: Tilkku + changes: + - type: Add + message: Added Pen Lights + - type: Add + message: Eye Examination + id: 6229 + time: '2024-08-06T21:51:21.0000000+00:00' From 8768df79121f3ccead72d97cba143cec49c9a369 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Wed, 7 Aug 2024 06:03:35 +0800 Subject: [PATCH 026/135] Unique Glove Fibers (#642) # Description Cherry-picked from Delta-V, originally by @WarMechanic (https://github.com/DeltaV-Station/Delta-v/pull/1455). Original Description: > Every pair of gloves now has its own fingerprint, so items can be traced back to gloves which can then be traced back to people. > > ## Why / Balance > > Evidence is very important to court cases running smoothly, so detectives now have more evidence that can certify whether or not John Syndicate's behaviour is valid. Traitors are now encouraged to either clean evidence off syndicate gear regardless of glove status, or use a disposable pair of gloves specifically for handling syndicate gear to be disposed of later. > > Aside from being required to obfuscate evidence you leave behind, there is now a value proposition to searching glove prints of departments. Wearing gloves that does not correspond your department can punish an unknowing detective into searching the wrong people. > > ## Technical details > > `FiberComponent.cs` now stores a Fiberprint variable like `FingerprintComponent.cs`. The code for assigning a fiberprint is the same as the fingerprint. When evidence is placed on an object, the fiberprint is concatenated to its localised fiber type.

Original Media

> hm ok we have these specific gloves on an akms >
> > > > hm well we found the gloves and they have fingerprints >
> > > > gotem >
> >

# Changelog :cl: WarMechanic - add: Gloves now have unique fingerprints. Items can be traced back to gloves, which can then be traced back to people. --------- Signed-off-by: Angelo Fallaria Co-authored-by: WarMechanic <69510347+WarMechanic@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Co-authored-by: VMSolidus --- .../Forensics/Components/FiberComponent.cs | 3 +++ .../Forensics/Systems/ForensicsSystem.cs | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Content.Server/Forensics/Components/FiberComponent.cs b/Content.Server/Forensics/Components/FiberComponent.cs index 2086c958702..4cbb1e7be7f 100644 --- a/Content.Server/Forensics/Components/FiberComponent.cs +++ b/Content.Server/Forensics/Components/FiberComponent.cs @@ -12,5 +12,8 @@ public sealed partial class FiberComponent : Component [DataField] public string? FiberColor; + + [DataField] + public string? Fiberprint; } } diff --git a/Content.Server/Forensics/Systems/ForensicsSystem.cs b/Content.Server/Forensics/Systems/ForensicsSystem.cs index a081429fd3a..1663c20fedb 100644 --- a/Content.Server/Forensics/Systems/ForensicsSystem.cs +++ b/Content.Server/Forensics/Systems/ForensicsSystem.cs @@ -23,6 +23,7 @@ public sealed class ForensicsSystem : EntitySystem public override void Initialize() { SubscribeLocalEvent(OnInteract); + SubscribeLocalEvent(OnFiberInit); SubscribeLocalEvent(OnFingerprintInit); SubscribeLocalEvent(OnDNAInit); @@ -39,6 +40,11 @@ private void OnInteract(EntityUid uid, FingerprintComponent component, ContactIn ApplyEvidence(uid, args.Other); } + private void OnFiberInit(EntityUid uid, FiberComponent component, MapInitEvent args) + { + component.Fiberprint = GenerateFingerprint(length: 7); + } + private void OnFingerprintInit(EntityUid uid, FingerprintComponent component, MapInitEvent args) { component.Fingerprint = GenerateFingerprint(); @@ -150,9 +156,9 @@ private void OnCleanForensicsDoAfter(EntityUid uid, ForensicsComponent component targetComp.Residues.Add(string.IsNullOrEmpty(residue.ResidueColor) ? Loc.GetString("forensic-residue", ("adjective", residue.ResidueAdjective)) : Loc.GetString("forensic-residue-colored", ("color", residue.ResidueColor), ("adjective", residue.ResidueAdjective))); } - public string GenerateFingerprint() + public string GenerateFingerprint(int length = 16) { - var fingerprint = new byte[16]; + var fingerprint = new byte[Math.Clamp(length, 0, 255)]; _random.NextBytes(fingerprint); return Convert.ToHexString(fingerprint); } @@ -179,7 +185,12 @@ private void ApplyEvidence(EntityUid user, EntityUid target) if (_inventory.TryGetSlotEntity(user, "gloves", out var gloves)) { if (TryComp(gloves, out var fiber) && !string.IsNullOrEmpty(fiber.FiberMaterial)) - component.Fibers.Add(string.IsNullOrEmpty(fiber.FiberColor) ? Loc.GetString("forensic-fibers", ("material", fiber.FiberMaterial)) : Loc.GetString("forensic-fibers-colored", ("color", fiber.FiberColor), ("material", fiber.FiberMaterial))); + { + var fiberLocale = string.IsNullOrEmpty(fiber.FiberColor) + ? Loc.GetString("forensic-fibers", ("material", fiber.FiberMaterial)) + : Loc.GetString("forensic-fibers-colored", ("color", fiber.FiberColor), ("material", fiber.FiberMaterial)); + component.Fibers.Add(fiberLocale + " ; " + fiber.Fiberprint); + } if (HasComp(gloves)) return; From 24a5f9201d906ee52b8a4da4c6e324cd2e64438e Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 6 Aug 2024 22:03:58 +0000 Subject: [PATCH 027/135] Automatic Changelog Update (#642) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b3218a908e1..742c9222745 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5033,3 +5033,11 @@ Entries: message: Eye Examination id: 6229 time: '2024-08-06T21:51:21.0000000+00:00' +- author: WarMechanic + changes: + - type: Add + message: >- + Gloves now have unique fingerprints. Items can be traced back to gloves, + which can then be traced back to people. + id: 6230 + time: '2024-08-06T22:03:36.0000000+00:00' From bd11307c54e0ed383246c81fec65a9d8dba1309f Mon Sep 17 00:00:00 2001 From: SleepyScarecrow <136123749+SleepyScarecrow@users.noreply.github.com> Date: Tue, 6 Aug 2024 18:04:15 -0400 Subject: [PATCH 028/135] Alphabetized physical-desc.ftl (Fr This Time) (#648) # Description alphabetized physical-desc.ftl because it annoyed me --- .../en-US/reagents/meta/physical-desc.ftl | 170 +++++++++--------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/Resources/Locale/en-US/reagents/meta/physical-desc.ftl b/Resources/Locale/en-US/reagents/meta/physical-desc.ftl index 50ea5f590c7..064b21eaa9c 100644 --- a/Resources/Locale/en-US/reagents/meta/physical-desc.ftl +++ b/Resources/Locale/en-US/reagents/meta/physical-desc.ftl @@ -1,101 +1,101 @@ -reagent-physical-desc-skunky = skunky -reagent-physical-desc-soapy = soapy -reagent-physical-desc-ferrous = ferrous -reagent-physical-desc-nothing = nothing +reagent-physical-desc-abrasive = abrasive +reagent-physical-desc-acidic = acidic reagent-physical-desc-acrid = acrid -reagent-physical-desc-thick-and-grainy = thick and grainy -reagent-physical-desc-necrotic = necrotic -reagent-physical-desc-oily = oily -reagent-physical-desc-glowing = glowing -reagent-physical-desc-heterogeneous = heterogeneous -reagent-physical-desc-mucus-like = mucus-like -reagent-physical-desc-cold = cold +reagent-physical-desc-alkaline = alkaline +reagent-physical-desc-aromatic = aromatic reagent-physical-desc-bee-guts = bee guts -reagent-physical-desc-tangy = tangy -reagent-physical-desc-fizzy = fizzy -reagent-physical-desc-fuzzy = fuzzy -reagent-physical-desc-spicy = spicy -reagent-physical-desc-abrasive = abrasive -reagent-physical-desc-chalky = chalky -reagent-physical-desc-roaring = roaring -reagent-physical-desc-robust = robust -reagent-physical-desc-sickly = sickly -reagent-physical-desc-murky = murky -reagent-physical-desc-bubbling = bubbling -reagent-physical-desc-wormy = wormy -reagent-physical-desc-frosty = frosty reagent-physical-desc-blazing = blazing -reagent-physical-desc-translucent = translucent -reagent-physical-desc-sugary = sugary -reagent-physical-desc-putrid = putrid -reagent-physical-desc-saucey = saucey -reagent-physical-desc-salty = salty -reagent-physical-desc-milky = milky -reagent-physical-desc-refreshing = refreshing -reagent-physical-desc-soothing = soothing -reagent-physical-desc-starchy = starchy -reagent-physical-desc-starry = starry -reagent-physical-desc-tart = tart -reagent-physical-desc-aromatic = aromatic -reagent-physical-desc-thick = thick -reagent-physical-desc-syrupy = syrupy -reagent-physical-desc-grainy = grainy -reagent-physical-desc-foamy = foamy -reagent-physical-desc-tropical = tropical +reagent-physical-desc-bubbling = bubbling +reagent-physical-desc-bubbly = bubbly +reagent-physical-desc-burning = burning +reagent-physical-desc-buzzy = buzzy +reagent-physical-desc-chalky = chalky +reagent-physical-desc-chewy = chewy +reagent-physical-desc-citric = citric +reagent-physical-desc-cloudy = cloudy +reagent-physical-desc-clumpy = clumpy reagent-physical-desc-coarse = coarse -reagent-physical-desc-opaque = opaque -reagent-physical-desc-pulpy = pulpy -reagent-physical-desc-reasonably-metallic = reasonably metallic -reagent-physical-desc-metallic = metallic -reagent-physical-desc-gaseous = gaseous -reagent-physical-desc-ground-brass = ground brass -reagent-physical-desc-dark-brown = dark brown +reagent-physical-desc-cold = cold +reagent-physical-desc-creamy = creamy +reagent-physical-desc-crisp = crisp reagent-physical-desc-crystalline = crystalline -reagent-physical-desc-viscous = viscous -reagent-physical-desc-shiny = shiny +reagent-physical-desc-dark-brown = dark brown reagent-physical-desc-dark-red = dark-red +reagent-physical-desc-electric = electric +reagent-physical-desc-energizing = energizing +reagent-physical-desc-enigmatic = enigmatic +reagent-physical-desc-ethereal = ethereal +reagent-physical-desc-exhilarating = exhilarating +reagent-physical-desc-exotic-smelling = exotic smelling +reagent-physical-desc-ferrous = ferrous +reagent-physical-desc-fibrous = fibrous +reagent-physical-desc-fizzy = fizzy +reagent-physical-desc-fizzy-and-creamy = fizzy and creamy +reagent-physical-desc-fluffy = fluffy +reagent-physical-desc-foamy = foamy +reagent-physical-desc-frosty = frosty +reagent-physical-desc-funny = funny +reagent-physical-desc-fuzzy = fuzzy +reagent-physical-desc-gaseous = gaseous +reagent-physical-desc-glittery = glittery +reagent-physical-desc-gloopy = gloopy +reagent-physical-desc-glowing = glowing +reagent-physical-desc-grainy = grainy +reagent-physical-desc-ground-brass = ground brass +reagent-physical-desc-heterogeneous = heterogeneous +reagent-physical-desc-holy = holy +reagent-physical-desc-inky = inky reagent-physical-desc-ionizing = ionizing +reagent-physical-desc-lemony-fresh = lemony fresh +reagent-physical-desc-metallic = metallic +reagent-physical-desc-milky = milky +reagent-physical-desc-mucus-like = mucus-like +reagent-physical-desc-murky = murky +reagent-physical-desc-necrotic = necrotic +reagent-physical-desc-neural = neural reagent-physical-desc-nondescript = nondescript -reagent-physical-desc-burning = burning +reagent-physical-desc-nothing = nothing +reagent-physical-desc-odorless = odorless +reagent-physical-desc-oily = oily +reagent-physical-desc-opaque = opaque +reagent-physical-desc-overpowering = overpowering reagent-physical-desc-porous = porous reagent-physical-desc-powdery = powdery -reagent-physical-desc-creamy = creamy -reagent-physical-desc-sticky = sticky -reagent-physical-desc-bubbly = bubbly +reagent-physical-desc-pulpy = pulpy +reagent-physical-desc-pungent = pungent +reagent-physical-desc-putrid = putrid +reagent-physical-desc-reasonably-metallic = reasonably metallic +reagent-physical-desc-reflective = reflective +reagent-physical-desc-refreshing = refreshing +reagent-physical-desc-roaring = roaring +reagent-physical-desc-robust = robust reagent-physical-desc-rocky = rocky -reagent-physical-desc-lemony-fresh = lemony fresh +reagent-physical-desc-salty = salty +reagent-physical-desc-saucey = saucey +reagent-physical-desc-shiny = shiny +reagent-physical-desc-sickly = sickly +reagent-physical-desc-skunky = skunky +reagent-physical-desc-slimy = slimy reagent-physical-desc-soapy = soapy -reagent-physical-desc-crisp = crisp -reagent-physical-desc-citric = citric -reagent-physical-desc-acidic = acidic -reagent-physical-desc-buzzy = buzzy -reagent-physical-desc-fibrous = fibrous -reagent-physical-desc-strong-smelling = strong smelling -reagent-physical-desc-fizzy-and-creamy = fizzy and creamy -reagent-physical-desc-overpowering = overpowering +reagent-physical-desc-soapy = soapy +reagent-physical-desc-soothing = soothing reagent-physical-desc-sour = sour -reagent-physical-desc-pungent = pungent -reagent-physical-desc-clumpy = clumpy +reagent-physical-desc-spicy = spicy +reagent-physical-desc-starchy = starchy +reagent-physical-desc-starry = starry +reagent-physical-desc-sticky = sticky +reagent-physical-desc-strong-smelling = strong smelling reagent-physical-desc-strong-smelling = strong-smelling -reagent-physical-desc-odorless = odorless -reagent-physical-desc-gloopy = gloopy -reagent-physical-desc-cloudy = cloudy +reagent-physical-desc-sugary = sugary reagent-physical-desc-sweet = sweet -reagent-physical-desc-electric = electric -reagent-physical-desc-chewy = chewy -reagent-physical-desc-volatile = volatile -reagent-physical-desc-inky = inky -reagent-physical-desc-enigmatic = enigmatic -reagent-physical-desc-exotic-smelling = exotic smelling -reagent-physical-desc-ethereal = ethereal -reagent-physical-desc-glittery = glittery -reagent-physical-desc-energizing = energizing -reagent-physical-desc-exhilarating = exhilarating +reagent-physical-desc-syrupy = syrupy +reagent-physical-desc-tangy = tangy +reagent-physical-desc-tart = tart +reagent-physical-desc-thick = thick +reagent-physical-desc-thick-and-grainy = thick and grainy +reagent-physical-desc-translucent = translucent +reagent-physical-desc-tropical = tropical reagent-physical-desc-vibrant = vibrant -reagent-physical-desc-fluffy = fluffy -reagent-physical-desc-funny = funny -reagent-physical-desc-alkaline = alkaline -reagent-physical-desc-reflective = reflective -reagent-physical-desc-holy = holy -reagent-physical-desc-slimy = slimy -reagent-physical-desc-neural = neural +reagent-physical-desc-viscous = viscous +reagent-physical-desc-volatile = volatile +reagent-physical-desc-wormy = wormy From ab2947b1ff5ba7ef8f60609454897616f8f13f55 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Wed, 7 Aug 2024 14:07:35 +0800 Subject: [PATCH 029/135] Fix No Blood Regeneration (#689) # Description Being a little too clever with omitting braces in complicated if statement chains in #686 caused blood regeneration for entities without Blood Deficiency to stop working altogether. I added some braces and now blood regeneration works again. I also added `DataField` to `HasBloodDeficiency` because I forgot to add that. # Changelog :cl: Skubman - fix: Passive blood regeneration now works again. --- Content.Server/Body/Components/BloodstreamComponent.cs | 1 + Content.Server/Body/Systems/BloodstreamSystem.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Content.Server/Body/Components/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs index 7a4af3e4cc1..76eadb99fd8 100644 --- a/Content.Server/Body/Components/BloodstreamComponent.cs +++ b/Content.Server/Body/Components/BloodstreamComponent.cs @@ -177,6 +177,7 @@ public sealed partial class BloodstreamComponent : Component /// If this is true, the entity will not passively regenerate blood, /// and instead will slowly lose blood. ///
+ [DataField] public bool HasBloodDeficiency = false; /// diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index fafc649eb29..b37ac5efeb4 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -120,12 +120,15 @@ public override void Update(float frameTime) // Removes blood for Blood Deficiency constantly. if (bloodstream.HasBloodDeficiency) + { if (!_mobStateSystem.IsDead(uid)) RemoveBlood(uid, bloodstream.BloodDeficiencyLossAmount, bloodstream); + } // Adds blood to their blood level if it is below the maximum. - else if (bloodSolution.Volume < bloodSolution.MaxVolume) - if (!_mobStateSystem.IsDead(uid)) - TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream); + else if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid)) + { + TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream); + } // Removes blood from the bloodstream based on bleed amount (bleed rate) // as well as stop their bleeding to a certain extent. From cf310f302c2add2eb0fe25cc59d7807483049285 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 06:08:10 +0000 Subject: [PATCH 030/135] Automatic Changelog Update (#689) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 742c9222745..73e90b2faf9 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5041,3 +5041,9 @@ Entries: which can then be traced back to people. id: 6230 time: '2024-08-06T22:03:36.0000000+00:00' +- author: Skubman + changes: + - type: Fix + message: Passive blood regeneration now works again. + id: 6231 + time: '2024-08-07T06:07:35.0000000+00:00' From 69946f87ce695bd0f1378a6705678845608b3a32 Mon Sep 17 00:00:00 2001 From: Fansana <116083121+Fansana@users.noreply.github.com> Date: Wed, 7 Aug 2024 19:31:55 +0200 Subject: [PATCH 031/135] Fix BarotraumaSystem (#694) # Description This PR fixes an issue with the BarotraumaSystem which would constantly report high pressure damage, even when no such damage was applied. --- - [x] Tested High pressure damage correctly reported - [x] Tested Low pressure damage correctly reported - [x] Tested No pressure damage correctly reported --- # Changelog :cl: - fix: Barotrauma admin log spam --- .../Atmos/EntitySystems/BarotraumaSystem.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs b/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs index d55ef355f02..948373940e4 100644 --- a/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs +++ b/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs @@ -247,7 +247,11 @@ public override void Update(float frameTime) var damageScale = MathF.Min(((pressure / Atmospherics.HazardHighPressure) - 1) * Atmospherics.PressureDamageCoefficient, Atmospherics.MaxHighPressureDamage); _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * damageScale, true, false); - + if (!barotrauma.TakingDamage) + { + barotrauma.TakingDamage = true; + _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} started taking high pressure damage"); + } _alertsSystem.ShowAlert(uid, AlertType.HighPressure, 2); } else @@ -258,11 +262,6 @@ public override void Update(float frameTime) barotrauma.TakingDamage = false; _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} stopped taking pressure damage"); } - if (!barotrauma.TakingDamage) - { - barotrauma.TakingDamage = true; - _adminLogger.Add(LogType.Barotrauma, $"{ToPrettyString(uid):entity} started taking high pressure damage"); - } // Set correct alert. switch (pressure) { From 1b2c946240b1ce5b229bc67ae5a1019d1f983f01 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 17:32:22 +0000 Subject: [PATCH 032/135] Automatic Changelog Update (#694) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 73e90b2faf9..5aca84c9f32 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5047,3 +5047,9 @@ Entries: message: Passive blood regeneration now works again. id: 6231 time: '2024-08-07T06:07:35.0000000+00:00' +- author: Fansana + changes: + - type: Fix + message: Barotrauma admin log spam + id: 6232 + time: '2024-08-07T17:31:55.0000000+00:00' From a0f3f31a747268dea5f82db49089314ebe826a89 Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Thu, 8 Aug 2024 01:38:04 +0300 Subject: [PATCH 033/135] Butlergone (Cherry-Pick From Delta-V) (#678) # Description Cherry-picks https://github.com/DeltaV-Station/Delta-v/pull/1100 and https://github.com/DeltaV-Station/Delta-v/pull/1222. Makes butlertron anchorable, pullable, and destructible, and disables logging of butlertron's messages. Credit to adeinitas and NullWanderer. # Note This was cherry-picked without testing, someone needs to test it first. # Changelog :cl: - add: Mr. Butlertron can now suffer for its crimes. --------- Signed-off-by: Null <56081759+NullWanderer@users.noreply.github.com> Co-authored-by: Adeinitas <147965189+adeinitas@users.noreply.github.com> Co-authored-by: Null <56081759+NullWanderer@users.noreply.github.com> --- .../DeltaV/NPC/Roboisseur/RoboisseurSystem.cs | 4 ++-- Resources/Prototypes/DeltaV/NPC/roboisseur.yml | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Content.Server/DeltaV/NPC/Roboisseur/RoboisseurSystem.cs b/Content.Server/DeltaV/NPC/Roboisseur/RoboisseurSystem.cs index b4e99e6199d..ee1c4582239 100644 --- a/Content.Server/DeltaV/NPC/Roboisseur/RoboisseurSystem.cs +++ b/Content.Server/DeltaV/NPC/Roboisseur/RoboisseurSystem.cs @@ -58,7 +58,7 @@ public override void Update(float frameTime) } else if (CheckTier(roboisseur.DesiredPrototype.ID, roboisseur) > 2) message = Loc.GetString(_random.Pick(roboisseur.DemandMessagesTier2), ("item", roboisseur.DesiredPrototype.Name)); - _chat.TrySendInGameICMessage(roboisseur.Owner, message, InGameICChatType.Speak, false); + _chat.TrySendInGameICMessage(roboisseur.Owner, message, InGameICChatType.Speak, true); } if (roboisseur.Accumulator >= roboisseur.ResetTime.TotalSeconds) @@ -100,7 +100,7 @@ private void OnInteractHand(EntityUid uid, RoboisseurComponent component, Intera if (CheckTier(component.DesiredPrototype.ID, component) > 1) message = Loc.GetString(_random.Pick(component.DemandMessagesTier2), ("item", component.DesiredPrototype.Name)); - _chat.TrySendInGameICMessage(component.Owner, message, InGameICChatType.Speak, false); + _chat.TrySendInGameICMessage(component.Owner, message, InGameICChatType.Speak, true); } private void OnInteractUsing(EntityUid uid, RoboisseurComponent component, InteractUsingEvent args) diff --git a/Resources/Prototypes/DeltaV/NPC/roboisseur.yml b/Resources/Prototypes/DeltaV/NPC/roboisseur.yml index 2c0b3aee8a0..e7f0b5bcd09 100644 --- a/Resources/Prototypes/DeltaV/NPC/roboisseur.yml +++ b/Resources/Prototypes/DeltaV/NPC/roboisseur.yml @@ -4,12 +4,22 @@ name: Mr. Butlertron description: It asks for food to deliver to exotic customers across the cosmos. Powered by the latest technology in bluespace food delivery. components: + - type: Anchorable + - type: Pullable - type: Sprite noRot: true drawdepth: Mobs sprite: DeltaV/Structures/Machines/roboisseur.rsi layers: - state: roboisseur-1 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 1000 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] - type: Roboisseur - type: Speech speechSounds: Pai From 732b8e87c5236798edc1bf34937ca217a121cdf6 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 22:38:28 +0000 Subject: [PATCH 034/135] Automatic Changelog Update (#678) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 5aca84c9f32..fb3fd2c343c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5053,3 +5053,9 @@ Entries: message: Barotrauma admin log spam id: 6232 time: '2024-08-07T17:31:55.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Add + message: Mr. Butlertron can now suffer for its crimes. + id: 6233 + time: '2024-08-07T22:38:04.0000000+00:00' From 2a6790ba9d703ecc825d59475187f70b96f031b1 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 7 Aug 2024 19:11:41 -0400 Subject: [PATCH 035/135] White Dream Harpy Markings (#696) # Description ONIKS was kind enough to provide me with several new Harpy markings, consisting of alternate Bat-wings, Haven Tail, Long Forked Tail, and Swallow Tail. I have also taken the liberty of actually making a basic set of "Bionic Wings", which are just a slightly edited version of the "harpsuit" wing sleeve, including hardsuit lights. Unfortunately due to limitations in the game's code concerning markings, I couldn't make the lights use the unshaded shader. This limitation irritates me. I'll probably fix that in a separate PR. I actually also received a pack of Arachnid and Felinid sprites! But I'm going to add those in a different PR entirely.

Media

Bionic wings ![image](https://github.com/user-attachments/assets/6acc64a9-be6b-435b-9c61-91287ef65c10) Bat Wings ![image](https://github.com/user-attachments/assets/e44fe12e-8410-47ca-a4c1-5e644fd36b8a) Haven tail ![image](https://github.com/user-attachments/assets/2adadcdd-04fc-458d-8491-61bd52a3b4d1) Swallow tail ![image](https://github.com/user-attachments/assets/615391eb-0314-4e6d-a87b-101d0a307955) Long Forked Tail ![image](https://github.com/user-attachments/assets/e3d672f7-b8cb-4497-a2a3-87d0c224847d)

# Changelog :cl: - add: The following new markings have been added for Harpies: Bat Wings, Simple Bionic Wings, Haven Tail, Swallow tail, and Long Forked Tail --- Resources/Locale/en-US/markings/harpy.ftl | 18 +++++ .../Mobs/Customization/Markings/harpy.yml | 73 ++++++++++++++++++ .../Harpy/harpy_tails.rsi/forked_long.png | Bin 0 -> 1245 bytes .../Harpy/harpy_tails.rsi/haven_tone_1.png | Bin 0 -> 853 bytes .../Harpy/harpy_tails.rsi/haven_tone_2.png | Bin 0 -> 630 bytes .../Harpy/harpy_tails.rsi/meta.json | 18 ++++- .../Harpy/harpy_tails.rsi/swallow_tail.png | Bin 0 -> 1092 bytes .../harpy_wings.rsi/bat_wings_tone_1.png | Bin 0 -> 1581 bytes .../harpy_wings.rsi/bat_wings_tone_2.png | Bin 0 -> 1753 bytes .../harpy_wings.rsi/bionic_wings_tone_1.png | Bin 0 -> 1448 bytes .../harpy_wings.rsi/bionic_wings_tone_2.png | Bin 0 -> 329 bytes .../Harpy/harpy_wings.rsi/meta.json | 18 ++++- 12 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/forked_long.png create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/haven_tone_1.png create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/haven_tone_2.png create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/swallow_tail.png create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bat_wings_tone_1.png create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bat_wings_tone_2.png create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bionic_wings_tone_1.png create mode 100644 Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bionic_wings_tone_2.png diff --git a/Resources/Locale/en-US/markings/harpy.ftl b/Resources/Locale/en-US/markings/harpy.ftl index 6d6ba75a936..724207c3ef8 100644 --- a/Resources/Locale/en-US/markings/harpy.ftl +++ b/Resources/Locale/en-US/markings/harpy.ftl @@ -40,6 +40,14 @@ marking-HarpyWingTipsClassic = Classic Wings with Feather Tips marking-HarpyWingTipsClassic-harpy_wingtip_1 = Main marking-HarpyWingTipsClassic-harpy_wingtip_2 = Feathertips +marking-HarpyWingBat = Bat Wings (Whitescale) +marking-HarpyWingBat-bat_wings_tone_1 = Limbs +marking-HarpyWingBat-bat_wings_tone_2 = Membrane + +marking-HarpyWingBionic = Simple Bionic Wings (Whitescale) +marking-HarpyWingBionic-bionic_wings_tone_1 = Wings +marking-HarpyWingBionic-bionic_wings_tone_2 = Lights (Unshaded) + marking-HarpyEarsDefault = Feather Tufts marking-HarpyEarsDefault-harpy_ears_default = Tufts @@ -65,6 +73,16 @@ marking-HarpyTailPeacock = Peacock Tail marking-HarpyTailPeacock-peacock_tail_feathers = Feathers marking-HarpyTailPeacock-peacock_tail_eyes = Eyes +marking-HarpyTailHaven = Haven Tail (Whitescale) +marking-HarpyTailHaven-haven_tone_1 = Outer Feathers +marking-HarpyTailHaven-haven_tone_2 = Inner Feathers + +marking-HarpyTailForkedLong = Long Forked Tail (Whitescale) +marking-HarpyTailForkedLong-forked_long = Tail + +marking-HarpyTailSwallow = Swallow Tail (Whitescale) +marking-HarpyTailForkedLong-forked_long = Tail + marking-HarpyChestDefault = Wing & Groin Under-Clothes marking-HarpyChestDefault-upper = Wing Under-Clothes marking-HarpyChestDefault-lower = Groin Under-Clothes diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/harpy.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/harpy.yml index 697781be939..2629d836516 100644 --- a/Resources/Prototypes/Entities/Mobs/Customization/Markings/harpy.yml +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/harpy.yml @@ -253,6 +253,56 @@ - sprite: Mobs/Customization/Harpy/harpy_tails48x48.rsi state: peacock_tail_eyes +- type: marking + id: HarpyTailHaven + bodyPart: Tail + markingCategory: Tail + speciesRestriction: [Harpy] + coloring: + default: + type: + !type:CategoryColoring + category: Hair + fallbackTypes: + - !type:SimpleColoring + sprites: + - sprite: Mobs/Customization/Harpy/harpy_tails.rsi + state: haven_tone_1 + - sprite: Mobs/Customization/Harpy/harpy_tails.rsi + state: haven_tone_2 + +- type: marking + id: HarpyTailForkedLong + bodyPart: Tail + markingCategory: Tail + speciesRestriction: [Harpy] + coloring: + default: + type: + !type:CategoryColoring + category: Hair + fallbackTypes: + - !type:SimpleColoring + sprites: + - sprite: Mobs/Customization/Harpy/harpy_tails.rsi + state: forked_long + +- type: marking + id: HarpyTailSwallow + bodyPart: Tail + markingCategory: Tail + speciesRestriction: [Harpy] + coloring: + default: + type: + !type:CategoryColoring + category: Hair + fallbackTypes: + - !type:SimpleColoring + sprites: + - sprite: Mobs/Customization/Harpy/harpy_tails.rsi + state: swallow_tail + - type: marking id: HarpyWing2ToneClassic bodyPart: RArm @@ -310,6 +360,29 @@ - sprite: Mobs/Customization/Harpy/harpy_wings.rsi state: harpy_wingtip_2 +- type: marking + id: HarpyWingBat + bodyPart: RArm + markingCategory: Arms + speciesRestriction: [Harpy] + sprites: + - sprite: Mobs/Customization/Harpy/harpy_wings.rsi + state: bat_wings_tone_1 + - sprite: Mobs/Customization/Harpy/harpy_wings.rsi + state: bat_wings_tone_2 + +- type: marking + id: HarpyWingBionic + bodyPart: RArm + markingCategory: Arms + speciesRestriction: [Harpy] + sprites: + - sprite: Mobs/Customization/Harpy/harpy_wings.rsi + state: bionic_wings_tone_1 + - sprite: Mobs/Customization/Harpy/harpy_wings.rsi + state: bionic_wings_tone_2 + shader: unshaded + - type: marking id: HarpyChestDefault bodyPart: Chest diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/forked_long.png b/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/forked_long.png new file mode 100644 index 0000000000000000000000000000000000000000..280768b40af24643cf1eea7660bf0cfd1d5ebe05 GIT binary patch literal 1245 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU@Xscb`J1#c2)=|%1_J8No8Qr zI6rmbUTB$tEso0N_(!E$G%Bb%MPBO^qIGAdd_m8&3k6AS^4C)#pPp*5~QCP7M-|odeP1P zJ)R2bdTKM-C7lZ0VdtWtbT=@EASH5yXKKqK$*zd1Tlx81q_%67^Ao`!ubCbW0 zdv9HGVs|JIw%DDMIWzV_4Yx$ahLGsB-f?d2%NW-$cgUA|v72#MxYXvXd5@pSdE|cR zT-Ug_Het$t_VE3TiaRqTx9~hn0mcMpfk$L90|U1p2s75F#7|^kVCM03aSW-5dpj#} z)h!2+*2#;a1rG9VvC;YTZNU!qiMv=7cX0+5aEcZ3FVg_+xP2hT-NPRKk%NvoBe6g&#c*j`_*mU$_YHx6S{J{#_s#qf17uzOBC4X&W~d{ z{P4r;?@_+4l2wuh{|hV>PMwI?kQ3ozO=XIjwRFM>hT308Cz>@{{J48G>7wQQ^XKaJ zhabB5Yo2&czL~V8QY_y_HiJeJwk4hp@p@H?=vzVG|(xsrFeI~oeC zV{5sX@uWSy;dy2F?+-V2%zt_2zwU>uqOU4HxYjTV^&XW{xEMizp<0+Luzv0Py=Tup z@(#7VzT=P3d4|8Swbwi+XDcy3(C|AIem0WLQYn1zg-;zWYzwSP)=NwbouI89Rd_^- zL0!`>X2A)iGlG`tGgF+<1)D)(q8!4p>$i^diJF+3myilcb{iuaSfT#aOz9Z z&XBeZKIepX8ZkUFG??kb)UHuyHv4JXtNV+uX0fVG@LT>ksMvs6Vcw$1s=BZB4S%&) q<>$XT^k|-gaRSpZ9{qmnbMg;kc;eHRHDmxY3xlVtpUXO@geCyBy)|h7 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/haven_tone_1.png b/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/haven_tone_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e818e7dd11e8a67e719be7bd065da25e56a847ab GIT binary patch literal 853 zcmV-b1FHOqP)4Tx04UFuk-bX;K@i1XjFO;{6k3RgToJ`00Z|Z3iC~&&kwh?RbJ^q);qG$W zB}lLpY%Bs6qK#jL|ADrGt%4vZf{3NHUyX$GZ4yWjE!<^pe!RUm%+3NGaa|Zr=L}$& zB|8y|Dog2Q#rFaqh8cc@RpD6k$+;B%T%ULF$b1`-weY{ylg&8-@c7A7!m>+bc7ynO z$&$QH?iU3$OFkrrZ8k{0l6t1W&yw>EewS>g60^LUtf}PNIMc?WU>oEya>&rjqS=qU zNg!t~CYc8rLvWBl3{fb^po}%>C?UdZa%R8##_PTX6zLKCTByLLBaZ^TVX9?T%`t1# zbKE*Aa_&Fp>1dM^jp~6Y(DmfHZzF(j2dGtD_v^@YYsY~15x6j0{vziz{XxCj(n1G7 za1%JYY-yQY;Cu@hc(7DktxH};ho%9qr$BES=(_>BR~oZwp5x>mNNwy1LTR(v6Lcx3{-nU0uY)#Gjv^jEsz^sHmHpo0F51 zkB^T4005OnZi@f_01b3fPE-H?|NsC0|NsC0|Nj6z=pu#y000SaNLh0L01FWS01FWT ze`H^g0003vNklZv*wV;Pkr1iSxp>8%jGZiU;`RxB>P=XP1jl9ABLv@K zPA0$kz@-arG4h=~B%sAvk1 z1%N}w93V?NCQJg(T7U(h7GMFW1?T|B%jh4ur5rX0KuQ2{8x-NFIgdCM0Ofah1vkG*^t)BfOpK^MYwK07A%r?5Qn!B>y4KTAKZ fr#b%cUnsynzg)gFOz00000NkvXXu0mjfXVZOu literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/haven_tone_2.png b/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/haven_tone_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fe98ec53eb2c4f1b570ef1a891228a7586e37178 GIT binary patch literal 630 zcmV-+0*U>JP)4Tx04UFuk-bX;K@i1XjFO;{6k3RgToJ`00Z|Z3iC~&&kwh?RbJ^q);qG$W zB}lLpY%Bs6qK#jL|ADrGt%4vZf{3NHUyX$GZ4yWjE!<^pe!RUm%+3NGaa|Zr=L}$& zB|8y|Dog2Q#rFaqh8cc@RpD6k$+;B%T%ULF$b1`-weY{ylg&8-@c7A7!m>+bc7ynO z$&$QH?iU3$OFkrrZ8k{0l6t1W&yw>EewS>g60^LUtf}PNIMc?WU>oEya>&rjqS=qU zNg!t~CYc8rLvWBl3{fb^po}%>C?UdZa%R8##_PTX6zLKCTByLLBaZ^TVX9?T%`t1# zbKE*Aa_&Fp>1dM^jp~6Y(DmfHZzF(j2dGtD_v^@YYsY~15x6j0{vziz{XxCj(n1G7 za1%JYY-yQY;Cu@hc(7DktxH};ho%9qr$BES=(_>BR~oZwp5x>mNNwgoUh0LdQz2><{90(4SNQ~v1oG9HLxR|nsN{d zC=e*1K%n4%K}t3N32NFX)M;#eYe}}H>wfPIhY5uBjfzsL^{HjkzY?9Gj$k8@psPQO%C(2{wk@-f5YZ#0@<$e-Pd$XM%#9FGyq$zd$^i QBme*a07*qoM6N<$f@XjYK>z>% literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/meta.json b/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/meta.json index f33401617c0..94795a626ea 100644 --- a/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/meta.json +++ b/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Phoenix and Rooster by @leonardo_dabepis, Finch & Forked Tailfin by @stillxicarus", + "copyright": "Phoenix and Rooster by @leonardo_dabepis, Finch & Forked Tailfin by @stillxicarus, haven & forked_long & swallow by @Kilath", "size": { "x": 32, "y": 32 @@ -22,6 +22,22 @@ { "name": "whitescale_forked_tailfin", "directions": 4 + }, + { + "name": "haven_tone_1", + "directions": 4 + }, + { + "name": "haven_tone_2", + "directions": 4 + }, + { + "name": "forked_long", + "directions": 4 + }, + { + "name": "swallow_tail", + "directions": 4 } ] } diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/swallow_tail.png b/Resources/Textures/Mobs/Customization/Harpy/harpy_tails.rsi/swallow_tail.png new file mode 100644 index 0000000000000000000000000000000000000000..f9187b66f84ad6bddfef3452079a7697372ed3a7 GIT binary patch literal 1092 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU@Xscb`J1#c2)=|%1_J8No8Qr zI6rmbUTB$tEso0N_(!E$G%Bb%MPBO^qIGAdd_m8&3k6AS^4C)#pPp*5~QCP7M-|odeP1P zJ)R2bdTKM-C7lZ0VdtWtbT=@EASH5yXKKqK$*zd1Tlx81q_%67^Ao`!ubCbW0 zdv9HGVs|JIw%DDMIWzV_4Yx$ahLGsB-f?d2%NW-$cgUA|v72#MxYXvXd5@pSdE|cR zT-Ug_Het$t_VE3TiaRqTx9~hn0mcMpfk$L90|U1p2s75F#7|^kU@G=>aSW-5dppaq z>yU$h>*G6)ANeLJ$T{sftWeBhevbD}MTg=OzD3gh3P}QYb_=e5p!7I@)so)Mmq#Sk zX0Bp?czf-!Rrgbcf--s8nEj3Nmm~!;dmLTFHlfRvS3$H}%0Wxav>`+%i(zHN6^5XV zD;Sp~3FbSz&F{=LlddW~pSRt6*WGpHR&)0#a73B>bqK8MUDNQisM1@m%W!Y#EH|kO z@4xSTTb3Q?Y`D(rF^|Rk^PFM#*pkm&-XPMuhC%P|;fDz(xgL^SyayaL@;_JaJ@tRD zR>IW4PaeODc2*pJ{4tH~+3JwSV%8^bZE{Z~ZS;8a(LYhWf64XNTW9t^{-G+Y^`CW- zhF8<;gX~_x``xT6Rrc=gQ=ja~{i}=9k1e772jlFr-G5*H-WNE_=s|I6_(RFalg;Z5 zOrFx)QEM%U=6&Td?v8|cwxBNqO=CjW`f7Z_Ec@n`GHdmNk{_)0@ zZWF%#%%1w}-@nV+2XE%2H67>+$VO{@RvAZIY6yuZ^}{{XgS)l*s&I)&<5#?#{Amme@J_Y13rJ zJL!+#`OJMN5nJ8t$9CZ2)vT{ubVJ1jl#@!=HaRgrP$|3Cay4B*JE?4C({i>2&OKqp zB5l19wQL)e(vF;qeP?5Ip6Q2>%#pAuHL~ZKcy=9q|9E5OwWi~^Oat~u9zw@8=Cz7{W5~LTNXP>}z^z%N(GM}Yx(sM<+fN7G!)78&q Iol`;+090D%3;+NC literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bat_wings_tone_1.png b/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bat_wings_tone_1.png new file mode 100644 index 0000000000000000000000000000000000000000..a147739cc90c5cc7bd164a8bb774730f17eed382 GIT binary patch literal 1581 zcmV+|2GaS7P)K@`MNB50!)F@jN>4us0f~|O4xJ%2X zR)vp*qmDEve693!nO_uV%KV|&NyI0?uWE)fHJq+tE$f)VgTfIrSJW!~sG9_JYhhk; zk3=snai)n8CQXqwaugVnY{|^(`-cB~bL7RN$={}gBaRGN@kT{0N>yF5A-XPKj*^=D z|9QH`=t#MGFa|Bpp7-7lfnE67@x1S2&-*!nrYE?xs{XvpY5Y_4ovIc&gwQ6OUsbjA z9$aie_oJP1Qh!pDgx@gW?F>4S(0L1O%jH>B_Bnlk#D+Z44eTGlfSeDl`~o4lXc-r; zD+mAp010qNS#tmY3labT3lag+-G2N400d=8L_t(|UhSGqPUAojg-sMLz=|`BV8kWh z7KjBKmPip|!GbLag*!x?feq|90SaiAXqJdGAZ2(So~Kf-?yimoeCr2^~(S)0sT>p6`O!x7SXy zmNI~&-QC^l_4TzretLSUMx#-y9_+Tax9k1Q&CTlm{@%39!5drJ=V~xd9v&W6M@L81 z!^1-(0Kq{@0Jad}6%ax;-V>YTYDo4bf=?eG=gv)TZd&yY_V?$e-1nWGiuFChC6U-` zAF)H#paGjkhetzGcz1U<+uPf#kDKf1GdLW{V<0<0HeTEEm;z)Rk`cSMu{z6pTTtJghs*>+nRYA#`9`OI-~$p#1?1&X9>CFhBQREzP@e*rfx>^ysWn_Qy$XogYP!ZI+6VkvcCA$a z#y?+P7Fxn2ayf%f-4MMBaF)r~eF1;)s~?P-_zZ6K_VMxYLLFe$V+<)`8L^2=!$&Vv z7Z(?;%3v~?bP~{|ewVtEzWfvlg+ifFC=?2X{~YUO<|^)8FFEuRRh|O|p(mBi&ZjlIdH6GXd$k~stu39!a zE8ABmu#r}lnv70P>hA%-$!O$`?K0ADYxKKyPCM@BCNyIpwoZ2Hc(jdWutPMLfX>^? zMz@j)pZR$NXM+(e_xf7|CSBxfEt%ku8VE53b&#Lr!;n&B7;XGQYdUNOgTY++GN!&p z#z1Un&~d2=+Sv}aOWM`n2i)G?R_p8QGx<$kDu-^3{IaIL#v1j|OaRt%0&MlS18(3@ zKNwkM%S5NwLS?;kc6Jv1LhLKC;^G(@Lv<|N%OIR@Y;3e{c-Ss`+FQtnBUuKGy$%Sc zx1L^KJ?%rpw7D*c(EoYfHLXUjO5;hWu`CaDMDvvxzs9ouW_s5CRUr0Eplugk1^(vS fA20uc#+Bk10P^udA=g`(00000NkvXXu0mjf*Ean; literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bat_wings_tone_2.png b/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bat_wings_tone_2.png new file mode 100644 index 0000000000000000000000000000000000000000..b2170ff803c694b4080f0a18e8ec78b2ff383adb GIT binary patch literal 1753 zcmV;~1}6E5P)K@`MNB50!)F@jN>4us0f~|O4xJ%2X zR)vp*qmDEve693!nO_uV%KV|&NyI0?uWE)fHJq+tE$f)VgTfIrSJW!~sG9_JYhhk; zk3=snai)n8CQXqwaugVnY{|^(`-cB~bL7RN$={}gBaRGN@kT{0N>yF5A-XPKj*^=D z|9QH`=t#MGFa|Bpp7-7lfnE67@x1S2&-*!nrYE?xs{XvpY5Y_4ovIc&gwQ6OUsbjA z9$aie_oJP1Qh!pDgx@gW?F>4S(0L1O%jH>B_Bnlk#D+Z44eTGlfSeDl`~o4lXc-r; zD+mAp010qNS#tmY3labT3lag+-G2N400j|AL_t(|UhSGqN+d}X$0NlPxDb({4=}W% zYZo#!y6_4^(cVEkh14A!%DIHn%t~BZlrqa^Xa*4%E?o&Z@eAW0^C~|o(<)~Wj2|Rc zW_-Mlc=0mLm(FD}nM@{=$z(E_OeT}bd@zbxjg!fwyuZJ9H#axMWIUc~`)xEzzrPL! zQ*E1DTW(`xqg-2CbDNu+Gi8Y3aOkXzqvPWsdw+kw*Z6sLSZ=zA;S99KGhzH&`oFaa zbzS{Dg`cB*cz6hgbUEVa=qUWH%APgGVizRva$YdsEFBshAO#qJXMY_G%HKz$qRn`S z#)o$G_m_*ky}e*iUnKkD;vzWy{QSHoyJoEWHv+T(NoQ|^oZ7@v^#a}+v(nL92v(a9 zsqnX|fX>yfaVUZz%*VX01Id>07$e$b3!_7lqw(0%ro)s2@Dv@j@9@4~K|--QZYK0+ z9IFt|g96OoHb$})_KYQZUMpKf9ZGEA9GjYSNDffKv&JhNwYU2aL$F{R<5`hOG%U;& z74Y+i1FFeZ$?LVUMO6pu1git29AFc~>FH^?;qWz#K9*&iBYJ0rW-9U=BBjSc~HVE(EO zwIry}({?D!6fM0JaIqib6!r?mF05?E8rgHfc!hnN4pT;HZ`fSGHD%?l5Cm>V3d7;a zN%8aN&u)8rJKcubo(HV#>+9>{Prv#+3=#UQY9HAm>JSpRX5b|V3T!1jjOAx(kGRg4 z?-JY4OIFP(8MN`cZ}qs1#^R_&3Wz~0cd3jegX0_Ag_P+7^7O{ppBB7J#1UIj$I(ks zHqd7QIvs%VGMcxx7|v_!<>h7f{QT^AeN7)*-Qkrq#mv6Nj4o90RGAD}iV9x4;}ow` zc>Qjx(IXM2{YFw3RDeSP-1Rbz5PY zwM|+hz}D2Y>S2H}p2)DZ{FC7@6*=4Hofqchg9~IHztjrCR`7o7! z3NoEl8qlN)ce^F5@mymM_St){MY%|_ae^vPDdeMUwgo5}W>ux8F4zwUR##U;8%YMN zk)R}~1jx0w4*e>2D*%a5+fYdm6sT5 zT#<=vbkGMF(oYLztJ$)PcKdxmr@|^(gA!rW%In&HwfaI^K_5|ojRelEzFp4=t&R2$ z0CCmB7@P3^Pvb?^2^=Qu!!1}&=(-cMIzXS6K{V1mK0X$I|M+1O-dxq&w}b-dAQn_{ z!cU(*xs{cb-~=rmf9L;kQsh0m_%I_ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bionic_wings_tone_1.png b/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/bionic_wings_tone_1.png new file mode 100644 index 0000000000000000000000000000000000000000..752d6cc9a2062ae380ac67d49149f5c25e783f9a GIT binary patch literal 1448 zcmV;Z1y}lsP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGizyJUazyWI3i3tDz1wBbbK~#8N?V7tw zEHMMo5^HnW%PP4`N1%gOmfb5&Lo-L%?2Ki$K&yMJRXn7vMSQ{t5N4f zE-x>`YDJ(u`l({ow6wH{Px>|eFD@?T)TI@@9}d`)8y2jFT3cJuQLeA9uH^jq_$cS8 zsi{QgkuY&oUtcff$c~(chlgRuDVjj+`1rUgeFFb3-vk=yUuR`yB`6k)vHr0Ukk9AC zLZKkn2p*0ZJPgAD10}4ZWA;rqYq=Hxi#>U3ve0+Qy zJUu;0&^*$hw?}{20km6*wY4=&JGrhla1-{2J=nDoO8^BRfS#V7AeT!ua$}$$`ooS( zfXU|Orc50i=&KWrDCa0L@1s9$!LE&10w^Gwi^2Q*yPQ!5m7WOi+xjO7FyXWzdJ;G? zlF;v4lBcf9DN6uWOj|><&RmSla*_?M&Mu+_Glyw&a&l5iJki$%8|HoVhaK31T~%F1 zSpv|A0?y9Pq^_psqY0mG(n`#Fwqrlop@1Y2I#^66Cns~=-QB9@lPDl(f7^Z7fjx8K zCb20%0TUAwV(j|*TIxZi*N}dn{b0u>KnHDhcXu(A!{}*>Ehf|)(n+u#`@s(E!LCh1 zSpswc7Z(>{dwY8>3_to*D**k_A9h>4N0+H&n2u7y5{7isNz*mDOW)g@lKnEJK@=Z()rth-C z-w;6f08UR&GxJTTp{uJ)%2o{!fCEDY9aMEDz#i<4V$b+suT1r~Rr7JUl#vhlhvq zn;n0DpPQQto0^*BzDX7$ZNZbfySrd|dRpw`CwTns*VoqM0{i>>5&XN*DN32QX-^Yh`t!a~UHDb91-T*MoJWIgO{=stAcgc_+C zF(4MiBozi$!TQ{f783kNK*|_e`n-L)22M*tdf;R6WV z6+Au@{513l4fu2UlY7e^wh(Vkr7Dykt}aCDLxjfaDL88&YAzWG1RS`qCR0d Uhf+r841JJ!p00i_>zopr052DVy#N3J literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/meta.json b/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/meta.json index 7737af0afc2..c8bf28767a8 100644 --- a/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/meta.json +++ b/Resources/Textures/Mobs/Customization/Harpy/harpy_wings.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "classicharpy Taken from S.P.L.U.R.T at commit https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13/commit/285f6f86ac41a6246f250993486effeab8581c2c, edited by @raistlin_jag | harpyfolded, harpy, and owl by @stillxicarus", + "copyright": "classicharpy Taken from S.P.L.U.R.T at commit https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13/commit/285f6f86ac41a6246f250993486effeab8581c2c, edited by @raistlin_jag | harpyfolded, harpy, and owl by @stillxicarus, bat wings by @Kilath", "states": [ { "name": "huescale_harpy", @@ -78,6 +78,22 @@ { "name": "whitescale_harpy_wing_owl", "directions": 4 + }, + { + "name": "bat_wings_tone_1", + "directions": 4 + }, + { + "name": "bat_wings_tone_2", + "directions": 4 + }, + { + "name": "bionic_wings_tone_1", + "directions": 4 + }, + { + "name": "bionic_wings_tone_2", + "directions": 4 } ] } From 07325fcdf80e9545da7d38a718c225e5b792136d Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 23:12:04 +0000 Subject: [PATCH 036/135] Automatic Changelog Update (#696) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index fb3fd2c343c..3334fd4e136 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5059,3 +5059,11 @@ Entries: message: Mr. Butlertron can now suffer for its crimes. id: 6233 time: '2024-08-07T22:38:04.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: >- + The following new markings have been added for Harpies: Bat Wings, + Simple Bionic Wings, Haven Tail, Swallow tail, and Long Forked Tail + id: 6234 + time: '2024-08-07T23:11:41.0000000+00:00' From 020e90ab1d9c7adf4c293053881b15a4bc8b4aae Mon Sep 17 00:00:00 2001 From: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Date: Thu, 8 Aug 2024 00:16:30 +0100 Subject: [PATCH 037/135] Add Le Psionic Orb From Nyanotrasen (#685) # Description It says Psionic chat out loud

Media

![image](https://github.com/user-attachments/assets/a60c4110-ce1b-40ca-8177-df2d0b45b6da)

--- # Changelog :cl: - add: Readded Psionic Relay Orb --- .../Entities/Objects/Specific/Research/misc.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Resources/Prototypes/Entities/Objects/Specific/Research/misc.yml diff --git a/Resources/Prototypes/Entities/Objects/Specific/Research/misc.yml b/Resources/Prototypes/Entities/Objects/Specific/Research/misc.yml new file mode 100644 index 00000000000..79c475900aa --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Specific/Research/misc.yml @@ -0,0 +1,9 @@ +- type: entity + parent: PonderingOrb + id: PonderingOrbTelepathic + name: telepathic relay orb + description: Relays messages intercepted from Psionics. + components: + - type: TelepathicRepeater + - type: Psionic + - type: Speech \ No newline at end of file From 9e83f669c836e8934ad21585c2c1dcaed6ebec93 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 23:16:55 +0000 Subject: [PATCH 038/135] Automatic Changelog Update (#685) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 3334fd4e136..b7ab981fc63 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5067,3 +5067,9 @@ Entries: Simple Bionic Wings, Haven Tail, Swallow tail, and Long Forked Tail id: 6234 time: '2024-08-07T23:11:41.0000000+00:00' +- author: DangerRevolution + changes: + - type: Add + message: Readded Psionic Relay Orb + id: 6235 + time: '2024-08-07T23:16:30.0000000+00:00' From dfe5c2c54045c026621f009b676f7f3ef97692dc Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 7 Aug 2024 19:18:35 -0400 Subject: [PATCH 039/135] Psionic Refactor Part 1: Respacing To Keep Files Changed Down (#698) # Description Due to some inherent limitations of maintenance, code review, and me having both severely crippling ADHD and a lifelong adderal dependency, I've made the executive decision to break apart the Psionic Refactor into a multitude of smaller, bite sized PRs. I'm keeping the original Psionic Refactor PR open, because I'm going to need it for code reference to keep track of the changes I had originally worked on, but I need to essentially restart the entire refactor from scratch, and approach it from a new angle that's going to make everything actually way easier. I also need to be able to work on each available system individually wherever possible, and this fact is most readily shown by how the Lightning Refactor and Oracle Refactor were both done separately. To start off, this PR is ONLY moving all of the relevant psionics code to core folders, and nothing more. I'm doing this first so that I can immediately cut down massively on the "Files Changed" with the simplest, most basic change necessary to start my work. No changelog because this isn't player facing, and no media because there's literally nothing to show. --- .../CartridgeLoader/Cartridges/GlimmerMonitorUi.cs | 5 ++--- .../Cartridges/GlimmerMonitorUiFragment.xaml | 2 +- .../Cartridges/GlimmerMonitorUiFragment.xaml.cs | 4 ++-- .../{Nyanotrasen => }/Chat/PsionicChatUpdateSystem.cs | 2 +- .../Psionics/Glimmer/GlimmerReactiveVisuals.cs | 0 .../{Nyanotrasen => }/Psionics/UI/AcceptPsionicsEUI.cs | 0 .../{Nyanotrasen => }/Psionics/UI/AcceptPsionicsWindow.cs | 0 .../{Nyanotrasen => }/UserInterface/GlimmerGraph.cs | 2 +- .../UserInterface/Systems/Chat/ChatUIController.cs | 1 - .../Abilities/Psionics/Abilities/DispelPowerSystem.cs | 0 .../Psionics/Abilities/MetapsionicPowerSystem.cs | 0 .../Abilities/Psionics/Abilities/MindSwapPowerSystem.cs | 0 .../Abilities/Psionics/Abilities/MindSwappedComponent.cs | 0 .../Psionics/Abilities/NoosphericZapPowerSystem.cs | 0 .../Psionics/Abilities/PsionicInvisibilityPowerSystem.cs | 0 .../Psionics/Abilities/PsionicRegenerationPowerSystem.cs | 0 .../Psionics/Abilities/PyrokinesisPowerSystem.cs | 0 .../Abilities/Psionics/Abilities/TelegnosisPowerSystem.cs | 0 .../Abilities/Psionics/PsionicAbilitiesSystem.cs | 0 .../{Nyanotrasen => }/Audio/GlimmerSoundComponent.cs | 0 .../Cartridges}/GlimmerMonitorCartridgeComponent.cs | 0 .../Cartridges}/GlimmerMonitorCartridgeSystem.cs | 0 .../{Nyanotrasen/Chat => Chat/Commands}/TSayCommand.cs | 0 Content.Server/Chat/Systems/ChatSystem.cs | 8 +++----- .../NyanoChatSystem.cs => Chat/TelepathicChatSystem.cs} | 6 +++--- .../{Nyanotrasen => }/Chat/TelepathicRepeaterComponent.cs | 2 +- .../{Nyanotrasen => }/Psionics/AcceptPsionicsEui.cs | 0 .../Psionics/AntiPsychicWeaponComponent.cs | 0 .../{Nyanotrasen => }/Psionics/Dreams/DreamSystem.cs | 0 .../{Nyanotrasen => }/Psionics/Glimmer/GlimmerCommands.cs | 0 .../Psionics/Glimmer/GlimmerReactiveSystem.cs | 0 .../Psionics/Glimmer/PassiveGlimmerReductionSystem.cs | 0 .../Psionics/Glimmer/Structures/GlimmerSourceComponent.cs | 0 .../Glimmer/Structures/GlimmerStructuresSystem.cs | 0 .../Psionics/Invisibility/PsionicInvisibilitySystem.cs | 0 .../Invisibility/PsionicInvisibleContactsComponent.cs | 0 .../Invisibility/PsionicInvisibleContactsSystem.cs | 0 .../Invisibility/PsionicallyInvisibleComponent.cs | 0 .../Psionics/PotentialPsionicComponent.cs | 0 .../Psionics/PsionicAwaitingPlayerComponent.cs | 0 .../Psionics/PsionicBonusChanceComponent.cs | 0 .../{Nyanotrasen => }/Psionics/PsionicsCommands.cs | 0 .../{Nyanotrasen => }/Psionics/PsionicsSystem.cs | 0 .../StationEvents/Components/FreeProberRuleComponent.cs | 0 .../StationEvents/Components/GlimmerEventComponent.cs | 0 .../Components/GlimmerRandomSentienceRuleComponent.cs | 0 .../Components/GlimmerRevenantSpawnRuleComponent.cs | 0 .../StationEvents/Components/GlimmerWispRuleComponent.cs | 0 .../StationEvents/Components/MassMindSwapRuleComponent.cs | 0 .../Components/MundaneDischargeRuleComponent.cs | 0 .../Components/NoosphericFryRuleComponent.cs | 0 .../Components/NoosphericStormRuleComponent.cs | 0 .../Components/NoosphericZapRuleComponent.cs | 0 .../Components/PsionicCatGotYourTongueRuleComponent.cs | 0 .../StationEvents/Events/FreeProberRule.cs | 0 .../StationEvents/Events/GlimmerEventSystem.cs | 0 .../StationEvents/Events/GlimmerRandomSentienceRule.cs | 0 .../StationEvents/Events/GlimmerRevenantSpawnRule.cs | 0 .../StationEvents/Events/GlimmerWispSpawnRule.cs | 0 .../StationEvents/Events/MassMindSwapRule.cs | 0 .../StationEvents/Events/MundaneDischargeRule.cs | 0 .../StationEvents/Events/NoosphericFryRule.cs | 0 .../StationEvents/Events/NoosphericStormRule.cs | 0 .../StationEvents/Events/NoosphericZapRule.cs | 0 .../StationEvents/Events/PsionicCatGotYourTongueRule.cs | 0 .../Actions/Events/DispelPowerActionEvent.cs | 0 .../Actions/Events/EatMouseActionEvent.cs | 0 .../Actions/Events/HairballActionEvent.cs | 0 .../Actions/Events/MassSleepPowerActionEvent.cs | 0 .../Actions/Events/MetapsionicPowerActionEvent.cs | 0 .../Actions/Events/MindSwapPowerActionEvent.cs | 0 .../Actions/Events/NoosphericZapPowerActionEvent.cs | 0 .../Actions/Events/PsionicInvisibilityPowerActionEvent.cs | 0 .../Actions/Events/PsionicRegenerationPowerActionEvent.cs | 0 .../Actions/Events/PyrokinesisPowerActionEvent.cs | 0 .../RemovePsionicInvisibilityOffPowerActionEvent.cs | 0 .../Actions/Events/TelegnosisPowerActionEvent.cs | 0 .../CartridgeLoader/Cartridges/GlimmerMonitorUiState.cs | 0 .../{Nyanotrasen => }/Chapel/SacrificeDoAfterEvent.cs | 0 .../Psionics/Abilities/AcceptPsionicsEuiMessage.cs | 0 .../Psionics/Abilities/Dispel/DamageOnDispelComponent.cs | 0 .../Psionics/Abilities/Dispel/DispelPowerComponent.cs | 0 .../Psionics/Abilities/Dispel/DispellableComponent.cs | 0 .../Abilities/MassSleep/MassSleepPowerComponent.cs | 0 .../Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs | 0 .../Abilities/Metapsionics/MetapsionicPowerComponent.cs | 0 .../Psionics/Abilities/MindSwap/MindSwapPowerComponent.cs | 0 .../NoosphericZap/NoosphericZapPowerComponent.cs | 0 .../PsionicInvisibilityPowerComponent.cs | 0 .../PsionicInvisibilityUsedComponent.cs | 0 .../PsionicRegenerationPowerComponent.cs | 0 .../Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs | 0 .../Abilities/Telegnosis/TelegnosisPowerComponent.cs | 0 .../Telegnosis/TelegnosticProjectionComponent.cs | 0 Content.Shared/{Nyanotrasen => }/Psionics/Events.cs | 0 .../{Nyanotrasen => }/Psionics/Glimmer/GlimmerSystem.cs | 0 .../Psionics/Glimmer/SharedGlimmerReactiveComponent.cs | 0 .../Psionics/Glimmer/SharedGlimmerReactiveVisuals.cs | 0 .../Psionics/Items/ClothingGrantPsionicPowerComponent.cs | 0 .../Abilities => }/Psionics/Items/HeadCageComponent.cs | 0 .../Abilities => }/Psionics/Items/HeadCagedComponent.cs | 0 .../Abilities => }/Psionics/Items/PsionicItemsSystem.cs | 0 .../Abilities => }/Psionics/Items/TinfoilHatComponent.cs | 0 .../Abilities => }/Psionics/PsionicComponent.cs | 0 .../Abilities => }/Psionics/PsionicInsulationComponent.cs | 0 .../Abilities => }/Psionics/PsionicsDisabledComponent.cs | 0 .../Psionics/SharedPsionicAbilitiesSystem.cs | 0 Content.Shared/{Nyanotrasen => }/Soul/GolemMessages.cs | 0 .../{Nyanotrasen => }/Soul/GunHeldByGolemComponent.cs | 0 .../{Nyanotrasen => }/Soul/SharedGolemComponent.cs | 0 .../{Nyanotrasen => }/Soul/SharedGolemSystem.cs | 0 111 files changed, 14 insertions(+), 18 deletions(-) rename Content.Client/{Nyanotrasen => }/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs (88%) rename Content.Client/{Nyanotrasen => }/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml (93%) rename Content.Client/{Nyanotrasen => }/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml.cs (96%) rename Content.Client/{Nyanotrasen => }/Chat/PsionicChatUpdateSystem.cs (96%) rename Content.Client/{Nyanotrasen => }/Psionics/Glimmer/GlimmerReactiveVisuals.cs (100%) rename Content.Client/{Nyanotrasen => }/Psionics/UI/AcceptPsionicsEUI.cs (100%) rename Content.Client/{Nyanotrasen => }/Psionics/UI/AcceptPsionicsWindow.cs (100%) rename Content.Client/{Nyanotrasen => }/UserInterface/GlimmerGraph.cs (97%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/DispelPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/MetapsionicPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/MindSwapPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/MindSwappedComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/NoosphericZapPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/PsionicRegenerationPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/PyrokinesisPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/Abilities/TelegnosisPowerSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Abilities/Psionics/PsionicAbilitiesSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Audio/GlimmerSoundComponent.cs (100%) rename Content.Server/{Nyanotrasen/CartridgeLoader => CartridgeLoader/Cartridges}/GlimmerMonitorCartridgeComponent.cs (100%) rename Content.Server/{Nyanotrasen/CartridgeLoader => CartridgeLoader/Cartridges}/GlimmerMonitorCartridgeSystem.cs (100%) rename Content.Server/{Nyanotrasen/Chat => Chat/Commands}/TSayCommand.cs (100%) rename Content.Server/{Nyanotrasen/Chat/NyanoChatSystem.cs => Chat/TelepathicChatSystem.cs} (97%) rename Content.Server/{Nyanotrasen => }/Chat/TelepathicRepeaterComponent.cs (83%) rename Content.Server/{Nyanotrasen => }/Psionics/AcceptPsionicsEui.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/AntiPsychicWeaponComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Dreams/DreamSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Glimmer/GlimmerCommands.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Glimmer/GlimmerReactiveSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Invisibility/PsionicInvisibilitySystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/Invisibility/PsionicallyInvisibleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/PotentialPsionicComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/PsionicAwaitingPlayerComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/PsionicBonusChanceComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/PsionicsCommands.cs (100%) rename Content.Server/{Nyanotrasen => }/Psionics/PsionicsSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/FreeProberRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/GlimmerEventComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/GlimmerRandomSentienceRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/GlimmerRevenantSpawnRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/GlimmerWispRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/MassMindSwapRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/MundaneDischargeRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/NoosphericFryRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/NoosphericStormRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/NoosphericZapRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Components/PsionicCatGotYourTongueRuleComponent.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/FreeProberRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/GlimmerEventSystem.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/GlimmerRandomSentienceRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/GlimmerRevenantSpawnRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/GlimmerWispSpawnRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/MassMindSwapRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/MundaneDischargeRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/NoosphericFryRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/NoosphericStormRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/NoosphericZapRule.cs (100%) rename Content.Server/{Nyanotrasen => }/StationEvents/Events/PsionicCatGotYourTongueRule.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/DispelPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/EatMouseActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/HairballActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/MassSleepPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/MetapsionicPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/MindSwapPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/NoosphericZapPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/PsionicInvisibilityPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/PsionicRegenerationPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/PyrokinesisPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/RemovePsionicInvisibilityOffPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Actions/Events/TelegnosisPowerActionEvent.cs (100%) rename Content.Shared/{Nyanotrasen => }/CartridgeLoader/Cartridges/GlimmerMonitorUiState.cs (100%) rename Content.Shared/{Nyanotrasen => }/Chapel/SacrificeDoAfterEvent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/AcceptPsionicsEuiMessage.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/Dispel/DamageOnDispelComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/Dispel/DispelPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/Dispel/DispellableComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/Metapsionics/MetapsionicPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/MindSwap/MindSwapPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/NoosphericZap/NoosphericZapPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/Telegnosis/TelegnosisPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Abilities/Telegnosis/TelegnosticProjectionComponent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Psionics/Events.cs (100%) rename Content.Shared/{Nyanotrasen => }/Psionics/Glimmer/GlimmerSystem.cs (100%) rename Content.Shared/{Nyanotrasen => }/Psionics/Glimmer/SharedGlimmerReactiveComponent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Psionics/Glimmer/SharedGlimmerReactiveVisuals.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Items/ClothingGrantPsionicPowerComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Items/HeadCageComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Items/HeadCagedComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Items/PsionicItemsSystem.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/Items/TinfoilHatComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/PsionicComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/PsionicInsulationComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/PsionicsDisabledComponent.cs (100%) rename Content.Shared/{Nyanotrasen/Abilities => }/Psionics/SharedPsionicAbilitiesSystem.cs (100%) rename Content.Shared/{Nyanotrasen => }/Soul/GolemMessages.cs (100%) rename Content.Shared/{Nyanotrasen => }/Soul/GunHeldByGolemComponent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Soul/SharedGolemComponent.cs (100%) rename Content.Shared/{Nyanotrasen => }/Soul/SharedGolemSystem.cs (100%) diff --git a/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs b/Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs similarity index 88% rename from Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs rename to Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs index 0b5fc7ad38c..9ef968e43b1 100644 --- a/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs +++ b/Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs @@ -1,10 +1,9 @@ -using Robust.Client.GameObjects; -using Robust.Client.UserInterface; +using Robust.Client.UserInterface; using Content.Client.UserInterface.Fragments; using Content.Shared.CartridgeLoader.Cartridges; using Content.Shared.CartridgeLoader; -namespace Content.Client.Nyanotrasen.CartridgeLoader.Cartridges; +namespace Content.Client.CartridgeLoader.Cartridges; public sealed partial class GlimmerMonitorUi : UIFragment { diff --git a/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml b/Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml similarity index 93% rename from Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml rename to Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml index 119a1831e6e..e09a422ddf7 100644 --- a/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml +++ b/Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml @@ -1,4 +1,4 @@ - diff --git a/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml.cs b/Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml.cs similarity index 96% rename from Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml.cs rename to Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml.cs index 43d9202aa45..3325c0d379e 100644 --- a/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml.cs +++ b/Content.Client/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml.cs @@ -1,12 +1,12 @@ using System.Linq; using System.Numerics; -using Content.Client.Nyanotrasen.UserInterface; +using Content.Client.UserInterface; using Robust.Client.AutoGenerated; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; -namespace Content.Client.Nyanotrasen.CartridgeLoader.Cartridges; +namespace Content.Client.CartridgeLoader.Cartridges; [GenerateTypedNameReferences] public sealed partial class GlimmerMonitorUiFragment : BoxContainer diff --git a/Content.Client/Nyanotrasen/Chat/PsionicChatUpdateSystem.cs b/Content.Client/Chat/PsionicChatUpdateSystem.cs similarity index 96% rename from Content.Client/Nyanotrasen/Chat/PsionicChatUpdateSystem.cs rename to Content.Client/Chat/PsionicChatUpdateSystem.cs index 84602052fe7..066501acb78 100644 --- a/Content.Client/Nyanotrasen/Chat/PsionicChatUpdateSystem.cs +++ b/Content.Client/Chat/PsionicChatUpdateSystem.cs @@ -2,7 +2,7 @@ using Content.Client.Chat.Managers; using Robust.Client.Player; -namespace Content.Client.Nyanotrasen.Chat +namespace Content.Client.Chat { public sealed class PsionicChatUpdateSystem : EntitySystem { diff --git a/Content.Client/Nyanotrasen/Psionics/Glimmer/GlimmerReactiveVisuals.cs b/Content.Client/Psionics/Glimmer/GlimmerReactiveVisuals.cs similarity index 100% rename from Content.Client/Nyanotrasen/Psionics/Glimmer/GlimmerReactiveVisuals.cs rename to Content.Client/Psionics/Glimmer/GlimmerReactiveVisuals.cs diff --git a/Content.Client/Nyanotrasen/Psionics/UI/AcceptPsionicsEUI.cs b/Content.Client/Psionics/UI/AcceptPsionicsEUI.cs similarity index 100% rename from Content.Client/Nyanotrasen/Psionics/UI/AcceptPsionicsEUI.cs rename to Content.Client/Psionics/UI/AcceptPsionicsEUI.cs diff --git a/Content.Client/Nyanotrasen/Psionics/UI/AcceptPsionicsWindow.cs b/Content.Client/Psionics/UI/AcceptPsionicsWindow.cs similarity index 100% rename from Content.Client/Nyanotrasen/Psionics/UI/AcceptPsionicsWindow.cs rename to Content.Client/Psionics/UI/AcceptPsionicsWindow.cs diff --git a/Content.Client/Nyanotrasen/UserInterface/GlimmerGraph.cs b/Content.Client/UserInterface/GlimmerGraph.cs similarity index 97% rename from Content.Client/Nyanotrasen/UserInterface/GlimmerGraph.cs rename to Content.Client/UserInterface/GlimmerGraph.cs index c4a9109dcd8..188ebe2475b 100644 --- a/Content.Client/Nyanotrasen/UserInterface/GlimmerGraph.cs +++ b/Content.Client/UserInterface/GlimmerGraph.cs @@ -4,7 +4,7 @@ using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; -namespace Content.Client.Nyanotrasen.UserInterface; +namespace Content.Client.UserInterface; public sealed class GlimmerGraph : Control { diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index 138dc9e52be..bc79283d76e 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -38,7 +38,6 @@ using Robust.Shared.Replays; using Robust.Shared.Timing; using Robust.Shared.Utility; -using Content.Client.Nyanotrasen.Chat; //Nyano - Summary: chat namespace. namespace Content.Client.UserInterface.Systems.Chat; diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/DispelPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/DispelPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/DispelPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/DispelPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/MetapsionicPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/MetapsionicPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/MetapsionicPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/MetapsionicPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/MindSwapPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/MindSwapPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/MindSwapPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/MindSwapPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/MindSwappedComponent.cs b/Content.Server/Abilities/Psionics/Abilities/MindSwappedComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/MindSwappedComponent.cs rename to Content.Server/Abilities/Psionics/Abilities/MindSwappedComponent.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/NoosphericZapPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/NoosphericZapPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/NoosphericZapPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/NoosphericZapPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/PsionicRegenerationPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/PsionicRegenerationPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/PsionicRegenerationPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/PsionicRegenerationPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/PyrokinesisPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/PyrokinesisPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/PyrokinesisPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/PyrokinesisPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/TelegnosisPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/TelegnosisPowerSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/TelegnosisPowerSystem.cs rename to Content.Server/Abilities/Psionics/Abilities/TelegnosisPowerSystem.cs diff --git a/Content.Server/Nyanotrasen/Abilities/Psionics/PsionicAbilitiesSystem.cs b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Abilities/Psionics/PsionicAbilitiesSystem.cs rename to Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs diff --git a/Content.Server/Nyanotrasen/Audio/GlimmerSoundComponent.cs b/Content.Server/Audio/GlimmerSoundComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Audio/GlimmerSoundComponent.cs rename to Content.Server/Audio/GlimmerSoundComponent.cs diff --git a/Content.Server/Nyanotrasen/CartridgeLoader/GlimmerMonitorCartridgeComponent.cs b/Content.Server/CartridgeLoader/Cartridges/GlimmerMonitorCartridgeComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/CartridgeLoader/GlimmerMonitorCartridgeComponent.cs rename to Content.Server/CartridgeLoader/Cartridges/GlimmerMonitorCartridgeComponent.cs diff --git a/Content.Server/Nyanotrasen/CartridgeLoader/GlimmerMonitorCartridgeSystem.cs b/Content.Server/CartridgeLoader/Cartridges/GlimmerMonitorCartridgeSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/CartridgeLoader/GlimmerMonitorCartridgeSystem.cs rename to Content.Server/CartridgeLoader/Cartridges/GlimmerMonitorCartridgeSystem.cs diff --git a/Content.Server/Nyanotrasen/Chat/TSayCommand.cs b/Content.Server/Chat/Commands/TSayCommand.cs similarity index 100% rename from Content.Server/Nyanotrasen/Chat/TSayCommand.cs rename to Content.Server/Chat/Commands/TSayCommand.cs diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index b41d2deda6f..b4641928e48 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -8,7 +8,7 @@ using Content.Server.Language; using Content.Server.Speech.Components; using Content.Server.Speech.EntitySystems; -using Content.Server.Nyanotrasen.Chat; +using Content.Server.Chat; using Content.Server.Station.Components; using Content.Server.Station.Systems; using Content.Shared.ActionBlocker; @@ -69,9 +69,7 @@ public sealed partial class ChatSystem : SharedChatSystem [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly ReplacementAccentSystem _wordreplacement = default!; [Dependency] private readonly LanguageSystem _language = default!; - - //Nyano - Summary: pulls in the nyano chat system for psionics. - [Dependency] private readonly NyanoChatSystem _nyanoChatSystem = default!; + [Dependency] private readonly TelepathicChatSystem _telepath = default!; public const int VoiceRange = 10; // how far voice goes in world units public const int WhisperClearRange = 2; // how far whisper goes while still being understandable, in world units @@ -277,7 +275,7 @@ public void TrySendInGameICMessage( break; //Nyano - Summary: case adds the telepathic chat sending ability. case InGameICChatType.Telepathic: - _nyanoChatSystem.SendTelepathicChat(source, message, range == ChatTransmitRange.HideChat); + _telepath.SendTelepathicChat(source, message, range == ChatTransmitRange.HideChat); break; } } diff --git a/Content.Server/Nyanotrasen/Chat/NyanoChatSystem.cs b/Content.Server/Chat/TelepathicChatSystem.cs similarity index 97% rename from Content.Server/Nyanotrasen/Chat/NyanoChatSystem.cs rename to Content.Server/Chat/TelepathicChatSystem.cs index 58ed1782741..8d44ead9d07 100644 --- a/Content.Server/Nyanotrasen/Chat/NyanoChatSystem.cs +++ b/Content.Server/Chat/TelepathicChatSystem.cs @@ -16,13 +16,13 @@ using System.Linq; using System.Text; -namespace Content.Server.Nyanotrasen.Chat +namespace Content.Server.Chat { /// - /// Extensions for nyano's chat stuff + /// Extensions for Telepathic chat stuff /// - public sealed class NyanoChatSystem : EntitySystem + public sealed class TelepathicChatSystem : EntitySystem { [Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly IChatManager _chatManager = default!; diff --git a/Content.Server/Nyanotrasen/Chat/TelepathicRepeaterComponent.cs b/Content.Server/Chat/TelepathicRepeaterComponent.cs similarity index 83% rename from Content.Server/Nyanotrasen/Chat/TelepathicRepeaterComponent.cs rename to Content.Server/Chat/TelepathicRepeaterComponent.cs index fc199f4332a..2183fafd4d1 100644 --- a/Content.Server/Nyanotrasen/Chat/TelepathicRepeaterComponent.cs +++ b/Content.Server/Chat/TelepathicRepeaterComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server.Nyanotrasen.Chat +namespace Content.Server.Chat { /// /// Repeats whatever is happening in telepathic chat. diff --git a/Content.Server/Nyanotrasen/Psionics/AcceptPsionicsEui.cs b/Content.Server/Psionics/AcceptPsionicsEui.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/AcceptPsionicsEui.cs rename to Content.Server/Psionics/AcceptPsionicsEui.cs diff --git a/Content.Server/Nyanotrasen/Psionics/AntiPsychicWeaponComponent.cs b/Content.Server/Psionics/AntiPsychicWeaponComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/AntiPsychicWeaponComponent.cs rename to Content.Server/Psionics/AntiPsychicWeaponComponent.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Dreams/DreamSystem.cs b/Content.Server/Psionics/Dreams/DreamSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Dreams/DreamSystem.cs rename to Content.Server/Psionics/Dreams/DreamSystem.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Glimmer/GlimmerCommands.cs b/Content.Server/Psionics/Glimmer/GlimmerCommands.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Glimmer/GlimmerCommands.cs rename to Content.Server/Psionics/Glimmer/GlimmerCommands.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Glimmer/GlimmerReactiveSystem.cs b/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Glimmer/GlimmerReactiveSystem.cs rename to Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs b/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs rename to Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs rename to Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs rename to Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicInvisibilitySystem.cs b/Content.Server/Psionics/Invisibility/PsionicInvisibilitySystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicInvisibilitySystem.cs rename to Content.Server/Psionics/Invisibility/PsionicInvisibilitySystem.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs b/Content.Server/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs rename to Content.Server/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs b/Content.Server/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs rename to Content.Server/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs diff --git a/Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicallyInvisibleComponent.cs b/Content.Server/Psionics/Invisibility/PsionicallyInvisibleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/Invisibility/PsionicallyInvisibleComponent.cs rename to Content.Server/Psionics/Invisibility/PsionicallyInvisibleComponent.cs diff --git a/Content.Server/Nyanotrasen/Psionics/PotentialPsionicComponent.cs b/Content.Server/Psionics/PotentialPsionicComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/PotentialPsionicComponent.cs rename to Content.Server/Psionics/PotentialPsionicComponent.cs diff --git a/Content.Server/Nyanotrasen/Psionics/PsionicAwaitingPlayerComponent.cs b/Content.Server/Psionics/PsionicAwaitingPlayerComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/PsionicAwaitingPlayerComponent.cs rename to Content.Server/Psionics/PsionicAwaitingPlayerComponent.cs diff --git a/Content.Server/Nyanotrasen/Psionics/PsionicBonusChanceComponent.cs b/Content.Server/Psionics/PsionicBonusChanceComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/PsionicBonusChanceComponent.cs rename to Content.Server/Psionics/PsionicBonusChanceComponent.cs diff --git a/Content.Server/Nyanotrasen/Psionics/PsionicsCommands.cs b/Content.Server/Psionics/PsionicsCommands.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/PsionicsCommands.cs rename to Content.Server/Psionics/PsionicsCommands.cs diff --git a/Content.Server/Nyanotrasen/Psionics/PsionicsSystem.cs b/Content.Server/Psionics/PsionicsSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/Psionics/PsionicsSystem.cs rename to Content.Server/Psionics/PsionicsSystem.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/FreeProberRuleComponent.cs b/Content.Server/StationEvents/Components/FreeProberRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/FreeProberRuleComponent.cs rename to Content.Server/StationEvents/Components/FreeProberRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/GlimmerEventComponent.cs b/Content.Server/StationEvents/Components/GlimmerEventComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/GlimmerEventComponent.cs rename to Content.Server/StationEvents/Components/GlimmerEventComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/GlimmerRandomSentienceRuleComponent.cs b/Content.Server/StationEvents/Components/GlimmerRandomSentienceRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/GlimmerRandomSentienceRuleComponent.cs rename to Content.Server/StationEvents/Components/GlimmerRandomSentienceRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/GlimmerRevenantSpawnRuleComponent.cs b/Content.Server/StationEvents/Components/GlimmerRevenantSpawnRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/GlimmerRevenantSpawnRuleComponent.cs rename to Content.Server/StationEvents/Components/GlimmerRevenantSpawnRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/GlimmerWispRuleComponent.cs b/Content.Server/StationEvents/Components/GlimmerWispRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/GlimmerWispRuleComponent.cs rename to Content.Server/StationEvents/Components/GlimmerWispRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/MassMindSwapRuleComponent.cs b/Content.Server/StationEvents/Components/MassMindSwapRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/MassMindSwapRuleComponent.cs rename to Content.Server/StationEvents/Components/MassMindSwapRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/MundaneDischargeRuleComponent.cs b/Content.Server/StationEvents/Components/MundaneDischargeRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/MundaneDischargeRuleComponent.cs rename to Content.Server/StationEvents/Components/MundaneDischargeRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/NoosphericFryRuleComponent.cs b/Content.Server/StationEvents/Components/NoosphericFryRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/NoosphericFryRuleComponent.cs rename to Content.Server/StationEvents/Components/NoosphericFryRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/NoosphericStormRuleComponent.cs b/Content.Server/StationEvents/Components/NoosphericStormRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/NoosphericStormRuleComponent.cs rename to Content.Server/StationEvents/Components/NoosphericStormRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/NoosphericZapRuleComponent.cs b/Content.Server/StationEvents/Components/NoosphericZapRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/NoosphericZapRuleComponent.cs rename to Content.Server/StationEvents/Components/NoosphericZapRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Components/PsionicCatGotYourTongueRuleComponent.cs b/Content.Server/StationEvents/Components/PsionicCatGotYourTongueRuleComponent.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Components/PsionicCatGotYourTongueRuleComponent.cs rename to Content.Server/StationEvents/Components/PsionicCatGotYourTongueRuleComponent.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/FreeProberRule.cs b/Content.Server/StationEvents/Events/FreeProberRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/FreeProberRule.cs rename to Content.Server/StationEvents/Events/FreeProberRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerEventSystem.cs b/Content.Server/StationEvents/Events/GlimmerEventSystem.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/GlimmerEventSystem.cs rename to Content.Server/StationEvents/Events/GlimmerEventSystem.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerRandomSentienceRule.cs b/Content.Server/StationEvents/Events/GlimmerRandomSentienceRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/GlimmerRandomSentienceRule.cs rename to Content.Server/StationEvents/Events/GlimmerRandomSentienceRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerRevenantSpawnRule.cs b/Content.Server/StationEvents/Events/GlimmerRevenantSpawnRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/GlimmerRevenantSpawnRule.cs rename to Content.Server/StationEvents/Events/GlimmerRevenantSpawnRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/GlimmerWispSpawnRule.cs b/Content.Server/StationEvents/Events/GlimmerWispSpawnRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/GlimmerWispSpawnRule.cs rename to Content.Server/StationEvents/Events/GlimmerWispSpawnRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/MassMindSwapRule.cs b/Content.Server/StationEvents/Events/MassMindSwapRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/MassMindSwapRule.cs rename to Content.Server/StationEvents/Events/MassMindSwapRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/MundaneDischargeRule.cs b/Content.Server/StationEvents/Events/MundaneDischargeRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/MundaneDischargeRule.cs rename to Content.Server/StationEvents/Events/MundaneDischargeRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs b/Content.Server/StationEvents/Events/NoosphericFryRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs rename to Content.Server/StationEvents/Events/NoosphericFryRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericStormRule.cs b/Content.Server/StationEvents/Events/NoosphericStormRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/NoosphericStormRule.cs rename to Content.Server/StationEvents/Events/NoosphericStormRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericZapRule.cs b/Content.Server/StationEvents/Events/NoosphericZapRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/NoosphericZapRule.cs rename to Content.Server/StationEvents/Events/NoosphericZapRule.cs diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/PsionicCatGotYourTongueRule.cs b/Content.Server/StationEvents/Events/PsionicCatGotYourTongueRule.cs similarity index 100% rename from Content.Server/Nyanotrasen/StationEvents/Events/PsionicCatGotYourTongueRule.cs rename to Content.Server/StationEvents/Events/PsionicCatGotYourTongueRule.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/DispelPowerActionEvent.cs b/Content.Shared/Actions/Events/DispelPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/DispelPowerActionEvent.cs rename to Content.Shared/Actions/Events/DispelPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/EatMouseActionEvent.cs b/Content.Shared/Actions/Events/EatMouseActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/EatMouseActionEvent.cs rename to Content.Shared/Actions/Events/EatMouseActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/HairballActionEvent.cs b/Content.Shared/Actions/Events/HairballActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/HairballActionEvent.cs rename to Content.Shared/Actions/Events/HairballActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/MassSleepPowerActionEvent.cs b/Content.Shared/Actions/Events/MassSleepPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/MassSleepPowerActionEvent.cs rename to Content.Shared/Actions/Events/MassSleepPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/MetapsionicPowerActionEvent.cs b/Content.Shared/Actions/Events/MetapsionicPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/MetapsionicPowerActionEvent.cs rename to Content.Shared/Actions/Events/MetapsionicPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/MindSwapPowerActionEvent.cs b/Content.Shared/Actions/Events/MindSwapPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/MindSwapPowerActionEvent.cs rename to Content.Shared/Actions/Events/MindSwapPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/NoosphericZapPowerActionEvent.cs b/Content.Shared/Actions/Events/NoosphericZapPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/NoosphericZapPowerActionEvent.cs rename to Content.Shared/Actions/Events/NoosphericZapPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/PsionicInvisibilityPowerActionEvent.cs b/Content.Shared/Actions/Events/PsionicInvisibilityPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/PsionicInvisibilityPowerActionEvent.cs rename to Content.Shared/Actions/Events/PsionicInvisibilityPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/PsionicRegenerationPowerActionEvent.cs b/Content.Shared/Actions/Events/PsionicRegenerationPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/PsionicRegenerationPowerActionEvent.cs rename to Content.Shared/Actions/Events/PsionicRegenerationPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/PyrokinesisPowerActionEvent.cs b/Content.Shared/Actions/Events/PyrokinesisPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/PyrokinesisPowerActionEvent.cs rename to Content.Shared/Actions/Events/PyrokinesisPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/RemovePsionicInvisibilityOffPowerActionEvent.cs b/Content.Shared/Actions/Events/RemovePsionicInvisibilityOffPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/RemovePsionicInvisibilityOffPowerActionEvent.cs rename to Content.Shared/Actions/Events/RemovePsionicInvisibilityOffPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/Actions/Events/TelegnosisPowerActionEvent.cs b/Content.Shared/Actions/Events/TelegnosisPowerActionEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Actions/Events/TelegnosisPowerActionEvent.cs rename to Content.Shared/Actions/Events/TelegnosisPowerActionEvent.cs diff --git a/Content.Shared/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiState.cs b/Content.Shared/CartridgeLoader/Cartridges/GlimmerMonitorUiState.cs similarity index 100% rename from Content.Shared/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiState.cs rename to Content.Shared/CartridgeLoader/Cartridges/GlimmerMonitorUiState.cs diff --git a/Content.Shared/Nyanotrasen/Chapel/SacrificeDoAfterEvent.cs b/Content.Shared/Chapel/SacrificeDoAfterEvent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Chapel/SacrificeDoAfterEvent.cs rename to Content.Shared/Chapel/SacrificeDoAfterEvent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/AcceptPsionicsEuiMessage.cs b/Content.Shared/Psionics/Abilities/AcceptPsionicsEuiMessage.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/AcceptPsionicsEuiMessage.cs rename to Content.Shared/Psionics/Abilities/AcceptPsionicsEuiMessage.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Dispel/DamageOnDispelComponent.cs b/Content.Shared/Psionics/Abilities/Dispel/DamageOnDispelComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Dispel/DamageOnDispelComponent.cs rename to Content.Shared/Psionics/Abilities/Dispel/DamageOnDispelComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Dispel/DispelPowerComponent.cs b/Content.Shared/Psionics/Abilities/Dispel/DispelPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Dispel/DispelPowerComponent.cs rename to Content.Shared/Psionics/Abilities/Dispel/DispelPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Dispel/DispellableComponent.cs b/Content.Shared/Psionics/Abilities/Dispel/DispellableComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Dispel/DispellableComponent.cs rename to Content.Shared/Psionics/Abilities/Dispel/DispellableComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs b/Content.Shared/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs rename to Content.Shared/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs b/Content.Shared/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs rename to Content.Shared/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Metapsionics/MetapsionicPowerComponent.cs b/Content.Shared/Psionics/Abilities/Metapsionics/MetapsionicPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Metapsionics/MetapsionicPowerComponent.cs rename to Content.Shared/Psionics/Abilities/Metapsionics/MetapsionicPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MindSwap/MindSwapPowerComponent.cs b/Content.Shared/Psionics/Abilities/MindSwap/MindSwapPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MindSwap/MindSwapPowerComponent.cs rename to Content.Shared/Psionics/Abilities/MindSwap/MindSwapPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/NoosphericZap/NoosphericZapPowerComponent.cs b/Content.Shared/Psionics/Abilities/NoosphericZap/NoosphericZapPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/NoosphericZap/NoosphericZapPowerComponent.cs rename to Content.Shared/Psionics/Abilities/NoosphericZap/NoosphericZapPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerComponent.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerComponent.cs rename to Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs rename to Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs b/Content.Shared/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs rename to Content.Shared/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs b/Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs rename to Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Telegnosis/TelegnosisPowerComponent.cs b/Content.Shared/Psionics/Abilities/Telegnosis/TelegnosisPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Telegnosis/TelegnosisPowerComponent.cs rename to Content.Shared/Psionics/Abilities/Telegnosis/TelegnosisPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Telegnosis/TelegnosticProjectionComponent.cs b/Content.Shared/Psionics/Abilities/Telegnosis/TelegnosticProjectionComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Telegnosis/TelegnosticProjectionComponent.cs rename to Content.Shared/Psionics/Abilities/Telegnosis/TelegnosticProjectionComponent.cs diff --git a/Content.Shared/Nyanotrasen/Psionics/Events.cs b/Content.Shared/Psionics/Events.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Psionics/Events.cs rename to Content.Shared/Psionics/Events.cs diff --git a/Content.Shared/Nyanotrasen/Psionics/Glimmer/GlimmerSystem.cs b/Content.Shared/Psionics/Glimmer/GlimmerSystem.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Psionics/Glimmer/GlimmerSystem.cs rename to Content.Shared/Psionics/Glimmer/GlimmerSystem.cs diff --git a/Content.Shared/Nyanotrasen/Psionics/Glimmer/SharedGlimmerReactiveComponent.cs b/Content.Shared/Psionics/Glimmer/SharedGlimmerReactiveComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Psionics/Glimmer/SharedGlimmerReactiveComponent.cs rename to Content.Shared/Psionics/Glimmer/SharedGlimmerReactiveComponent.cs diff --git a/Content.Shared/Nyanotrasen/Psionics/Glimmer/SharedGlimmerReactiveVisuals.cs b/Content.Shared/Psionics/Glimmer/SharedGlimmerReactiveVisuals.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Psionics/Glimmer/SharedGlimmerReactiveVisuals.cs rename to Content.Shared/Psionics/Glimmer/SharedGlimmerReactiveVisuals.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Items/ClothingGrantPsionicPowerComponent.cs b/Content.Shared/Psionics/Items/ClothingGrantPsionicPowerComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Items/ClothingGrantPsionicPowerComponent.cs rename to Content.Shared/Psionics/Items/ClothingGrantPsionicPowerComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Items/HeadCageComponent.cs b/Content.Shared/Psionics/Items/HeadCageComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Items/HeadCageComponent.cs rename to Content.Shared/Psionics/Items/HeadCageComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Items/HeadCagedComponent.cs b/Content.Shared/Psionics/Items/HeadCagedComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Items/HeadCagedComponent.cs rename to Content.Shared/Psionics/Items/HeadCagedComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Items/PsionicItemsSystem.cs b/Content.Shared/Psionics/Items/PsionicItemsSystem.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Items/PsionicItemsSystem.cs rename to Content.Shared/Psionics/Items/PsionicItemsSystem.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Items/TinfoilHatComponent.cs b/Content.Shared/Psionics/Items/TinfoilHatComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/Items/TinfoilHatComponent.cs rename to Content.Shared/Psionics/Items/TinfoilHatComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/PsionicComponent.cs b/Content.Shared/Psionics/PsionicComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/PsionicComponent.cs rename to Content.Shared/Psionics/PsionicComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/PsionicInsulationComponent.cs b/Content.Shared/Psionics/PsionicInsulationComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/PsionicInsulationComponent.cs rename to Content.Shared/Psionics/PsionicInsulationComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/PsionicsDisabledComponent.cs b/Content.Shared/Psionics/PsionicsDisabledComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/PsionicsDisabledComponent.cs rename to Content.Shared/Psionics/PsionicsDisabledComponent.cs diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/SharedPsionicAbilitiesSystem.cs b/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Abilities/Psionics/SharedPsionicAbilitiesSystem.cs rename to Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs diff --git a/Content.Shared/Nyanotrasen/Soul/GolemMessages.cs b/Content.Shared/Soul/GolemMessages.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Soul/GolemMessages.cs rename to Content.Shared/Soul/GolemMessages.cs diff --git a/Content.Shared/Nyanotrasen/Soul/GunHeldByGolemComponent.cs b/Content.Shared/Soul/GunHeldByGolemComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Soul/GunHeldByGolemComponent.cs rename to Content.Shared/Soul/GunHeldByGolemComponent.cs diff --git a/Content.Shared/Nyanotrasen/Soul/SharedGolemComponent.cs b/Content.Shared/Soul/SharedGolemComponent.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Soul/SharedGolemComponent.cs rename to Content.Shared/Soul/SharedGolemComponent.cs diff --git a/Content.Shared/Nyanotrasen/Soul/SharedGolemSystem.cs b/Content.Shared/Soul/SharedGolemSystem.cs similarity index 100% rename from Content.Shared/Nyanotrasen/Soul/SharedGolemSystem.cs rename to Content.Shared/Soul/SharedGolemSystem.cs From f79c6db8c9549bb595423205004893ed59cb1f8d Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Thu, 8 Aug 2024 07:38:33 +0800 Subject: [PATCH 040/135] New Trait: Sluggish / Snail-Paced (#692) # Description This PR adds two new negative traits that decrease your movement speed: **Sluggish** and **Snail-Paced**. - Sluggish (+1 points) - 15% slower movement speed - 35% slower climbing speed (for standard tables, from 1.5s to ~2.02 seconds) - Cooldown on laying down/standing up increased from 2.5 seconds to 3 seconds - Snail-Paced (+2 points) - 30% slower movement speed - 66% slower climbing speed (for standard tables, from 1.5s to ~2.48 seconds) - Cooldown on laying down/standing up increased from 2.5 seconds to 4 seconds ## Media
Expand **Trait entry** ![image](https://github.com/user-attachments/assets/cb483536-ec3e-4c28-a4b4-c431bb1b669e) ![image](https://github.com/user-attachments/assets/a251844e-7058-4d4b-b21d-a5637c39489f)
# Changelog :cl: Skubman - add: Add two new negative traits: Sluggish (+1) and Snail-Paced (+2) that make you move slower, and climb tables slower. --------- Signed-off-by: Angelo Fallaria Co-authored-by: VMSolidus --- .../Assorted/TraitSpeedModifierComponent.cs | 14 +++++++ .../Assorted/TraitSpeedModifierSystem.cs | 19 ++++++++++ Resources/Locale/en-US/traits/traits.ftl | 12 +++++- Resources/Prototypes/Traits/disabilities.yml | 38 +++++++++++++++++++ Resources/Prototypes/Traits/skills.yml | 6 +++ 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 Content.Server/Traits/Assorted/TraitSpeedModifierComponent.cs create mode 100644 Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs diff --git a/Content.Server/Traits/Assorted/TraitSpeedModifierComponent.cs b/Content.Server/Traits/Assorted/TraitSpeedModifierComponent.cs new file mode 100644 index 00000000000..6acb32e6c1d --- /dev/null +++ b/Content.Server/Traits/Assorted/TraitSpeedModifierComponent.cs @@ -0,0 +1,14 @@ +namespace Content.Server.Traits.Assorted; + +/// +/// This component is used for traits that modify movement speed. +/// +[RegisterComponent] +public sealed partial class TraitSpeedModifierComponent : Component +{ + [DataField(required: true)] + public float WalkModifier = 1.0f; + + [DataField(required: true)] + public float SprintModifier = 1.0f; +} diff --git a/Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs b/Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs new file mode 100644 index 00000000000..c804592347a --- /dev/null +++ b/Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs @@ -0,0 +1,19 @@ +using Content.Shared.Movement.Systems; +using Content.Server.Traits.Assorted; + +namespace Content.Shared.Traits.Assorted; + +public sealed class TraitSpeedModifierSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRefreshMovementSpeed); + } + + private void OnRefreshMovementSpeed(EntityUid uid, TraitSpeedModifierComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.WalkModifier, component.SprintModifier); + } +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 3439ffcdc97..5fb361af01f 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -89,6 +89,16 @@ trait-description-ParkourTraining = Whether as a hobby, lifestyle, or professional training, you are trained in the discipline of parkour. You're faster with climbing, crawling, lying down, and getting up. +trait-name-Sluggish = Sluggish +trait-description-Sluggish = + You navigate the world slower than others, perhaps due to a medical condition, inactivity, or age. + You move slower, and it takes longer for you to climb, lie down and get up. + +trait-name-SnailPaced = Snail-Paced +trait-description-SnailPaced = + You walk at a snail's pace, perhaps due to a medical condition, mobility impairment, or age. + You move substantially slower, and it takes far longer for you to climb, lie down and get up. + trait-name-LightStep = Light Step trait-description-LightStep = You move with a gentle step, making your footsteps quieter. @@ -106,4 +116,4 @@ trait-description-Spearmaster = trait-name-WeaponsGeneralist = Weapons Generalist trait-description-WeaponsGeneralist = You are a jack of all trades with melee weapons, enabling you to be versatile with your weapon arsenal. - Your melee damage bonus for all Brute damage types (Blunt, Slash, Piercing) becomes 25%. \ No newline at end of file + Your melee damage bonus for all Brute damage types (Blunt, Slash, Piercing) becomes 25%. diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index afdd27f339d..c47a673f84a 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -95,6 +95,44 @@ components: - type: Snoring +- type: trait + id: Sluggish + category: Physical + points: 1 + requirements: + - !type:CharacterTraitRequirement + inverted: true + traits: + - ParkourTraining + - SnailPaced + components: + - type: TraitSpeedModifier + sprintModifier: 0.85 + walkModifier: 0.85 + - type: ClimbDelayModifier + climbDelayMultiplier: 1.35 + - type: LayingDownModifier + layingDownCooldownMultiplier: 1.2 + +- type: trait + id: SnailPaced + category: Physical + points: 2 + requirements: + - !type:CharacterTraitRequirement + inverted: true + traits: + - ParkourTraining + - Sluggish + components: + - type: TraitSpeedModifier + sprintModifier: 0.7 + walkModifier: 0.7 + - type: ClimbDelayModifier + climbDelayMultiplier: 1.66 + - type: LayingDownModifier + layingDownCooldownMultiplier: 1.6 + - type: trait id: BloodDeficiency category: Physical diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index 1a4242aff80..0da622da3c9 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -91,6 +91,12 @@ id: ParkourTraining category: Physical points: -3 + requirements: + - !type:CharacterTraitRequirement + inverted: true + traits: + - Sluggish + - SnailPaced components: - type: ClimbDelayModifier climbDelayMultiplier: 0.70 From 04330a4cc89906508db781503f55a2ea8084b770 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 23:38:58 +0000 Subject: [PATCH 041/135] Automatic Changelog Update (#692) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b7ab981fc63..6de7dc7bf17 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5073,3 +5073,11 @@ Entries: message: Readded Psionic Relay Orb id: 6235 time: '2024-08-07T23:16:30.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add two new negative traits: Sluggish (+1) and Snail-Paced (+2) that + make you move slower, and climb tables slower. + id: 6236 + time: '2024-08-07T23:38:33.0000000+00:00' From 54e59822b6098df2f399c67d3fb7f7b6e2f1cbdd Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Thu, 8 Aug 2024 07:39:52 +0800 Subject: [PATCH 042/135] New Trait: Hemophilia (#690) # Description **Hemophilia** is a +1 point negative Physical trait that makes you more susceptible to bleeding. You bleed twice as long, and you take 10% more Blunt damage. ## Media
Expand ![image](https://github.com/user-attachments/assets/ceb0e91e-73c8-4986-a566-40fb9cd0d32b)
--- # Changelog :cl: Skubman - add: Add the Hemophilia trait, a new negative trait for 1 point that makes you bleed twice as long and makes you take 10% more Blunt damage. --- .../Body/Components/BloodstreamComponent.cs | 2 +- Content.Server/Traits/HemophiliaComponent.cs | 21 ++++++++++++++ Content.Server/Traits/HemophiliaSystem.cs | 28 +++++++++++++++++++ Resources/Locale/en-US/traits/traits.ftl | 5 ++++ Resources/Prototypes/Traits/disabilities.yml | 17 +++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 Content.Server/Traits/HemophiliaComponent.cs create mode 100644 Content.Server/Traits/HemophiliaSystem.cs diff --git a/Content.Server/Body/Components/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs index 76eadb99fd8..dd93da9598c 100644 --- a/Content.Server/Body/Components/BloodstreamComponent.cs +++ b/Content.Server/Body/Components/BloodstreamComponent.cs @@ -12,7 +12,7 @@ namespace Content.Server.Body.Components { - [RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem), typeof(BloodDeficiencySystem))] + [RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem), typeof(BloodDeficiencySystem), typeof(HemophiliaSystem))] public sealed partial class BloodstreamComponent : Component { public static string DefaultChemicalsSolutionName = "chemicals"; diff --git a/Content.Server/Traits/HemophiliaComponent.cs b/Content.Server/Traits/HemophiliaComponent.cs new file mode 100644 index 00000000000..e8f1f57c6e5 --- /dev/null +++ b/Content.Server/Traits/HemophiliaComponent.cs @@ -0,0 +1,21 @@ +using Content.Shared.Damage; +namespace Content.Server.Traits.Assorted; + +/// +/// This is used for the Hemophilia trait. +/// +[RegisterComponent] +public sealed partial class HemophiliaComponent : Component +{ + // + // What the BleedReductionAmount should be multiplied by. + // + [DataField(required: true)] + public float BleedReductionModifier = 1f; + + /// + /// The damage increase from this trait. + /// + [DataField(required: true)] + public DamageModifierSet DamageModifiers = default!; +} diff --git a/Content.Server/Traits/HemophiliaSystem.cs b/Content.Server/Traits/HemophiliaSystem.cs new file mode 100644 index 00000000000..c70c7de37c0 --- /dev/null +++ b/Content.Server/Traits/HemophiliaSystem.cs @@ -0,0 +1,28 @@ +using Content.Server.Body.Systems; +using Content.Server.Body.Components; +using Content.Shared.Damage; + +namespace Content.Server.Traits.Assorted; + +public sealed class HemophiliaSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnDamageModify); + } + + private void OnStartup(EntityUid uid, HemophiliaComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var bloodstream)) + return; + + bloodstream.BleedReductionAmount *= component.BleedReductionModifier; + } + + private void OnDamageModify(EntityUid uid, HemophiliaComponent component, DamageModifyEvent args) + { + args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, component.DamageModifiers); + } +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 5fb361af01f..16cae663009 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -28,6 +28,11 @@ trait-description-BloodDeficiency = Your body loses more blood than it can replenish. You lose blood over time, and when left untreated you will eventually die from blood loss. +trait-name-Hemophilia = Hemophilia +trait-description-Hemophilia = + Your body's ability to form blood clots is impaired. + You bleed twice as long, and you have easy bruising, taking 10% more Blunt damage. + trait-name-Paracusia = Paracusia trait-description-Paracusia = You hear sounds that aren't really there diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index c47a673f84a..915ea0bf674 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -146,3 +146,20 @@ components: - type: BloodDeficiency # 0.07 = start taking bloodloss damage at around ~21.4 minutes, bloodLossAmount: 0.07 # then become crit ~10 minutes later + +- type: trait + id: Hemophilia + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + components: + - type: Hemophilia + bleedReductionModifier: 0.5 + damageModifiers: + coefficients: + Blunt: 1.1 From 0fc4051e4f1333da6d8b1ea57531230aa9e48b9b Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 23:40:16 +0000 Subject: [PATCH 043/135] Automatic Changelog Update (#690) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6de7dc7bf17..744677a1147 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5081,3 +5081,11 @@ Entries: make you move slower, and climb tables slower. id: 6236 time: '2024-08-07T23:38:33.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add the Hemophilia trait, a new negative trait for 1 point that makes + you bleed twice as long and makes you take 10% more Blunt damage. + id: 6237 + time: '2024-08-07T23:39:52.0000000+00:00' From c469961bf9944fdd37da2578f84211e51a075293 Mon Sep 17 00:00:00 2001 From: SleepyScarecrow <136123749+SleepyScarecrow@users.noreply.github.com> Date: Wed, 7 Aug 2024 19:51:29 -0400 Subject: [PATCH 044/135] Aloe Cream Recipe Fix, Now 15 Seconds (#688) # Description Changed the cooking time for aloe cream, so now it doesn't interfere with RegenerativeMesh any longer. # Changelog :cl: - fix: Fixed the RegenMesh recipe --- Resources/Prototypes/Recipes/Cooking/medical_recipes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Recipes/Cooking/medical_recipes.yml b/Resources/Prototypes/Recipes/Cooking/medical_recipes.yml index 9d1947f03eb..03ca5203582 100644 --- a/Resources/Prototypes/Recipes/Cooking/medical_recipes.yml +++ b/Resources/Prototypes/Recipes/Cooking/medical_recipes.yml @@ -2,7 +2,7 @@ id: RecipeAloeCream name: aloe cream recipe result: AloeCream - time: 10 + time: 15 solids: FoodAloe: 1 From 7ef43ac75251636175c535ea610118b9870704b8 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 23:51:52 +0000 Subject: [PATCH 045/135] Automatic Changelog Update (#688) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 744677a1147..bb19e08360c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5089,3 +5089,9 @@ Entries: you bleed twice as long and makes you take 10% more Blunt damage. id: 6237 time: '2024-08-07T23:39:52.0000000+00:00' +- author: SleepyScarecrow + changes: + - type: Fix + message: Fixed the RegenMesh recipe + id: 6238 + time: '2024-08-07T23:51:29.0000000+00:00' From f2e6d1a657588be369a9ac0c2a19c9a4962170af Mon Sep 17 00:00:00 2001 From: dootythefrooty <137359445+dootythefrooty@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:54:13 -0700 Subject: [PATCH 046/135] New Plant Trait : Bluespace Slips (#674) # Description Adds a new trait which plants can mutate to have. It teleports both the slippee and the produce to a random location within a radius determined by how potent the produce is. Inert unless the plant also has the slippery trait. ~~Probably very stinky code considering this is my first time dealing with c#.~~ ---

Media

https://github.com/user-attachments/assets/cd22756d-ea5e-4a30-8043-c991549c9019

--- # Changelog :cl: - add: Added Bluespace Slips, a plant trait that teleports you randomly if you slip. --- .../Components/TeleportingTraitComponent.cs | 31 +++++++++++ Content.Server/Botany/SeedPrototype.cs | 8 ++- .../Botany/Systems/BotanySystem.Seed.cs | 5 ++ .../Botany/Systems/MutationSystem.cs | 6 ++- .../Botany/Systems/TeleportingTraitSystem.cs | 51 +++++++++++++++++++ .../teleporting-trait-component.ftl | 1 + 6 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 Content.Server/Botany/Components/TeleportingTraitComponent.cs create mode 100644 Content.Server/Botany/Systems/TeleportingTraitSystem.cs create mode 100644 Resources/Locale/en-US/botany/components/teleporting-trait-component.ftl diff --git a/Content.Server/Botany/Components/TeleportingTraitComponent.cs b/Content.Server/Botany/Components/TeleportingTraitComponent.cs new file mode 100644 index 00000000000..b5f79ac8c7e --- /dev/null +++ b/Content.Server/Botany/Components/TeleportingTraitComponent.cs @@ -0,0 +1,31 @@ +namespace Content.Server.Botany +{ + [RegisterComponent] + + public sealed partial class TeleportingTraitComponent : Component + { + /// + /// Teleportation radius of produce. + /// + [DataField] + public float ProduceTeleportRadius; + + /// + /// How much to divide the potency. + /// + [DataField] + public float PotencyDivide = 10f; + + /// + /// Potency of fruit. + /// + [DataField] + public float Potency; + + /// + /// Chance of deletion. + /// + [DataField] + public float DeletionChance = .5f; + } +} diff --git a/Content.Server/Botany/SeedPrototype.cs b/Content.Server/Botany/SeedPrototype.cs index 1a3c0473a48..2644da2a3b0 100644 --- a/Content.Server/Botany/SeedPrototype.cs +++ b/Content.Server/Botany/SeedPrototype.cs @@ -205,6 +205,11 @@ public partial class SeedData ///
[DataField("ligneous")] public bool Ligneous; + /// + /// If true, teleports both fruit and player if slippable. + /// + [DataField] public bool Teleporting; + // No, I'm not removing these. // if you re-add these, make sure that they get cloned. //public PlantSpread Spread { get; set; } @@ -215,7 +220,6 @@ public partial class SeedData //public bool Hematophage { get; set; } //public bool Thorny { get; set; } //public bool Stinging { get; set; } - // public bool Teleporting { get; set; } // public PlantJuicy Juicy { get; set; } #endregion @@ -295,6 +299,7 @@ public SeedData Clone() Slip = Slip, Sentient = Sentient, Ligneous = Ligneous, + Teleporting = Teleporting, PlantRsi = PlantRsi, PlantIconState = PlantIconState, @@ -358,6 +363,7 @@ public SeedData SpeciesChange(SeedData other) Slip = Slip, Sentient = Sentient, Ligneous = Ligneous, + Teleporting = Teleporting, PlantRsi = other.PlantRsi, PlantIconState = other.PlantIconState, diff --git a/Content.Server/Botany/Systems/BotanySystem.Seed.cs b/Content.Server/Botany/Systems/BotanySystem.Seed.cs index f64fcb3c43d..82190d1c443 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Seed.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Seed.cs @@ -207,6 +207,11 @@ public IEnumerable GenerateProduct(SeedData proto, EntityCoordinates var collisionWake = EnsureComp(entity); _colWakeSystem.SetEnabled(entity, false, collisionWake); } + if (proto.Teleporting) + { + var teleporting = EnsureComp(entity); + TeleportingTraitSystem.SetPotencyRadius(proto.Potency, teleporting); + } } return products; diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index c7ce5d47efa..4780f8b3310 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -40,7 +40,7 @@ public void MutateSeed(ref SeedData seed, float severity) } // Add up everything in the bits column and put the number here. - const int totalbits = 275; + const int totalbits = 285; // Tolerances (55) MutateFloat(ref seed.NutrientConsumption , 0.05f, 1.2f, 5, totalbits, severity); @@ -66,11 +66,12 @@ public void MutateSeed(ref SeedData seed, float severity) // Kill the plant (30) MutateBool(ref seed.Viable , false, 30, totalbits, severity); - // Fun (90) + // Fun (100) MutateBool(ref seed.Seedless , true , 10, totalbits, severity); MutateBool(ref seed.Slip , true , 10, totalbits, severity); MutateBool(ref seed.Sentient , true , 10, totalbits, severity); MutateBool(ref seed.Ligneous , true , 10, totalbits, severity); + MutateBool(ref seed.Teleporting , true , 10, totalbits, severity); MutateBool(ref seed.Bioluminescent, true , 10, totalbits, severity); MutateBool(ref seed.TurnIntoKudzu , true , 10, totalbits, severity); MutateBool(ref seed.CanScream , true , 10, totalbits, severity); @@ -120,6 +121,7 @@ public SeedData Cross(SeedData a, SeedData b) CrossBool(ref result.Slip, a.Slip); CrossBool(ref result.Sentient, a.Sentient); CrossBool(ref result.Ligneous, a.Ligneous); + CrossBool(ref result.Teleporting, a.Teleporting); CrossBool(ref result.Bioluminescent, a.Bioluminescent); CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu); CrossBool(ref result.CanScream, a.CanScream); diff --git a/Content.Server/Botany/Systems/TeleportingTraitSystem.cs b/Content.Server/Botany/Systems/TeleportingTraitSystem.cs new file mode 100644 index 00000000000..7aa9a6a82ab --- /dev/null +++ b/Content.Server/Botany/Systems/TeleportingTraitSystem.cs @@ -0,0 +1,51 @@ +using Robust.Shared.Random; +using Content.Shared.Slippery; +using Content.Server.Fluids.EntitySystems; +using Content.Shared.Chemistry.Components; +using Content.Shared.Popups; + +namespace Content.Server.Botany.Systems; + +public sealed class TeleportingTraitSystem : EntitySystem +{ + [Dependency] private readonly SharedTransformSystem _xform = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly PuddleSystem _puddle = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(Teleport); + } + + // sets the potency and the radius + public static void SetPotencyRadius(float seedPotency, TeleportingTraitComponent comp) + { + comp.Potency = seedPotency; + comp.ProduceTeleportRadius = comp.Potency / comp.PotencyDivide; + } + + // teleports both the produce and the foolish fool who slipped on it to a random postion limited by the radius + private void Teleport(EntityUid uid, TeleportingTraitComponent comp, ref SlipEvent args) + { + var coordinates = Transform(uid).Coordinates; + _xform.SetCoordinates(uid, coordinates.Offset(_random.NextVector2(comp.ProduceTeleportRadius))); + _popup.PopupEntity(Loc.GetString("teleporting-trait-component-slipped"), args.Slipped, args.Slipped, PopupType.SmallCaution); + _xform.SetCoordinates(args.Slipped, coordinates.Offset(_random.NextVector2(comp.ProduceTeleportRadius))); + VanishProbablity(uid, comp); + } + + // chance of being deleted and then spawnin the goop + private void VanishProbablity(EntityUid uid, TeleportingTraitComponent comp) + { + if (!_random.Prob(comp.DeletionChance)) + return; + Solution vanishSolution = new(); + vanishSolution.AddReagent("Slime", comp.Potency / 2); + _puddle.TrySpillAt(uid, vanishSolution, out _); + QueueDel(uid); + } +} + diff --git a/Resources/Locale/en-US/botany/components/teleporting-trait-component.ftl b/Resources/Locale/en-US/botany/components/teleporting-trait-component.ftl new file mode 100644 index 00000000000..c38b8605f2b --- /dev/null +++ b/Resources/Locale/en-US/botany/components/teleporting-trait-component.ftl @@ -0,0 +1 @@ +teleporting-trait-component-slipped = You slip through bluespace! From a243fca7063844cb2ec13bafce52e216f94f5cb9 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 7 Aug 2024 23:54:35 +0000 Subject: [PATCH 047/135] Automatic Changelog Update (#674) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index bb19e08360c..0aff29d638c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5095,3 +5095,11 @@ Entries: message: Fixed the RegenMesh recipe id: 6238 time: '2024-08-07T23:51:29.0000000+00:00' +- author: dootythefrooty + changes: + - type: Add + message: >- + Added Bluespace Slips, a plant trait that teleports you randomly if you + slip. + id: 6239 + time: '2024-08-07T23:54:13.0000000+00:00' From 4c4b37aacca1448842155a9a1bafa0d002e1c890 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 7 Aug 2024 20:09:41 -0400 Subject: [PATCH 048/135] 1984 Dresser Arbitrage 2, Electric Boogaloo (#682) # Description @DEATHB4DEFEAT ![image](https://github.com/user-attachments/assets/0ee6b468-7959-4ebd-8202-6fbc2794511c) No changelog because this isn't player facing. --- Resources/Prototypes/Entities/Structures/Furniture/dresser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml b/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml index 6c50b334091..1d0a25ed852 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/dresser.yml @@ -52,7 +52,7 @@ suffix: Filled components: - type: StaticPrice - price: 5 + price: 15 - type: StorageFill contents: - id: ClothingNeckLGBTPin From 9b112609e009fedccf7adb70292af914752fcd2c Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 7 Aug 2024 20:10:21 -0400 Subject: [PATCH 049/135] Respace Psionics Audio & Localization Files (#700) # Description Effectively Part 2 of splitting up the Psionic Refactor. This PR is partially respacing the non-C# side of Psionics code, such as Localizations, Audio files, some entities. I'm not respacing all of them in a single sitting because just finding them all is a complete pain in the ass. No media because there's nothing to show. No changelog because this isn't player facing. --- .../Ambience/Objects/prober_hum_dangerous.ogg | Bin .../Ambience/Objects/prober_hum_high.ogg | Bin .../Ambience/Objects/prober_hum_low.ogg | Bin .../Ambience/Objects/prober_hum_moderate.ogg | Bin .../Psionics/attributions.yml | 0 .../Psionics/heartbeat_fast.ogg | Bin .../{nyanotrasen => }/abilities/psionic.ftl | 0 .../en-US/cartridge-loader/cartridges.ftl | 5 + .../en-US/chemistry/reagent-effects.ftl | 2 +- .../en-US/guidebook/chemistry/effects.ftl | 18 +++ Resources/Locale/en-US/guidebook/guides.ftl | 4 + .../cartridge-loader/cartridges.ftl | 4 - .../en-US/nyanotrasen/chemistry/effects.ftl | 18 --- .../en-US/nyanotrasen/guidebook/guides.ftl | 3 - .../en-US/nyanotrasen/reagents/toxins.ftl | 8 - .../xenoarchaeology/artifact-hints.ftl | 1 - .../paper => psionics}/book-epistemics.ftl | 0 .../cargo => psionics}/cargo-epistemics.ftl | 0 .../{nyanotrasen => }/psionics/death-gasp.ftl | 0 .../crates => psionics}/epistemics-crates.ftl | 0 .../events => psionics}/noospheric-storm.ftl | 0 .../objectives.ftl} | 0 .../research => psionics}/oracle.ftl | 0 .../psionics/psionic-chat.ftl | 0 .../psionics/psionic-commands.ftl | 0 .../paper => psionics}/stamp-component.ftl | 0 .../research => psionics}/technologies.ftl | 0 .../Locale/en-US/reagents/meta/toxins.ftl | 9 ++ .../{nyanotrasen => }/reagents/psionic.ftl | 0 .../en-US/xenoarchaeology/artifact-hints.ftl | 3 + Resources/Prototypes/Actions/psionics.yml | 136 +++++++++++++++++ .../Prototypes/Nyanotrasen/Actions/types.yml | 139 +----------------- .../Structures/Research/glimmer_prober.yml | 14 +- .../Interface/VerbIcons/dispel.png | Bin .../Interface/VerbIcons/dispel.png.yml | 0 .../Interface/VerbIcons/license.txt | 0 .../Interface/VerbIcons/mass_sleep.png | Bin .../Interface/VerbIcons/mass_sleep.png.yml | 0 .../Interface/VerbIcons/metapsionic.png | Bin .../Interface/VerbIcons/metapsionic.png.yml | 0 .../Interface/VerbIcons/mind_swap.png | Bin .../Interface/VerbIcons/mind_swap.png.yml | 0 .../Interface/VerbIcons/mind_swap_return.png | Bin .../VerbIcons/mind_swap_return.png.yml | 0 .../Interface/VerbIcons/noospheric_zap.png | Bin .../VerbIcons/noospheric_zap.png.yml | 0 .../VerbIcons/psionic_invisibility.png | Bin .../VerbIcons/psionic_invisibility.png.yml | 0 .../VerbIcons/psionic_invisibility_off.png | Bin .../psionic_invisibility_off.png.yml | 0 .../VerbIcons/psionic_regeneration.png | Bin .../VerbIcons/psionic_regeneration.png.yml | 0 .../Interface/VerbIcons/pyrokinesis.png | Bin .../Interface/VerbIcons/pyrokinesis.png.yml | 0 .../Interface/VerbIcons/telegnosis.png | Bin .../Interface/VerbIcons/telegnosis.png.yml | 0 56 files changed, 184 insertions(+), 180 deletions(-) rename Resources/Audio/{Nyanotrasen => }/Ambience/Objects/prober_hum_dangerous.ogg (100%) rename Resources/Audio/{Nyanotrasen => }/Ambience/Objects/prober_hum_high.ogg (100%) rename Resources/Audio/{Nyanotrasen => }/Ambience/Objects/prober_hum_low.ogg (100%) rename Resources/Audio/{Nyanotrasen => }/Ambience/Objects/prober_hum_moderate.ogg (100%) rename Resources/Audio/{Nyanotrasen => }/Psionics/attributions.yml (100%) rename Resources/Audio/{Nyanotrasen => }/Psionics/heartbeat_fast.ogg (100%) rename Resources/Locale/en-US/{nyanotrasen => }/abilities/psionic.ftl (100%) delete mode 100644 Resources/Locale/en-US/nyanotrasen/cartridge-loader/cartridges.ftl delete mode 100644 Resources/Locale/en-US/nyanotrasen/guidebook/guides.ftl delete mode 100644 Resources/Locale/en-US/nyanotrasen/reagents/toxins.ftl delete mode 100644 Resources/Locale/en-US/nyanotrasen/xenoarchaeology/artifact-hints.ftl rename Resources/Locale/en-US/{nyanotrasen/paper => psionics}/book-epistemics.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen/prototypes/catalog/cargo => psionics}/cargo-epistemics.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen => }/psionics/death-gasp.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen/prototypes/catalog/fills/crates => psionics}/epistemics-crates.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen/station-events/events => psionics}/noospheric-storm.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen/objectives/conditions/conditions.ftl => psionics/objectives.ftl} (100%) rename Resources/Locale/en-US/{nyanotrasen/research => psionics}/oracle.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen => }/psionics/psionic-chat.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen => }/psionics/psionic-commands.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen/paper => psionics}/stamp-component.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen/research => psionics}/technologies.ftl (100%) rename Resources/Locale/en-US/{nyanotrasen => }/reagents/psionic.ftl (100%) create mode 100644 Resources/Prototypes/Actions/psionics.yml rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/dispel.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/dispel.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/license.txt (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/mass_sleep.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/mass_sleep.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/metapsionic.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/metapsionic.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/mind_swap.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/mind_swap.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/mind_swap_return.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/mind_swap_return.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/noospheric_zap.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/noospheric_zap.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/psionic_invisibility.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/psionic_invisibility.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/psionic_invisibility_off.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/psionic_invisibility_off.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/psionic_regeneration.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/psionic_regeneration.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/pyrokinesis.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/pyrokinesis.png.yml (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/telegnosis.png (100%) rename Resources/Textures/{Nyanotrasen => }/Interface/VerbIcons/telegnosis.png.yml (100%) diff --git a/Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_dangerous.ogg b/Resources/Audio/Ambience/Objects/prober_hum_dangerous.ogg similarity index 100% rename from Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_dangerous.ogg rename to Resources/Audio/Ambience/Objects/prober_hum_dangerous.ogg diff --git a/Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_high.ogg b/Resources/Audio/Ambience/Objects/prober_hum_high.ogg similarity index 100% rename from Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_high.ogg rename to Resources/Audio/Ambience/Objects/prober_hum_high.ogg diff --git a/Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_low.ogg b/Resources/Audio/Ambience/Objects/prober_hum_low.ogg similarity index 100% rename from Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_low.ogg rename to Resources/Audio/Ambience/Objects/prober_hum_low.ogg diff --git a/Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_moderate.ogg b/Resources/Audio/Ambience/Objects/prober_hum_moderate.ogg similarity index 100% rename from Resources/Audio/Nyanotrasen/Ambience/Objects/prober_hum_moderate.ogg rename to Resources/Audio/Ambience/Objects/prober_hum_moderate.ogg diff --git a/Resources/Audio/Nyanotrasen/Psionics/attributions.yml b/Resources/Audio/Psionics/attributions.yml similarity index 100% rename from Resources/Audio/Nyanotrasen/Psionics/attributions.yml rename to Resources/Audio/Psionics/attributions.yml diff --git a/Resources/Audio/Nyanotrasen/Psionics/heartbeat_fast.ogg b/Resources/Audio/Psionics/heartbeat_fast.ogg similarity index 100% rename from Resources/Audio/Nyanotrasen/Psionics/heartbeat_fast.ogg rename to Resources/Audio/Psionics/heartbeat_fast.ogg diff --git a/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl b/Resources/Locale/en-US/abilities/psionic.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl rename to Resources/Locale/en-US/abilities/psionic.ftl diff --git a/Resources/Locale/en-US/cartridge-loader/cartridges.ftl b/Resources/Locale/en-US/cartridge-loader/cartridges.ftl index f5cda2f2a18..cfa1b1424d2 100644 --- a/Resources/Locale/en-US/cartridge-loader/cartridges.ftl +++ b/Resources/Locale/en-US/cartridge-loader/cartridges.ftl @@ -19,3 +19,8 @@ log-probe-scan = Downloaded logs from {$device}! log-probe-label-time = Time log-probe-label-accessor = Accessed by log-probe-label-number = # + +glimmer-monitor-program-name = Glimmer Monitor +glimmer-monitor-current-glimmer = Current Glimmer: {$glimmer}Ψ +glimmer-monitor-interval = Interval +glimmer-monitor-sync = Sync diff --git a/Resources/Locale/en-US/chemistry/reagent-effects.ftl b/Resources/Locale/en-US/chemistry/reagent-effects.ftl index 537770b35a5..cb55db111d6 100644 --- a/Resources/Locale/en-US/chemistry/reagent-effects.ftl +++ b/Resources/Locale/en-US/chemistry/reagent-effects.ftl @@ -1 +1 @@ -effect-sleepy = You feel a bit sleepy. +effect-sleepy = You feel a bit sleepy. \ No newline at end of file diff --git a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl index b6f45d23862..db2f3816f6b 100644 --- a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl +++ b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl @@ -344,3 +344,21 @@ reagent-effect-guidebook-missing = [1] Causes *[other] cause } an unknown effect as nobody has written this effect yet + +reagent-effect-guidebook-change-glimmer-reaction-effect = + { $chance -> + [1] Modifies + *[other] modify + } the glimmer count by {$count} points + +reagent-effect-guidebook-chem-remove-psionic = + { $chance -> + [1] Removes + *[other] remove + } psionic powers + +reagent-effect-guidebook-chem-reroll-psionic = + { $chance -> + [1] Allows + *[other] allow + } a chance to get a different psionic power \ No newline at end of file diff --git a/Resources/Locale/en-US/guidebook/guides.ftl b/Resources/Locale/en-US/guidebook/guides.ftl index 72746dbf51f..968d3b20038 100644 --- a/Resources/Locale/en-US/guidebook/guides.ftl +++ b/Resources/Locale/en-US/guidebook/guides.ftl @@ -70,3 +70,7 @@ guide-entry-space-ninja = Space Ninja guide-entry-writing = Writing guide-entry-glossary = Glossary + +guide-entry-altars-golemancy = Altars and Golemancy +guide-entry-psionics = Psionics +guide-entry-reverse-engineering = Reverse Engineering diff --git a/Resources/Locale/en-US/nyanotrasen/cartridge-loader/cartridges.ftl b/Resources/Locale/en-US/nyanotrasen/cartridge-loader/cartridges.ftl deleted file mode 100644 index 906466bc10f..00000000000 --- a/Resources/Locale/en-US/nyanotrasen/cartridge-loader/cartridges.ftl +++ /dev/null @@ -1,4 +0,0 @@ -glimmer-monitor-program-name = Glimmer Monitor -glimmer-monitor-current-glimmer = Current Glimmer: {$glimmer}Ψ -glimmer-monitor-interval = Interval -glimmer-monitor-sync = Sync diff --git a/Resources/Locale/en-US/nyanotrasen/chemistry/effects.ftl b/Resources/Locale/en-US/nyanotrasen/chemistry/effects.ftl index 19aeebee69e..8d0c96f13c5 100644 --- a/Resources/Locale/en-US/nyanotrasen/chemistry/effects.ftl +++ b/Resources/Locale/en-US/nyanotrasen/chemistry/effects.ftl @@ -1,21 +1,3 @@ -reagent-effect-guidebook-change-glimmer-reaction-effect = - { $chance -> - [1] Modifies - *[other] modify - } the glimmer count by {$count} points - -reagent-effect-guidebook-chem-remove-psionic = - { $chance -> - [1] Removes - *[other] remove - } psionic powers - -reagent-effect-guidebook-chem-reroll-psionic = - { $chance -> - [1] Allows - *[other] allow - } a chance to get a different psionic power - ## Disease System support reagent-effect-guidebook-chem-miasma-pool = diff --git a/Resources/Locale/en-US/nyanotrasen/guidebook/guides.ftl b/Resources/Locale/en-US/nyanotrasen/guidebook/guides.ftl deleted file mode 100644 index 60166b82598..00000000000 --- a/Resources/Locale/en-US/nyanotrasen/guidebook/guides.ftl +++ /dev/null @@ -1,3 +0,0 @@ -guide-entry-altars-golemancy = Altars and Golemancy -guide-entry-psionics = Psionics -guide-entry-reverse-engineering = Reverse Engineering diff --git a/Resources/Locale/en-US/nyanotrasen/reagents/toxins.ftl b/Resources/Locale/en-US/nyanotrasen/reagents/toxins.ftl deleted file mode 100644 index 43e35c191c9..00000000000 --- a/Resources/Locale/en-US/nyanotrasen/reagents/toxins.ftl +++ /dev/null @@ -1,8 +0,0 @@ -reagent-name-soulbreaker-toxin = soulbreaker toxin -reagent-desc-soulbreaker-toxin = An anti-psionic about 4 times as powerful as mindbreaker toxin. - -reagent-name-lotophagoi-oil = lotophagoi oil -reagent-desc-lotophagoi-oil = A super potent drug that is much better at inducing psionics than normal hallucinogens, but with worse side effects. - -reagent-name-ectoplasm = ectoplasm -reagent-desc-ectoplasm = The physical component of semi-corporeal spirits. diff --git a/Resources/Locale/en-US/nyanotrasen/xenoarchaeology/artifact-hints.ftl b/Resources/Locale/en-US/nyanotrasen/xenoarchaeology/artifact-hints.ftl deleted file mode 100644 index e07aa0a0322..00000000000 --- a/Resources/Locale/en-US/nyanotrasen/xenoarchaeology/artifact-hints.ftl +++ /dev/null @@ -1 +0,0 @@ -artifact-effect-hint-psionic = Noöspheric disturbance diff --git a/Resources/Locale/en-US/nyanotrasen/paper/book-epistemics.ftl b/Resources/Locale/en-US/psionics/book-epistemics.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/paper/book-epistemics.ftl rename to Resources/Locale/en-US/psionics/book-epistemics.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/prototypes/catalog/cargo/cargo-epistemics.ftl b/Resources/Locale/en-US/psionics/cargo-epistemics.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/prototypes/catalog/cargo/cargo-epistemics.ftl rename to Resources/Locale/en-US/psionics/cargo-epistemics.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/psionics/death-gasp.ftl b/Resources/Locale/en-US/psionics/death-gasp.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/psionics/death-gasp.ftl rename to Resources/Locale/en-US/psionics/death-gasp.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/prototypes/catalog/fills/crates/epistemics-crates.ftl b/Resources/Locale/en-US/psionics/epistemics-crates.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/prototypes/catalog/fills/crates/epistemics-crates.ftl rename to Resources/Locale/en-US/psionics/epistemics-crates.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/station-events/events/noospheric-storm.ftl b/Resources/Locale/en-US/psionics/noospheric-storm.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/station-events/events/noospheric-storm.ftl rename to Resources/Locale/en-US/psionics/noospheric-storm.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/objectives/conditions/conditions.ftl b/Resources/Locale/en-US/psionics/objectives.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/objectives/conditions/conditions.ftl rename to Resources/Locale/en-US/psionics/objectives.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/research/oracle.ftl b/Resources/Locale/en-US/psionics/oracle.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/research/oracle.ftl rename to Resources/Locale/en-US/psionics/oracle.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/psionics/psionic-chat.ftl b/Resources/Locale/en-US/psionics/psionic-chat.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/psionics/psionic-chat.ftl rename to Resources/Locale/en-US/psionics/psionic-chat.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/psionics/psionic-commands.ftl b/Resources/Locale/en-US/psionics/psionic-commands.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/psionics/psionic-commands.ftl rename to Resources/Locale/en-US/psionics/psionic-commands.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/paper/stamp-component.ftl b/Resources/Locale/en-US/psionics/stamp-component.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/paper/stamp-component.ftl rename to Resources/Locale/en-US/psionics/stamp-component.ftl diff --git a/Resources/Locale/en-US/nyanotrasen/research/technologies.ftl b/Resources/Locale/en-US/psionics/technologies.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/research/technologies.ftl rename to Resources/Locale/en-US/psionics/technologies.ftl diff --git a/Resources/Locale/en-US/reagents/meta/toxins.ftl b/Resources/Locale/en-US/reagents/meta/toxins.ftl index eb8422e66cf..fa2a813d1d6 100644 --- a/Resources/Locale/en-US/reagents/meta/toxins.ftl +++ b/Resources/Locale/en-US/reagents/meta/toxins.ftl @@ -75,3 +75,12 @@ reagent-desc-vestine = Has an adverse reaction within the body causing major jit reagent-name-tazinide = tazinide reagent-desc-tazinide = A highly dangerous metallic mixture which can interfere with most movement through an electrifying current. + +reagent-name-soulbreaker-toxin = soulbreaker toxin +reagent-desc-soulbreaker-toxin = An anti-psionic about 4 times as powerful as mindbreaker toxin. + +reagent-name-lotophagoi-oil = lotophagoi oil +reagent-desc-lotophagoi-oil = A super potent drug that is much better at inducing psionics than normal hallucinogens, but with worse side effects. + +reagent-name-ectoplasm = ectoplasm +reagent-desc-ectoplasm = The physical component of semi-corporeal spirits. diff --git a/Resources/Locale/en-US/nyanotrasen/reagents/psionic.ftl b/Resources/Locale/en-US/reagents/psionic.ftl similarity index 100% rename from Resources/Locale/en-US/nyanotrasen/reagents/psionic.ftl rename to Resources/Locale/en-US/reagents/psionic.ftl diff --git a/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl b/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl index 98dfa89fa9f..a139c2036e1 100644 --- a/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl +++ b/Resources/Locale/en-US/xenoarchaeology/artifact-hints.ftl @@ -40,3 +40,6 @@ artifact-trigger-hint-regular-gases = Standard atmospheric gases artifact-trigger-hint-plasma = Gaseous plasma artifact-trigger-hint-land = Active deceleration artifact-trigger-hint-examine = Examination + +# Psionic Effects +artifact-effect-hint-psionic = Noöspheric disturbance diff --git a/Resources/Prototypes/Actions/psionics.yml b/Resources/Prototypes/Actions/psionics.yml new file mode 100644 index 00000000000..62a7fc014cd --- /dev/null +++ b/Resources/Prototypes/Actions/psionics.yml @@ -0,0 +1,136 @@ +- type: entity + id: ActionDispel + name: action-name-dispel + description: action-description-dispel + noSpawn: true + components: + - type: EntityTargetAction + icon: Interface/VerbIcons/dispel.png + useDelay: 45 + checkCanAccess: false + range: 6 + itemIconStyle: BigAction + canTargetSelf: false + event: !type:DispelPowerActionEvent + +- type: entity + id: ActionMassSleep + name: action-name-mass-sleep + description: action-description-mass-sleep + noSpawn: true + components: + - type: WorldTargetAction + icon: Interface/VerbIcons/mass_sleep.png + useDelay: 60 + checkCanAccess: false + range: 8 + itemIconStyle: BigAction + event: !type:MassSleepPowerActionEvent + +- type: entity + id: ActionMindSwap + name: action-name-mind-swap + description: action-description-mind-swap + noSpawn: true + components: + - type: EntityTargetAction + icon: Interface/VerbIcons/mind_swap.png + useDelay: 240 + checkCanAccess: false + range: 8 + itemIconStyle: BigAction + event: !type:MindSwapPowerActionEvent + +- type: entity + id: ActionMindSwapReturn + name: action-name-mind-swap-return + description: action-description-mind-swap-return + noSpawn: true + components: + - type: InstantAction + icon: Interface/VerbIcons/mind_swap_return.png + useDelay: 20 + checkCanInteract: false + event: !type:MindSwapPowerReturnActionEvent + +- type: entity + id: ActionNoosphericZap + name: action-name-noospheric-zap + description: action-description-noospheric-zap + noSpawn: true + components: + - type: EntityTargetAction + icon: Interface/VerbIcons/noospheric_zap.png + useDelay: 100 + range: 5 + itemIconStyle: BigAction + event: !type:NoosphericZapPowerActionEvent + +- type: entity + id: ActionPyrokinesis + name: action-name-pyrokinesis + description: action-description-pyrokinesis + noSpawn: true + components: + - type: EntityTargetAction + icon: Interface/VerbIcons/pyrokinesis.png + useDelay: 50 + range: 6 + checkCanAccess: false + itemIconStyle: BigAction + event: !type:PyrokinesisPowerActionEvent + +- type: entity + id: ActionMetapsionic + name: action-name-metapsionic + description: action-description-metapsionic + noSpawn: true + components: + - type: InstantAction + icon: Interface/VerbIcons/metapsionic.png + useDelay: 45 + event: !type:MetapsionicPowerActionEvent + +- type: entity + id: ActionPsionicRegeneration + name: action-name-psionic-regeneration + description: action-description-psionic-regeneration + noSpawn: true + components: + - type: InstantAction + icon: Interface/VerbIcons/psionic_regeneration.png + useDelay: 120 + event: !type:PsionicRegenerationPowerActionEvent + +- type: entity + id: ActionTelegnosis + name: action-name-telegnosis + description: action-description-telegnosis + noSpawn: true + components: + - type: InstantAction + icon: Interface/VerbIcons/telegnosis.png + useDelay: 150 + event: !type:TelegnosisPowerActionEvent + +- type: entity + id: ActionPsionicInvisibility + name: action-name-psionic-invisibility + description: action-description-psionic-invisibility + noSpawn: true + components: + - type: InstantAction + icon: Interface/VerbIcons/psionic_invisibility.png + useDelay: 120 + event: !type:PsionicInvisibilityPowerActionEvent + +- type: entity + id: ActionPsionicInvisibilityUsed + name: action-name-psionic-invisibility-off + description: action-description-psionic-invisibility-off + noSpawn: true + components: + - type: InstantAction + icon: Interface/VerbIcons/psionic_invisibility_off.png + event: !type:RemovePsionicInvisibilityOffPowerActionEvent + diff --git a/Resources/Prototypes/Nyanotrasen/Actions/types.yml b/Resources/Prototypes/Nyanotrasen/Actions/types.yml index 04002f5755d..cab8f4a1f4e 100644 --- a/Resources/Prototypes/Nyanotrasen/Actions/types.yml +++ b/Resources/Prototypes/Nyanotrasen/Actions/types.yml @@ -18,141 +18,4 @@ charges: 1 icon: { sprite: Nyanotrasen/Objects/Specific/Species/felinid.rsi, state: icon } useDelay: 30 - event: !type:HairballActionEvent - -- type: entity - id: ActionDispel - name: action-name-dispel - description: action-description-dispel - noSpawn: true - components: - - type: EntityTargetAction - icon: Nyanotrasen/Interface/VerbIcons/dispel.png - useDelay: 45 - checkCanAccess: false - range: 6 - itemIconStyle: BigAction - canTargetSelf: false - event: !type:DispelPowerActionEvent - -- type: entity - id: ActionMassSleep - name: action-name-mass-sleep - description: action-description-mass-sleep - noSpawn: true - components: - - type: WorldTargetAction - icon: Nyanotrasen/Interface/VerbIcons/mass_sleep.png - useDelay: 60 - checkCanAccess: false - range: 8 - itemIconStyle: BigAction - event: !type:MassSleepPowerActionEvent - -- type: entity - id: ActionMindSwap - name: action-name-mind-swap - description: action-description-mind-swap - noSpawn: true - components: - - type: EntityTargetAction - icon: Nyanotrasen/Interface/VerbIcons/mind_swap.png - useDelay: 240 - checkCanAccess: false - range: 8 - itemIconStyle: BigAction - event: !type:MindSwapPowerActionEvent - -- type: entity - id: ActionMindSwapReturn - name: action-name-mind-swap-return - description: action-description-mind-swap-return - noSpawn: true - components: - - type: InstantAction - icon: Nyanotrasen/Interface/VerbIcons/mind_swap_return.png - useDelay: 20 - checkCanInteract: false - event: !type:MindSwapPowerReturnActionEvent - -- type: entity - id: ActionNoosphericZap - name: action-name-noospheric-zap - description: action-description-noospheric-zap - noSpawn: true - components: - - type: EntityTargetAction - icon: Nyanotrasen/Interface/VerbIcons/noospheric_zap.png - useDelay: 100 - range: 5 - itemIconStyle: BigAction - event: !type:NoosphericZapPowerActionEvent - -- type: entity - id: ActionPyrokinesis - name: action-name-pyrokinesis - description: action-description-pyrokinesis - noSpawn: true - components: - - type: EntityTargetAction - icon: Nyanotrasen/Interface/VerbIcons/pyrokinesis.png - useDelay: 50 - range: 6 - checkCanAccess: false - itemIconStyle: BigAction - event: !type:PyrokinesisPowerActionEvent - -- type: entity - id: ActionMetapsionic - name: action-name-metapsionic - description: action-description-metapsionic - noSpawn: true - components: - - type: InstantAction - icon: Nyanotrasen/Interface/VerbIcons/metapsionic.png - useDelay: 45 - event: !type:MetapsionicPowerActionEvent - -- type: entity - id: ActionPsionicRegeneration - name: action-name-psionic-regeneration - description: action-description-psionic-regeneration - noSpawn: true - components: - - type: InstantAction - icon: Nyanotrasen/Interface/VerbIcons/psionic_regeneration.png - useDelay: 120 - event: !type:PsionicRegenerationPowerActionEvent - -- type: entity - id: ActionTelegnosis - name: action-name-telegnosis - description: action-description-telegnosis - noSpawn: true - components: - - type: InstantAction - icon: Nyanotrasen/Interface/VerbIcons/telegnosis.png - useDelay: 150 - event: !type:TelegnosisPowerActionEvent - -- type: entity - id: ActionPsionicInvisibility - name: action-name-psionic-invisibility - description: action-description-psionic-invisibility - noSpawn: true - components: - - type: InstantAction - icon: Nyanotrasen/Interface/VerbIcons/psionic_invisibility.png - useDelay: 120 - event: !type:PsionicInvisibilityPowerActionEvent - -- type: entity - id: ActionPsionicInvisibilityUsed - name: action-name-psionic-invisibility-off - description: action-description-psionic-invisibility-off - noSpawn: true - components: - - type: InstantAction - icon: Nyanotrasen/Interface/VerbIcons/psionic_invisibility_off.png - event: !type:RemovePsionicInvisibilityOffPowerActionEvent - + event: !type:HairballActionEvent \ No newline at end of file diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml index e157f8b7ff4..102000f8b26 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml @@ -67,22 +67,22 @@ - type: AmbientSound range: 6 volume: -6 - sound: /Audio/Nyanotrasen/Ambience/Objects/prober_hum_low.ogg + sound: /Audio/Ambience/Objects/prober_hum_low.ogg - type: AmbientOnPowered - type: GlimmerSound glimmerTier: Minimal: - path: /Audio/Nyanotrasen/Ambience/Objects/prober_hum_low.ogg + path: /Audio/Ambience/Objects/prober_hum_low.ogg Low: - path: /Audio/Nyanotrasen/Ambience/Objects/prober_hum_low.ogg + path: /Audio/Ambience/Objects/prober_hum_low.ogg Moderate: - path: /Audio/Nyanotrasen/Ambience/Objects/prober_hum_moderate.ogg + path: /Audio/Ambience/Objects/prober_hum_moderate.ogg High: - path: /Audio/Nyanotrasen/Ambience/Objects/prober_hum_high.ogg + path: /Audio/Ambience/Objects/prober_hum_high.ogg Dangerous: - path: /Audio/Nyanotrasen/Ambience/Objects/prober_hum_dangerous.ogg + path: /Audio/Ambience/Objects/prober_hum_dangerous.ogg Critical: - path: /Audio/Nyanotrasen/Ambience/Objects/prober_hum_dangerous.ogg + path: /Audio/Ambience/Objects/prober_hum_dangerous.ogg - type: entity parent: BaseMachinePowered diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/dispel.png b/Resources/Textures/Interface/VerbIcons/dispel.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/dispel.png rename to Resources/Textures/Interface/VerbIcons/dispel.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/dispel.png.yml b/Resources/Textures/Interface/VerbIcons/dispel.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/dispel.png.yml rename to Resources/Textures/Interface/VerbIcons/dispel.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/license.txt b/Resources/Textures/Interface/VerbIcons/license.txt similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/license.txt rename to Resources/Textures/Interface/VerbIcons/license.txt diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/mass_sleep.png b/Resources/Textures/Interface/VerbIcons/mass_sleep.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/mass_sleep.png rename to Resources/Textures/Interface/VerbIcons/mass_sleep.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/mass_sleep.png.yml b/Resources/Textures/Interface/VerbIcons/mass_sleep.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/mass_sleep.png.yml rename to Resources/Textures/Interface/VerbIcons/mass_sleep.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/metapsionic.png b/Resources/Textures/Interface/VerbIcons/metapsionic.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/metapsionic.png rename to Resources/Textures/Interface/VerbIcons/metapsionic.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/metapsionic.png.yml b/Resources/Textures/Interface/VerbIcons/metapsionic.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/metapsionic.png.yml rename to Resources/Textures/Interface/VerbIcons/metapsionic.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap.png b/Resources/Textures/Interface/VerbIcons/mind_swap.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap.png rename to Resources/Textures/Interface/VerbIcons/mind_swap.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap.png.yml b/Resources/Textures/Interface/VerbIcons/mind_swap.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap.png.yml rename to Resources/Textures/Interface/VerbIcons/mind_swap.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap_return.png b/Resources/Textures/Interface/VerbIcons/mind_swap_return.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap_return.png rename to Resources/Textures/Interface/VerbIcons/mind_swap_return.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap_return.png.yml b/Resources/Textures/Interface/VerbIcons/mind_swap_return.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/mind_swap_return.png.yml rename to Resources/Textures/Interface/VerbIcons/mind_swap_return.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/noospheric_zap.png b/Resources/Textures/Interface/VerbIcons/noospheric_zap.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/noospheric_zap.png rename to Resources/Textures/Interface/VerbIcons/noospheric_zap.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/noospheric_zap.png.yml b/Resources/Textures/Interface/VerbIcons/noospheric_zap.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/noospheric_zap.png.yml rename to Resources/Textures/Interface/VerbIcons/noospheric_zap.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility.png b/Resources/Textures/Interface/VerbIcons/psionic_invisibility.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility.png rename to Resources/Textures/Interface/VerbIcons/psionic_invisibility.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility.png.yml b/Resources/Textures/Interface/VerbIcons/psionic_invisibility.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility.png.yml rename to Resources/Textures/Interface/VerbIcons/psionic_invisibility.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility_off.png b/Resources/Textures/Interface/VerbIcons/psionic_invisibility_off.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility_off.png rename to Resources/Textures/Interface/VerbIcons/psionic_invisibility_off.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility_off.png.yml b/Resources/Textures/Interface/VerbIcons/psionic_invisibility_off.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_invisibility_off.png.yml rename to Resources/Textures/Interface/VerbIcons/psionic_invisibility_off.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_regeneration.png b/Resources/Textures/Interface/VerbIcons/psionic_regeneration.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_regeneration.png rename to Resources/Textures/Interface/VerbIcons/psionic_regeneration.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_regeneration.png.yml b/Resources/Textures/Interface/VerbIcons/psionic_regeneration.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/psionic_regeneration.png.yml rename to Resources/Textures/Interface/VerbIcons/psionic_regeneration.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/pyrokinesis.png b/Resources/Textures/Interface/VerbIcons/pyrokinesis.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/pyrokinesis.png rename to Resources/Textures/Interface/VerbIcons/pyrokinesis.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/pyrokinesis.png.yml b/Resources/Textures/Interface/VerbIcons/pyrokinesis.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/pyrokinesis.png.yml rename to Resources/Textures/Interface/VerbIcons/pyrokinesis.png.yml diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/telegnosis.png b/Resources/Textures/Interface/VerbIcons/telegnosis.png similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/telegnosis.png rename to Resources/Textures/Interface/VerbIcons/telegnosis.png diff --git a/Resources/Textures/Nyanotrasen/Interface/VerbIcons/telegnosis.png.yml b/Resources/Textures/Interface/VerbIcons/telegnosis.png.yml similarity index 100% rename from Resources/Textures/Nyanotrasen/Interface/VerbIcons/telegnosis.png.yml rename to Resources/Textures/Interface/VerbIcons/telegnosis.png.yml From e9e10f29b69cef5b79114caec0786de3b801d757 Mon Sep 17 00:00:00 2001 From: BlueHNT <79374236+BlueHNT@users.noreply.github.com> Date: Thu, 8 Aug 2024 02:16:02 +0200 Subject: [PATCH 050/135] Updates WelderRefinable Component (#687) # Description I have made this originally for N14 as there was a heavy need for junk items to be list instead of a hash. It created a few issues where you were unable to put down 2 pieces of steel without making a new defined entity which spawns a stack of 2. I thought this was quite annoying so I decided to instead make it into a `EntitySpawnEntry` from a `string` which would also give it options of `amount` `prob` `maxAmount` and `orGroup` which would definitely aid in the scrapping needs there as you could randomize the refined amounts. I believe this could be useful upstream. As well as cleaning up code which is more modifiable than before. The new example of how it can be typed in yaml is also simpler in my opinion as it is self-explanatory and used in various places like StorageFill contents for one. ```YAML - type: WelderRefinable refineResult: - id: SheetGlass1 amount: 1 maxAmount: 2 prob: 0.5 orGroup: Glass ``` --- :cl: refactor: Refactors WelderRefinableComponent.cs and RefiningSystem.cs tweak: Tweaked the formatting for WelderRefinable refineResult to use EntitySpawnEntry format --- .../Components/WelderRefinableComponent.cs | 13 +++++----- Content.Server/Construction/RefiningSystem.cs | 15 +++-------- .../Entities/Objects/Materials/shards.yml | 18 ++++++------- .../Entities/Objects/Misc/broken_bottle.yml | 2 +- .../Entities/Objects/Power/lights.yml | 26 +++++++++---------- 5 files changed, 33 insertions(+), 41 deletions(-) diff --git a/Content.Server/Construction/Components/WelderRefinableComponent.cs b/Content.Server/Construction/Components/WelderRefinableComponent.cs index 9d8958f7614..dc3074f1958 100644 --- a/Content.Server/Construction/Components/WelderRefinableComponent.cs +++ b/Content.Server/Construction/Components/WelderRefinableComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.Tools; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Content.Shared.Storage; +using Robust.Shared.Prototypes; namespace Content.Server.Construction.Components { @@ -10,13 +11,13 @@ namespace Content.Server.Construction.Components [RegisterComponent] public sealed partial class WelderRefinableComponent : Component { - [DataField("refineResult")] - public HashSet? RefineResult = new(); + [DataField] + public List RefineResult = new(); - [DataField("refineTime")] + [DataField] public float RefineTime = 2f; - [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string QualityNeeded = "Welding"; + [DataField] + public ProtoId QualityNeeded = "Welding"; } } diff --git a/Content.Server/Construction/RefiningSystem.cs b/Content.Server/Construction/RefiningSystem.cs index b9d80c7170a..d4df8b0916b 100644 --- a/Content.Server/Construction/RefiningSystem.cs +++ b/Content.Server/Construction/RefiningSystem.cs @@ -1,11 +1,8 @@ using Content.Server.Construction.Components; using Content.Server.Stack; using Content.Shared.Construction; -using Content.Shared.DoAfter; using Content.Shared.Interaction; -using Content.Shared.Stacks; -using Content.Shared.Tools; -using Robust.Shared.Serialization; +using Content.Shared.Storage; using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Construction @@ -13,7 +10,6 @@ namespace Content.Server.Construction public sealed class RefiningSystem : EntitySystem { [Dependency] private readonly SharedToolSystem _toolSystem = default!; - [Dependency] private readonly StackSystem _stackSystem = default!; public override void Initialize() { base.Initialize(); @@ -39,14 +35,9 @@ private void OnDoAfter(EntityUid uid, WelderRefinableComponent component, Welder EntityManager.DeleteEntity(uid); // spawn each result after refine - foreach (var result in component.RefineResult!) + foreach (var ent in EntitySpawnCollection.GetSpawns(component.RefineResult)) { - var droppedEnt = EntityManager.SpawnEntity(result, resultPosition); - - // TODO: If something has a stack... Just use a prototype with a single thing in the stack. - // This is not a good way to do it. - if (TryComp(droppedEnt, out var stack)) - _stackSystem.SetCount(droppedEnt, 1, stack); + Spawn(ent, resultPosition); } } } diff --git a/Resources/Prototypes/Entities/Objects/Materials/shards.yml b/Resources/Prototypes/Entities/Objects/Materials/shards.yml index 5fcb006cfa5..6cdc066cf10 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/shards.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/shards.yml @@ -89,7 +89,7 @@ color: "#bbeeff" - type: WelderRefinable refineResult: - - SheetGlass1 + - id: SheetGlass1 - type: DamageUserOnTrigger damage: types: @@ -120,8 +120,8 @@ color: "#96cdef" - type: WelderRefinable refineResult: - - SheetGlass1 - - PartRodMetal1 + - id: SheetGlass1 + - id: PartRodMetal1 - type: DamageUserOnTrigger damage: types: @@ -152,8 +152,8 @@ color: "#FF72E7" - type: WelderRefinable refineResult: - - SheetGlass1 - - SheetPlasma1 + - id: SheetGlass1 + - id: SheetPlasma1 - type: DamageUserOnTrigger damage: types: @@ -186,8 +186,8 @@ color: "#8eff7a" - type: WelderRefinable refineResult: - - SheetGlass1 - - SheetUranium1 + - id: SheetGlass1 + - id: SheetUranium1 - type: DamageUserOnTrigger damage: types: @@ -221,8 +221,8 @@ color: "#e0aa36" - type: WelderRefinable refineResult: - - SheetGlass1 - - SheetBrass1 + - id: SheetGlass1 + - id: SheetBrass1 - type: DamageUserOnTrigger damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml index b7c73f5e0cc..32222d0036c 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml @@ -28,4 +28,4 @@ - type: SpaceGarbage - type: WelderRefinable refineResult: - - SheetGlass1 + - id: SheetGlass1 diff --git a/Resources/Prototypes/Entities/Objects/Power/lights.yml b/Resources/Prototypes/Entities/Objects/Power/lights.yml index c8089cd22d3..b18a0feaa52 100644 --- a/Resources/Prototypes/Entities/Objects/Power/lights.yml +++ b/Resources/Prototypes/Entities/Objects/Power/lights.yml @@ -68,7 +68,7 @@ - type: SpaceGarbage - type: WelderRefinable refineResult: - - SheetGlass1 + - id: SheetGlass1 - type: entity parent: BaseLightbulb @@ -276,8 +276,8 @@ node: icon - type: WelderRefinable refineResult: - - SheetGlass1 - - ShardCrystalCyan + - id: SheetGlass1 + - id: ShardCrystalCyan - type: entity parent: LightTubeCrystalCyan @@ -296,8 +296,8 @@ node: icon - type: WelderRefinable refineResult: - - SheetGlass1 - - ShardCrystalBlue + - id: SheetGlass1 + - id: ShardCrystalBlue - type: entity parent: LightTubeCrystalCyan @@ -316,8 +316,8 @@ node: icon - type: WelderRefinable refineResult: - - SheetGlass1 - - ShardCrystalPink + - id: SheetGlass1 + - id: ShardCrystalPink - type: entity parent: LightTubeCrystalCyan @@ -336,8 +336,8 @@ node: icon - type: WelderRefinable refineResult: - - SheetGlass1 - - ShardCrystalOrange + - id: SheetGlass1 + - id: ShardCrystalOrange - type: entity parent: LightTubeCrystalCyan @@ -356,8 +356,8 @@ node: icon - type: WelderRefinable refineResult: - - SheetGlass1 - - ShardCrystalRed + - id: SheetGlass1 + - id: ShardCrystalRed - type: entity parent: LightTubeCrystalCyan @@ -376,5 +376,5 @@ node: icon - type: WelderRefinable refineResult: - - SheetGlass1 - - ShardCrystalGreen + - id: SheetGlass1 + - id: ShardCrystalGreen From 844218c8180d2e4439642717ad1c91e1d7229381 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Thu, 8 Aug 2024 00:16:23 +0000 Subject: [PATCH 051/135] Automatic Changelog Update (#687) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0aff29d638c..45e36fa3f08 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5103,3 +5103,11 @@ Entries: slip. id: 6239 time: '2024-08-07T23:54:13.0000000+00:00' +- author: BlueHNT + changes: + - type: Tweak + message: >- + Tweaked the formatting for WelderRefinable refineResult to use + EntitySpawnEntry format + id: 6240 + time: '2024-08-08T00:16:02.0000000+00:00' From 75d2ea8f35c9be1b76a6b6c15531fc2cf5592fe9 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 7 Aug 2024 20:18:08 -0400 Subject: [PATCH 052/135] 1984 Shit Colored Moths (#681) # Description I'll let google image search make my case. ![image](https://github.com/user-attachments/assets/c8fe9ec7-0292-4d77-bc94-f890219349e3) ![image](https://github.com/user-attachments/assets/1d871bff-4a18-4ce9-a121-d0282821c48c) ![image](https://github.com/user-attachments/assets/2375fe34-691c-49ab-b9d7-a16a17b2a3ce) Done. By popular request, I'm bringing back RGB Moths. # Changelog :cl: - fix: Moths can now once again be colorful. --- Content.Shared/Humanoid/SkinColor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Humanoid/SkinColor.cs b/Content.Shared/Humanoid/SkinColor.cs index 55fab4af5ba..dcc5c2d7645 100644 --- a/Content.Shared/Humanoid/SkinColor.cs +++ b/Content.Shared/Humanoid/SkinColor.cs @@ -136,7 +136,7 @@ public static Color TintedHues(Color color) /// The skin color to blend with /// Blending factor (0.0 to 1.0) /// Tinted hue color - public static Color TintedHuesSkin(Color color, Color skinColor, float blendFactor = 0.5f) + public static Color TintedHuesSkin(Color color, Color skinColor, float blendFactor = 0.0f) { blendFactor = MathHelper.Clamp(blendFactor, 0.0f, 1.0f); From ba9a93707855c63dcbbbdc5cf5fe0931f196c9b0 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Thu, 8 Aug 2024 00:18:30 +0000 Subject: [PATCH 053/135] Automatic Changelog Update (#681) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 45e36fa3f08..f6fba8d64b5 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5111,3 +5111,9 @@ Entries: EntitySpawnEntry format id: 6240 time: '2024-08-08T00:16:02.0000000+00:00' +- author: VMSolidus + changes: + - type: Fix + message: Moths can now once again be colorful. + id: 6241 + time: '2024-08-08T00:18:08.0000000+00:00' From d1c8bf10953b63c675eb8629b119fb06f66b1ea5 Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:52:49 +0300 Subject: [PATCH 054/135] Tweak Skeleton Description (#707) # Description Cherry-picks https://github.com/Fansana/floofstation1/pull/88 from Floofstation - changes skeleton description to match with Delta-v. Credit to ShatteredSwords. # Changelog :cl: ShatteredSwords - tweak: Skeleton ghost role description has been adjusted to be less evil. --------- Signed-off-by: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Co-authored-by: ShatteredSwords <135023515+ShatteredSwords@users.noreply.github.com> --- Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 7b25eb660bc..9260db903fc 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -161,7 +161,7 @@ ghost-role-information-skeleton-biker-name = Skeleton Biker ghost-role-information-skeleton-biker-description = Ride around on your sweet ride. ghost-role-information-closet-skeleton-name = Closet Skeleton -ghost-role-information-closet-skeleton-description = Wreak havoc! You are a primordial force with no allegiance. Live happily with the crew or wage sweet skeletal war. +ghost-role-information-closet-skeleton-description = You are a closet skeleton! You are a primordial force of chaos with no allegiance! You can either join the crew and use your skeletal antics to help them, or be a a prankster, and hinder their efforts! ghost-role-information-onestar-mecha-name = Onestar Mecha ghost-role-information-onestar-mecha-description = You are an experimental mecha created by who-knows-what, all you know is that you have weapons and you detect fleshy moving targets nearby... From 892f1e04c9861e04b2b1e7fc6c2279e80f1b53fa Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Fri, 9 Aug 2024 10:53:11 +0000 Subject: [PATCH 055/135] Automatic Changelog Update (#707) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f6fba8d64b5..6e9745ffd8b 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5117,3 +5117,9 @@ Entries: message: Moths can now once again be colorful. id: 6241 time: '2024-08-08T00:18:08.0000000+00:00' +- author: ShatteredSwords + changes: + - type: Tweak + message: Skeleton ghost role description has been adjusted to be less evil. + id: 6242 + time: '2024-08-09T10:52:49.0000000+00:00' From 7d92c3e69f2347fe4616600698f63e6d23280282 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Fri, 9 Aug 2024 07:13:13 -0400 Subject: [PATCH 056/135] Soft-Refactor Geiger Counters (#615) # Description This refactors Geiger Counters so that their behavior of "Only making sound to a person holding them" is no longer hardcoded. The GeigerCounterComponent now can define how loud it ticks, how far away people can hear the ticks, and whether it plays only for the person holding it or for anyone nearby. This PR partially fulfills one of the "Nice To Have" features requested for https://github.com/Simple-Station/Einstein-Engines/pull/341 by making it possible to create stationary radiation alarm objects. It also serves as a substantial quality of life improvement for Engineering and Science crew, since it's now possible to place an active Geiger counter in the artifact lab, and then be able to audibly hear if the lab becomes radioactive due to an artifact.

Media

https://github.com/user-attachments/assets/74122135-7345-4995-bb0e-d1216e1d53b6 https://github.com/user-attachments/assets/de79db6f-e1c1-471f-88b5-0a47ff4bfa16

# Changelog :cl: - add: Geiger Counters other than ones installed in Hardsuits now generate an audible sound when active and exposed to radiation. - add: Wall mounted geiger counters have been added to the game. --------- Signed-off-by: VMSolidus --- .../Radiation/Systems/GeigerSystem.cs | 28 +++++----- .../Radiation/Components/GeigerComponent.cs | 19 +++++-- .../OuterClothing/base_clothingouter.yml | 3 ++ .../Structures/Wallmounts/radalarm.yml | 51 ++++++++++++++++++ .../Wallmounts/radalarm.rsi/geiger_base.png | Bin 0 -> 1283 bytes .../Wallmounts/radalarm.rsi/geiger_on_ext.png | Bin 0 -> 375 bytes .../radalarm.rsi/geiger_on_high.png | Bin 0 -> 375 bytes .../radalarm.rsi/geiger_on_idle.png | Bin 0 -> 326 bytes .../Wallmounts/radalarm.rsi/geiger_on_low.png | Bin 0 -> 363 bytes .../Wallmounts/radalarm.rsi/geiger_on_med.png | Bin 0 -> 368 bytes .../Wallmounts/radalarm.rsi/meta.json | 35 ++++++++++++ 11 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_base.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_ext.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_high.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_idle.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_low.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_med.png create mode 100644 Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json diff --git a/Content.Server/Radiation/Systems/GeigerSystem.cs b/Content.Server/Radiation/Systems/GeigerSystem.cs index f889336a068..06e5911cb7c 100644 --- a/Content.Server/Radiation/Systems/GeigerSystem.cs +++ b/Content.Server/Radiation/Systems/GeigerSystem.cs @@ -6,8 +6,8 @@ using Content.Shared.Radiation.Components; using Content.Shared.Radiation.Systems; using Robust.Server.Audio; -using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Player; namespace Content.Server.Radiation.Systems; @@ -152,19 +152,19 @@ private void UpdateSound(EntityUid uid, GeigerComponent? component = null) component.Stream = _audio.Stop(component.Stream); - if (!component.Sounds.TryGetValue(component.DangerLevel, out var sounds)) - return; - - if (component.User == null) - return; - - if (!_player.TryGetSessionByEntity(component.User.Value, out var session)) - return; - - var sound = _audio.GetSound(sounds); - var param = sounds.Params.WithLoop(true).WithVolume(-4f); - - component.Stream = _audio.PlayGlobal(sound, session, param)?.Entity; + if (component.Sounds.TryGetValue(component.DangerLevel, out var sounds)) + { + var sound = _audio.GetSound(sounds); + + if (component.LocalSoundOnly + && component.User is not null + && _player.TryGetSessionByEntity(component.User.Value, out var session)) + { + component.Stream = _audio.PlayGlobal(sound, session, component.AudioParameters)?.Entity; + return; + } + component.Stream = _audio.PlayEntity(sound, Filter.Pvs(uid), uid, true, component.AudioParameters)?.Entity; + } } public static GeigerDangerLevel RadsToLevel(float rads) diff --git a/Content.Shared/Radiation/Components/GeigerComponent.cs b/Content.Shared/Radiation/Components/GeigerComponent.cs index 71edb70b37c..710d74d9b38 100644 --- a/Content.Shared/Radiation/Components/GeigerComponent.cs +++ b/Content.Shared/Radiation/Components/GeigerComponent.cs @@ -29,14 +29,12 @@ public sealed partial class GeigerComponent : Component /// /// Should it shows examine message with current radiation level? /// - [ViewVariables(VVAccess.ReadWrite)] [DataField] public bool ShowExamine; /// /// Should it shows item control when equipped by player? /// - [ViewVariables(VVAccess.ReadWrite)] [DataField] public bool ShowControl; @@ -55,7 +53,7 @@ public sealed partial class GeigerComponent : Component /// /// Current radiation level in rad per second. /// - [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + [DataField, AutoNetworkedField] public float CurrentRadiation; /// @@ -66,8 +64,6 @@ public sealed partial class GeigerComponent : Component /// /// Current player that equipped geiger counter. - /// Because sound is annoying, geiger counter clicks will play - /// only for player that equipped it. /// [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] public EntityUid? User; @@ -83,6 +79,19 @@ public sealed partial class GeigerComponent : Component /// Played only for current user. /// public EntityUid? Stream; + + /// + /// Controls whether the geiger counter plays only for the local player, or plays for everyone nearby. + /// Useful for things like hardsuits with integrated geigers. Alternatively, to create stationary radiation alarm objects. + /// + [DataField] + public bool LocalSoundOnly = false; + + /// + /// Used for all geiger counter audio controls, allowing entities to override default audio parameters. + /// + [DataField] + public AudioParams AudioParameters; } [Serializable, NetSerializable] diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index d6a2cd446be..358f91d2971 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -142,6 +142,9 @@ - type: Clothing equipDelay: 2.5 # Hardsuits are heavy and take a while to put on/off. unequipDelay: 2.5 + - type: Geiger + attachedToSuit: true + localSoundOnly: true - type: StaminaDamageResistance coefficient: 0.75 # 25% diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml new file mode 100644 index 00000000000..44bbe3e6170 --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/radalarm.yml @@ -0,0 +1,51 @@ +- type: entity + id: GeigerCounterWallMount + name: wall-mounted Geiger counter + description: A stationary device that emits a warning tone when it detects radiation pulses. + placement: + mode: SnapgridCenter + snap: + - Wallmount + components: + - type: InteractionOutline + - type: Clickable + - type: Rotatable + rotateWhileAnchored: false + rotateWhilePulling: true + - type: WallMount + - type: Transform + noRot: false + anchored: true + - type: Sprite + noRot: true + drawdepth: WallMountedItems + sprite: Structures/Wallmounts/radalarm.rsi + layers: + - state: geiger_base + - state: geiger_on_idle + map: ["enum.GeigerLayers.Screen"] + shader: unshaded + visible: false + - type: Geiger + showControl: true + showExamine: true + localSoundOnly: false + audioParameters: + volume: -4 + maxDistance: 10 + rolloffFactor: 4 + - type: Appearance + - type: GenericVisualizer + visuals: + enum.GeigerVisuals.IsEnabled: + GeigerLayers.Screen: + True: { visible: True } + False: { visible: False } + enum.GeigerVisuals.DangerLevel: + GeigerLayers.Screen: + None: {state: geiger_on_idle} + Low: {state: geiger_on_low} + Med: {state: geiger_on_med} + High: {state: geiger_on_high} + Extreme: {state: geiger_on_ext} + diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_base.png b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_base.png new file mode 100644 index 0000000000000000000000000000000000000000..778c427735012720fbd093e0a7f54b9adb5b5dcb GIT binary patch literal 1283 zcmV+e1^oJnP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1ei%gK~#8N?VC+# z6fqRXr&cSaqWD?6t)*JE2zpUb#DgLhKMo?O^ybN1p$8GygRlx-R>Xs_7x5&5hzjDt z4+L=!A{9I-i1nkTe$-ZrRV-3vsr%35)tF6YGP|?0vzi|~l1aBS$;-=|yq8_aVzF5M zXKHxqNhXt-)ae3=Hzx9}m3orr8fTS8Qwg6KOt$g=a8F#c!aQnthlTd=_ z1XXMP!^a_3mdgpQT(z!f=V|iHKo)?(%2F;c@KOeEiqUHj`+y*O00Mgf>;sCi02+MW zf>Ql2-ZKCtEQI1vn8Vm~zJm}zqAjc-ky^6=K*2n@X zfoK8PRbJ?8nJUQwyyB3Tub#!j0>S`;7R#V`SwK}N05eHa3|?_fRVY9Q%p7kWS%wN|%+zQ5a5bql8YVO2tzFVm4M5nXo!!3YGv& zzf?RGK(ntB5qB*{;{*vf-!S}+kq_{5Dj2-UYbZ?QwO=g03eY(f5pqaTLf&6SPK&G3 z|+1`002ovPDHLkV1lQfLi_*# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_ext.png b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_ext.png new file mode 100644 index 0000000000000000000000000000000000000000..7b7f3f4e767822a0454026ece50fdf8aa63daccc GIT binary patch literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0(2Ka=yo-qubspz*wJ?a07p8pOJ|MxEk${c^8m;$8OOM?7@|APU8lsB^* zP>8d@BeIx*f$sJOGwXs7uI@pgKH7q$8)q86K*i9cof7b<0cat^NPii2}sJdh|QQQw?qxU9i%sA7!F7P~0;<4II9;|murgH5Pcbli+x?k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0(2Ka=yo-qubspz*wJ?a07p8pOJ|MxEk${c^8m;$8OOM?7@|APU8lsB^* zP>8d@BeIx*f$sJOGwXs7uI@pgKH7q$8)q86K*i9cof7b<0cat^NPii2}sJdh|QQQw?qxU9i%sA7!F7P~0;<4II9;|murgH5Pcbli+x?k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O_~O1^9%x+S`|Sc~6vEk-F}i@#+7YfWj|k1jGO-wvr&f;Qt`NuzCNI{Xh}U z0*}aI1_r((Aj~*bn@<`jxZ2ajF(ktM?X=r`4GJ6%d;k5{Hy4xSoVh*9^qlvtXMz)@ z)c6)P-RI?228@qvIwE(XyR3@?Nurq^Y~6x>W|$yl@f_MtwG zd)f+}n#D>H@zbP4no78RnGQW?=_|GO45;UJFLPAa3SczQ=qO~I8t?n@t65k9(Af;0 Lu6{1-oD!Mk44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O_~O1^9%xcKM4hij)2SKj*;`&i@}b0fpa6e^LQbY$ZW{!T&*kVe|ea`+*{y z1s;*b3=DinK$vl=HlH+5@Pem{V@QPi+i4fYniV)4m_ProuUw&1I>|Xx-}=t;{(1YYCyj+c)I$ztaD0e0swKOgqZ*U literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_med.png b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/geiger_on_med.png new file mode 100644 index 0000000000000000000000000000000000000000..33d354a6a6ecd6f9b410c95d9aa80557712694e8 GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O_~O1^9%xPBP(H=Fb27kpHGeqyK07fx=#U>Y9KQTS<^#@P80s*t~zqexL|v zfk$L90|Va?5N4dJ%_j{Myz1%V7!u+BcABG5vjUH+r_%TRMT$$fR9zKv#pmwnJtjHt zBez$FTg->@rU?^2XRcywa9~ilsx!60z&Yq_Q27KY2XFRgJl|HZxI1dGn$DZb7tqH$ zzov!zYgm2&YxB+vtY7E4OMJA73}X!l>j~)$b=;nC&H90;a_FPyk|jG1uu6*WP}r>K zVc+^CaJ#dg`o4EQNM|}nc>gTe~DWM4f D7!iXk literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json new file mode 100644 index 00000000000..2ef22994bc0 --- /dev/null +++ b/Resources/Textures/Structures/Wallmounts/radalarm.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Made by @dootythefrooty (Discord)", + "states": [ + { + "name": "geiger_base", + "directions": 4 + }, + { + "name": "geiger_on_idle", + "directions": 4 + }, + { + "name": "geiger_on_low", + "directions": 4 + }, + { + "name": "geiger_on_med", + "directions": 4 + }, + { + "name": "geiger_on_high", + "directions": 4 + }, + { + "name": "geiger_on_ext", + "directions": 4 + } + ] +} From f0340314ad062d4bf7e2bfbfd7dc9efb67a62ce3 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Fri, 9 Aug 2024 11:13:38 +0000 Subject: [PATCH 057/135] Automatic Changelog Update (#615) --- Resources/Changelog/Changelog.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6e9745ffd8b..f571aeb6bbf 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5123,3 +5123,13 @@ Entries: message: Skeleton ghost role description has been adjusted to be less evil. id: 6242 time: '2024-08-09T10:52:49.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: >- + Geiger Counters other than ones installed in Hardsuits now generate an + audible sound when active and exposed to radiation. + - type: Add + message: Wall mounted geiger counters have been added to the game. + id: 6243 + time: '2024-08-09T11:13:13.0000000+00:00' From f4d2e3551b78203cfa5bb4a068ebfbdc515a2c23 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Sat, 10 Aug 2024 01:28:01 +0800 Subject: [PATCH 058/135] Make Dionas Slow And Steady (#704) # Description Dionas now have 25% slower movement speed in exchange for total slip immunity and slow immunity (except lying down). Note that this also prevents slowdowns from hunger and thirst. This also fixes an existing bug with Sluggish and Snail-Paced related to `TraitSpeedModifierSystem`, as it was not applying the reduced movement speed upon spawning, only when the movement speed has been modified by another source. `TraitSpeedModifierSystem` has been moved from `Content.Server` to `Content.Shared`. This used to be a trait costing 3 points, but is now given for free to all Dionas per request of @VMSolidus. ## Media
Expand **Speed with no items** ![image](https://github.com/user-attachments/assets/b723614a-79fe-401c-ae53-2ad98ff9a6d3) **Speed wearing a jugsuit, wearing a duffel bag, holding one duffel bag in each arm, and walking through a puddle of glue covered in spider webs.** ![image](https://github.com/user-attachments/assets/a934d2c1-437f-463c-8fe3-63b7b54a1f58)
# Changelog :cl: Skubman - add: Dionas have been given a 25% slower movement speed. In exchange for that, they gain absolute slip immunity and movement speed modifier immunity. This makes them immune to slowdown from things like duffelbags, hardsuits, and spider webs. - fix: Sluggish and Snail-Paced will now properly apply their movement penalties upon joining. --- Content.Server/Standing/LayingDownSystem.cs | 2 +- .../Assorted/TraitSpeedModifierSystem.cs | 19 ------------ .../Systems/MovementSpeedModifierSystem.cs | 23 ++++++++++++-- .../SpeedModifierImmunityComponent.cs | 12 +++++++ .../TraitSpeedModifierComponent.cs | 10 +++--- .../Systems/TraitSpeedModifierSystem.cs | 31 +++++++++++++++++++ .../Entities/Mobs/Species/diona.yml | 5 +++ Resources/Prototypes/Traits/disabilities.yml | 8 +++++ Resources/Prototypes/Traits/skills.yml | 4 +++ 9 files changed, 88 insertions(+), 26 deletions(-) delete mode 100644 Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs create mode 100644 Content.Shared/Traits/Assorted/Components/SpeedModifierImmunityComponent.cs rename {Content.Server/Traits/Assorted => Content.Shared/Traits/Assorted/Components}/TraitSpeedModifierComponent.cs (52%) create mode 100644 Content.Shared/Traits/Assorted/Systems/TraitSpeedModifierSystem.cs diff --git a/Content.Server/Standing/LayingDownSystem.cs b/Content.Server/Standing/LayingDownSystem.cs index 69787ae8308..73a929fdfc4 100644 --- a/Content.Server/Standing/LayingDownSystem.cs +++ b/Content.Server/Standing/LayingDownSystem.cs @@ -48,7 +48,7 @@ private void OnRefreshMovementSpeed(EntityUid uid, LayingDownComponent component if (TryComp(uid, out var standingState) && standingState.Standing) return; - args.ModifySpeed(component.DownedSpeedMultiplier, component.DownedSpeedMultiplier); + args.ModifySpeed(component.DownedSpeedMultiplier, component.DownedSpeedMultiplier, bypassImmunity: true); } private void OnParentChanged(EntityUid uid, LayingDownComponent component, EntParentChangedMessage args) diff --git a/Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs b/Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs deleted file mode 100644 index c804592347a..00000000000 --- a/Content.Server/Traits/Assorted/TraitSpeedModifierSystem.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Content.Shared.Movement.Systems; -using Content.Server.Traits.Assorted; - -namespace Content.Shared.Traits.Assorted; - -public sealed class TraitSpeedModifierSystem : EntitySystem -{ - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnRefreshMovementSpeed); - } - - private void OnRefreshMovementSpeed(EntityUid uid, TraitSpeedModifierComponent component, RefreshMovementSpeedModifiersEvent args) - { - args.ModifySpeed(component.WalkModifier, component.SprintModifier); - } -} diff --git a/Content.Shared/Movement/Systems/MovementSpeedModifierSystem.cs b/Content.Shared/Movement/Systems/MovementSpeedModifierSystem.cs index 7c793d5eb89..67a238cf60f 100644 --- a/Content.Shared/Movement/Systems/MovementSpeedModifierSystem.cs +++ b/Content.Shared/Movement/Systems/MovementSpeedModifierSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Inventory; using Content.Shared.Movement.Components; +using Content.Shared.Traits.Assorted.Components; using Robust.Shared.Timing; namespace Content.Shared.Movement.Systems @@ -16,7 +17,11 @@ public void RefreshMovementSpeedModifiers(EntityUid uid, MovementSpeedModifierCo if (_timing.ApplyingState) return; - var ev = new RefreshMovementSpeedModifiersEvent(); + var isImmune = false; + if (HasComp(uid)) + isImmune = true; + + var ev = new RefreshMovementSpeedModifiersEvent(isImmune); RaiseLocalEvent(uid, ev); if (MathHelper.CloseTo(ev.WalkSpeedModifier, move.WalkSpeedModifier) && @@ -64,10 +69,24 @@ public sealed class RefreshMovementSpeedModifiersEvent : EntityEventArgs, IInven public float WalkSpeedModifier { get; private set; } = 1.0f; public float SprintSpeedModifier { get; private set; } = 1.0f; - public void ModifySpeed(float walk, float sprint) + /// + /// Whether this entity is immune to most movement speed modifiers. + /// Bypassable by setting bypassImmunity to true. + /// +/// This is used to make an entity's movement speed constant and +/// never affected by almost all movement speed modifiers. +///
+[RegisterComponent, NetworkedComponent] +public sealed partial class SpeedModifierImmunityComponent : Component +{ +} diff --git a/Content.Server/Traits/Assorted/TraitSpeedModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/TraitSpeedModifierComponent.cs similarity index 52% rename from Content.Server/Traits/Assorted/TraitSpeedModifierComponent.cs rename to Content.Shared/Traits/Assorted/Components/TraitSpeedModifierComponent.cs index 6acb32e6c1d..85dc52a21f5 100644 --- a/Content.Server/Traits/Assorted/TraitSpeedModifierComponent.cs +++ b/Content.Shared/Traits/Assorted/Components/TraitSpeedModifierComponent.cs @@ -1,14 +1,16 @@ -namespace Content.Server.Traits.Assorted; +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; /// /// This component is used for traits that modify movement speed. /// -[RegisterComponent] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class TraitSpeedModifierComponent : Component { - [DataField(required: true)] + [DataField, AutoNetworkedField] public float WalkModifier = 1.0f; - [DataField(required: true)] + [DataField, AutoNetworkedField] public float SprintModifier = 1.0f; } diff --git a/Content.Shared/Traits/Assorted/Systems/TraitSpeedModifierSystem.cs b/Content.Shared/Traits/Assorted/Systems/TraitSpeedModifierSystem.cs new file mode 100644 index 00000000000..9817ebc1560 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Systems/TraitSpeedModifierSystem.cs @@ -0,0 +1,31 @@ +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; +using Content.Shared.Traits.Assorted.Components; + +namespace Content.Shared.Traits.Assorted.Systems; + +public sealed class TraitSpeedModifierSystem : EntitySystem +{ + [Dependency] private readonly MovementSpeedModifierSystem _movement = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnRefreshMovementSpeed); + } + + private void OnRefreshMovementSpeed(EntityUid uid, TraitSpeedModifierComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.WalkModifier, component.SprintModifier, bypassImmunity: true); + } + + private void OnStartup(EntityUid uid, TraitSpeedModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var move)) + return; + + _movement.RefreshMovementSpeedModifiers(uid, move); + } +} diff --git a/Resources/Prototypes/Entities/Mobs/Species/diona.yml b/Resources/Prototypes/Entities/Mobs/Species/diona.yml index e1628c620a2..42383d9a426 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/diona.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/diona.yml @@ -109,6 +109,11 @@ understands: - GalacticCommon - RootSpeak + - type: TraitSpeedModifier + sprintModifier: 0.75 + walkModifier: 0.75 + - type: SpeedModifierImmunity + - type: NoSlip - type: entity parent: BaseSpeciesDummy diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index 915ea0bf674..ca2453e41a1 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -105,6 +105,10 @@ traits: - ParkourTraining - SnailPaced + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona components: - type: TraitSpeedModifier sprintModifier: 0.85 @@ -124,6 +128,10 @@ traits: - ParkourTraining - Sluggish + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona components: - type: TraitSpeedModifier sprintModifier: 0.7 diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index 0da622da3c9..56a8549c933 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -97,6 +97,10 @@ traits: - Sluggish - SnailPaced + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona components: - type: ClimbDelayModifier climbDelayMultiplier: 0.70 From 3657ad42d2f0ab15f44bc6d32ee9f442c047090b Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Fri, 9 Aug 2024 17:28:26 +0000 Subject: [PATCH 059/135] Automatic Changelog Update (#704) --- Resources/Changelog/Changelog.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f571aeb6bbf..3f94c100b5a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5133,3 +5133,17 @@ Entries: message: Wall mounted geiger counters have been added to the game. id: 6243 time: '2024-08-09T11:13:13.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Dionas have been given a 25% slower movement speed. In exchange for + that, they gain absolute slip immunity and movement speed modifier + immunity. This makes them immune to slowdown from things like + duffelbags, hardsuits, and spider webs. + - type: Fix + message: >- + Sluggish and Snail-Paced will now properly apply their movement + penalties upon joining. + id: 6244 + time: '2024-08-09T17:28:01.0000000+00:00' From 31e3c02aad4fdb435b9682d42df90e27ef9af96b Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Fri, 9 Aug 2024 16:41:18 -0400 Subject: [PATCH 060/135] Psionic System Cleanup (#703) # Description Just some regular cleanup of PsionicSystem and PsionicAbilitiesSystem. No refactoring today, just cleanup. Tomorrow I will serialize this shit, assuming this gets merged. No media because there's nothing to show. No changelog because this isn't playerfacing. --- .../Psionics/PsionicAbilitiesSystem.cs | 48 +++++++------------ Content.Server/Psionics/PsionicsSystem.cs | 41 ++++------------ 2 files changed, 25 insertions(+), 64 deletions(-) diff --git a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs index ee16aaccfb6..e59696aa904 100644 --- a/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs +++ b/Content.Server/Abilities/Psionics/PsionicAbilitiesSystem.cs @@ -6,13 +6,9 @@ using Content.Server.EUI; using Content.Server.Psionics; using Content.Server.Mind; -using Content.Shared.Mind; -using Content.Shared.Mind.Components; using Content.Shared.StatusEffect; using Robust.Shared.Random; using Robust.Shared.Prototypes; -using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Player; namespace Content.Server.Abilities.Psionics @@ -22,13 +18,14 @@ public sealed class PsionicAbilitiesSystem : EntitySystem [Dependency] private readonly IComponentFactory _componentFactory = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; - [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly EuiManager _euiManager = default!; [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!; [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly MindSystem _mindSystem = default!; + private ISawmill _sawmill = default!; + public override void Initialize() { base.Initialize(); @@ -46,17 +43,11 @@ private void OnPlayerAttached(EntityUid uid, PsionicAwaitingPlayerComponent comp public void AddPsionics(EntityUid uid, bool warn = true) { - if (Deleted(uid)) - return; - - if (HasComp(uid)) + if (Deleted(uid) + || HasComp(uid)) return; - //Don't know if this will work. New mind state vs old. - if (!TryComp(uid, out var mindContainer) || - !_mindSystem.TryGetMind(uid, out _, out var mind )) - //|| - //!_mindSystem.TryGetMind(uid, out var mind, mindContainer)) + if (!_mindSystem.TryGetMind(uid, out _, out var mind)) { EnsureComp(uid); return; @@ -65,7 +56,7 @@ public void AddPsionics(EntityUid uid, bool warn = true) if (!_mindSystem.TryGetSession(mind, out var client)) return; - if (warn && TryComp(uid, out var actor)) + if (warn && HasComp(uid)) _euiManager.OpenEui(new AcceptPsionicsEui(uid, this), client); else AddRandomPsionicPower(uid); @@ -73,10 +64,8 @@ public void AddPsionics(EntityUid uid, bool warn = true) public void AddPsionics(EntityUid uid, string powerComp) { - if (Deleted(uid)) - return; - - if (HasComp(uid)) + if (Deleted(uid) + || HasComp(uid)) return; AddComp(uid); @@ -93,7 +82,7 @@ public void AddRandomPsionicPower(EntityUid uid) if (!_prototypeManager.TryIndex("RandomPsionicPowerPool", out var pool)) { - Logger.Error("Can't index the random psionic power pool!"); + _sawmill.Error("Can't index the random psionic power pool!"); return; } @@ -108,15 +97,13 @@ public void AddRandomPsionicPower(EntityUid uid) public void RemovePsionics(EntityUid uid) { - if (!TryComp(uid, out var psionic)) - return; - - if (!psionic.Removable) + if (!TryComp(uid, out var psionic) + || !psionic.Removable) return; if (!_prototypeManager.TryIndex("RandomPsionicPowerPool", out var pool)) { - Logger.Error("Can't index the random psionic power pool!"); + _sawmill.Error("Can't index the random psionic power pool!"); return; } @@ -127,13 +114,10 @@ public void RemovePsionics(EntityUid uid) if (EntityManager.TryGetComponent(uid, comp.GetType(), out var psionicPower)) RemComp(uid, psionicPower); } - if (psionic.PsionicAbility != null){ - _actionsSystem.TryGetActionData( psionic.PsionicAbility, out var psiAbility ); - if (psiAbility != null){ - var owner = psiAbility.Owner; - _actionsSystem.RemoveAction(uid, psiAbility.Owner); - } - } + if (psionic.PsionicAbility != null + && _actionsSystem.TryGetActionData(psionic.PsionicAbility, out var psiAbility) + && psiAbility is not null) + _actionsSystem.RemoveAction(uid, psionic.PsionicAbility); _statusEffectsSystem.TryAddStatusEffect(uid, "Stutter", TimeSpan.FromMinutes(5), false, "StutteringAccent"); diff --git a/Content.Server/Psionics/PsionicsSystem.cs b/Content.Server/Psionics/PsionicsSystem.cs index 33505e3f6fc..fb5d18f2843 100644 --- a/Content.Server/Psionics/PsionicsSystem.cs +++ b/Content.Server/Psionics/PsionicsSystem.cs @@ -1,19 +1,15 @@ using Content.Shared.Abilities.Psionics; using Content.Shared.StatusEffect; -using Content.Shared.Mobs; using Content.Shared.Psionics.Glimmer; using Content.Shared.Weapons.Melee.Events; using Content.Shared.Damage.Events; -using Content.Shared.IdentityManagement; using Content.Shared.CCVar; using Content.Server.Abilities.Psionics; using Content.Server.Chat.Systems; using Content.Server.Electrocution; using Content.Server.NPC.Components; using Content.Server.NPC.Systems; -using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; -using Robust.Shared.Player; using Robust.Shared.Configuration; using Robust.Shared.Random; @@ -27,7 +23,6 @@ public sealed class PsionicsSystem : EntitySystem [Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!; [Dependency] private readonly MindSwapPowerSystem _mindSwapPowerSystem = default!; [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; - [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly NpcFactionSystem _npcFactonSystem = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; @@ -41,9 +36,7 @@ public override void Update(float frameTime) { base.Update(frameTime); foreach (var roller in _rollers) - { RollPsionics(roller.uid, roller.component, false); - } _rollers.Clear(); } public override void Initialize() @@ -90,13 +83,9 @@ private void OnMeleeHit(EntityUid uid, AntiPsionicWeaponComponent component, Mel private void OnInit(EntityUid uid, PsionicComponent component, ComponentInit args) { - if (!component.Removable) - return; - - if (!TryComp(uid, out var factions)) - return; - - if (_npcFactonSystem.ContainsFaction(uid, "GlimmerMonster", factions)) + if (!component.Removable + || !TryComp(uid, out var factions) + || _npcFactonSystem.ContainsFaction(uid, "GlimmerMonster", factions)) return; _npcFactonSystem.AddFaction(uid, "PsionicInterloper"); @@ -104,7 +93,7 @@ private void OnInit(EntityUid uid, PsionicComponent component, ComponentInit arg private void OnRemove(EntityUid uid, PsionicComponent component, ComponentRemove args) { - if (!TryComp(uid, out var factions)) + if (!HasComp(uid)) return; _npcFactonSystem.RemoveFaction(uid, "PsionicInterloper"); @@ -112,24 +101,14 @@ private void OnRemove(EntityUid uid, PsionicComponent component, ComponentRemove private void OnStamHit(EntityUid uid, AntiPsionicWeaponComponent component, TakeStaminaDamageEvent args) { - var bonus = false; - if (HasComp(args.Target)) - bonus = true; - - if (!bonus) - return; - - - args.FlatModifier += component.PsychicStaminaDamage; + args.FlatModifier += component.PsychicStaminaDamage; } public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, bool applyGlimmer = true, float multiplier = 1f) { - if (HasComp(uid)) - return; - - if (!_cfg.GetCVar(CCVars.PsionicRollsEnabled)) + if (HasComp(uid) + || !_cfg.GetCVar(CCVars.PsionicRollsEnabled)) return; var chance = component.Chance; @@ -154,10 +133,8 @@ public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, boo public void RerollPsionics(EntityUid uid, PotentialPsionicComponent? psionic = null, float bonusMuliplier = 1f) { - if (!Resolve(uid, ref psionic, false)) - return; - - if (psionic.Rerolled) + if (!Resolve(uid, ref psionic, false) + || psionic.Rerolled) return; RollPsionics(uid, psionic, multiplier: bonusMuliplier); From 05364c5ad8d465ea35241bf53397b4721012c5ce Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Fri, 9 Aug 2024 16:41:46 -0400 Subject: [PATCH 061/135] Minor Glimmer System Cleanup (#702) # Description More tedium to get out of the way, I can't do much more than this since by now in the day my adderall has worn off. This just does basic code cleanup of the glimmer system. No media because there's nothing to show. No changelog because this isn't player facing. --- .../Psionics/Glimmer/GlimmerCommands.cs | 6 +- .../Psionics/Glimmer/GlimmerReactiveSystem.cs | 139 ++++++------------ .../Glimmer/PassiveGlimmerReductionSystem.cs | 2 - .../Structures/GlimmerSourceComponent.cs | 8 +- .../Structures/GlimmerStructuresSystem.cs | 10 +- 5 files changed, 57 insertions(+), 108 deletions(-) diff --git a/Content.Server/Psionics/Glimmer/GlimmerCommands.cs b/Content.Server/Psionics/Glimmer/GlimmerCommands.cs index 744f4cdb9a8..9e05886adca 100644 --- a/Content.Server/Psionics/Glimmer/GlimmerCommands.cs +++ b/Content.Server/Psionics/Glimmer/GlimmerCommands.cs @@ -27,10 +27,8 @@ public sealed class GlimmerSetCommand : IConsoleCommand public async void Execute(IConsoleShell shell, string argStr, string[] args) { - if (args.Length != 1) - return; - - if (!int.TryParse(args[0], out var glimmerValue)) + if (args.Length != 1 + || !int.TryParse(args[0], out var glimmerValue)) return; var entMan = IoCManager.Resolve(); diff --git a/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs b/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs index da3b07d6dab..f828874aacb 100644 --- a/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs +++ b/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs @@ -3,12 +3,10 @@ using Content.Server.Electrocution; using Content.Server.Lightning; using Content.Server.Explosion.EntitySystems; -using Content.Server.Construction; using Content.Server.Ghost; using Content.Server.Revenant.EntitySystems; using Content.Shared.Audio; using Content.Shared.Construction.EntitySystems; -using Content.Shared.Coordinates.Helpers; using Content.Shared.GameTicking; using Content.Shared.Psionics.Glimmer; using Content.Shared.Verbs; @@ -16,14 +14,12 @@ using Content.Shared.Damage; using Content.Shared.Destructible; using Content.Shared.Construction.Components; -using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Weapons.Melee.Components; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Map; using Robust.Shared.Random; -using Robust.Shared.Physics.Components; using Robust.Shared.Utility; namespace Content.Server.Psionics.Glimmer @@ -39,13 +35,12 @@ public sealed class GlimmerReactiveSystem : EntitySystem [Dependency] private readonly LightningSystem _lightning = default!; [Dependency] private readonly ExplosionSystem _explosionSystem = default!; [Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!; - [Dependency] private readonly AnchorableSystem _anchorableSystem = default!; [Dependency] private readonly SharedDestructibleSystem _destructibleSystem = default!; [Dependency] private readonly GhostSystem _ghostSystem = default!; [Dependency] private readonly RevenantSystem _revenantSystem = default!; - [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; [Dependency] private readonly SharedPointLightSystem _pointLightSystem = default!; + private ISawmill _sawmill = default!; public float Accumulator = 0; public const float UpdateFrequency = 15f; @@ -78,35 +73,28 @@ private void UpdateEntityState(EntityUid uid, SharedGlimmerReactiveComponent com { var isEnabled = true; - if (component.RequiresApcPower) - if (TryComp(uid, out ApcPowerReceiverComponent? apcPower)) - isEnabled = apcPower.Powered; + if (component.RequiresApcPower + && TryComp(uid, out ApcPowerReceiverComponent? apcPower)) + isEnabled = apcPower.Powered; _appearanceSystem.SetData(uid, GlimmerReactiveVisuals.GlimmerTier, isEnabled ? currentGlimmerTier : GlimmerTier.Minimal); - // update ambient sound + // Update ambient sound if (TryComp(uid, out GlimmerSoundComponent? glimmerSound) && TryComp(uid, out AmbientSoundComponent? ambientSoundComponent) - && glimmerSound.GetSound(currentGlimmerTier, out SoundSpecifier? spec)) + && glimmerSound.GetSound(currentGlimmerTier, out SoundSpecifier? spec) + && spec != null) + _sharedAmbientSoundSystem.SetSound(uid, spec, ambientSoundComponent); + + // Update point light + if (component.ModulatesPointLight + && _pointLightSystem.TryGetLight(uid, out var pointLight)) { - if (spec != null) - _sharedAmbientSoundSystem.SetSound(uid, spec, ambientSoundComponent); + _pointLightSystem.SetEnabled(uid, isEnabled ? currentGlimmerTier != GlimmerTier.Minimal : false, pointLight); + _pointLightSystem.SetEnergy(uid, pointLight.Energy + glimmerTierDelta * component.GlimmerToLightEnergyFactor, pointLight); + _pointLightSystem.SetRadius(uid, pointLight.Radius + glimmerTierDelta * component.GlimmerToLightRadiusFactor, pointLight); } - if (component.ModulatesPointLight) //SharedPointLightComponent is now being fetched via TryGetLight. - if (_pointLightSystem.TryGetLight(uid, out var pointLight)) - { - _pointLightSystem.SetEnabled(uid, isEnabled ? currentGlimmerTier != GlimmerTier.Minimal : false, pointLight); - // The light energy and radius are kept updated even when off - // to prevent the need to store additional state. - // - // Note that this doesn't handle edge cases where the - // PointLightComponent is removed while the - // GlimmerReactiveComponent is still present. - _pointLightSystem.SetEnergy(uid, pointLight.Energy + glimmerTierDelta * component.GlimmerToLightEnergyFactor, pointLight); - _pointLightSystem.SetRadius(uid, pointLight.Radius + glimmerTierDelta * component.GlimmerToLightRadiusFactor, pointLight); - } - } /// @@ -117,7 +105,7 @@ private void UpdateEntityState(EntityUid uid, SharedGlimmerReactiveComponent com private void OnMapInit(EntityUid uid, SharedGlimmerReactiveComponent component, MapInitEvent args) { if (component.RequiresApcPower && !HasComp(uid)) - Logger.Warning($"{ToPrettyString(uid)} had RequiresApcPower set to true but no ApcPowerReceiverComponent was found on init."); + _sawmill.Warning($"{ToPrettyString(uid)} had RequiresApcPower set to true but no ApcPowerReceiverComponent was found on init."); UpdateEntityState(uid, component, LastGlimmerTier, (int) LastGlimmerTier); } @@ -157,7 +145,8 @@ private void OnTierChanged(EntityUid uid, SharedGlimmerReactiveComponent compone receiver.PowerDisabled = false; receiver.NeedsPower = false; - } else + } + else { receiver.NeedsPower = true; } @@ -165,13 +154,10 @@ private void OnTierChanged(EntityUid uid, SharedGlimmerReactiveComponent compone private void AddShockVerb(EntityUid uid, SharedGlimmerReactiveComponent component, GetVerbsEvent args) { - if(!args.CanAccess || !args.CanInteract) - return; - - if (!TryComp(uid, out var receiver)) - return; - - if (receiver.NeedsPower) + if (!args.CanAccess + || !args.CanInteract + || !TryComp(uid, out var receiver) + || receiver.NeedsPower) return; AlternativeVerb verb = new() @@ -181,7 +167,7 @@ private void AddShockVerb(EntityUid uid, SharedGlimmerReactiveComponent componen _sharedAudioSystem.PlayPvs(component.ShockNoises, args.User); _electrocutionSystem.TryDoElectrocution(args.User, null, _glimmerSystem.Glimmer / 200, TimeSpan.FromSeconds((float) _glimmerSystem.Glimmer / 100), false); }, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png")), Text = Loc.GetString("power-switch-component-toggle-verb"), Priority = -3 }; @@ -190,10 +176,8 @@ private void AddShockVerb(EntityUid uid, SharedGlimmerReactiveComponent componen private void OnDamageChanged(EntityUid uid, SharedGlimmerReactiveComponent component, DamageChangedEvent args) { - if (args.Origin == null) - return; - - if (!_random.Prob((float) _glimmerSystem.Glimmer / 1000)) + if (args.Origin == null + || !_random.Prob((float) _glimmerSystem.Glimmer / 1000)) return; var tier = _glimmerSystem.GetGlimmerTier(); @@ -222,27 +206,23 @@ private void OnDestroyed(EntityUid uid, SharedGlimmerReactiveComponent component private void OnUnanchorAttempt(EntityUid uid, SharedGlimmerReactiveComponent component, UnanchorAttemptEvent args) { - if (_glimmerSystem.GetGlimmerTier() >= GlimmerTier.Dangerous) - { - _sharedAudioSystem.PlayPvs(component.ShockNoises, args.User); - _electrocutionSystem.TryDoElectrocution(args.User, null, _glimmerSystem.Glimmer / 200, TimeSpan.FromSeconds((float) _glimmerSystem.Glimmer / 100), false); - args.Cancel(); - } + if (_glimmerSystem.GetGlimmerTier() < GlimmerTier.Dangerous) + return; + + _sharedAudioSystem.PlayPvs(component.ShockNoises, args.User); + _electrocutionSystem.TryDoElectrocution(args.User, null, _glimmerSystem.Glimmer / 200, TimeSpan.FromSeconds((float) _glimmerSystem.Glimmer / 100), false); + args.Cancel(); } public void BeamRandomNearProber(EntityUid prober, int targets, float range = 10f) { List targetList = new(); - foreach (var target in _entityLookupSystem.GetComponentsInRange(_transformSystem.GetMapCoordinates(prober), range)) - { - if (target.AllowedEffects.Contains("Electrocution")) - targetList.Add(target.Owner); - } + foreach (var (target, status) in _entityLookupSystem.GetEntitiesInRange(_transformSystem.GetMapCoordinates(prober), range)) + if (status.AllowedEffects.Contains("Electrocution")) + targetList.Add(target); - foreach(var reactive in _entityLookupSystem.GetComponentsInRange(_transformSystem.GetMapCoordinates(prober), range)) - { - targetList.Add(reactive.Owner); - } + foreach (var reactive in _entityLookupSystem.GetEntitiesInRange(_transformSystem.GetMapCoordinates(prober), range)) + targetList.Add(reactive); _random.Shuffle(targetList); foreach (var target in targetList) @@ -257,10 +237,9 @@ public void BeamRandomNearProber(EntityUid prober, int targets, float range = 10 private void Beam(EntityUid prober, EntityUid target, GlimmerTier tier, bool obeyCD = true) { - if (obeyCD && BeamCooldown != 0) - return; - - if (Deleted(prober) || Deleted(target)) + if (obeyCD && BeamCooldown != 0 + || Deleted(prober) + || Deleted(target)) return; var lxform = Transform(prober); @@ -293,47 +272,27 @@ private void Beam(EntityUid prober, EntityUid target, GlimmerTier tier, bool obe private void AnchorOrExplode(EntityUid uid) { - var xform = Transform(uid); - if (xform.Anchored) - return; - - if (!TryComp(uid, out var physics)) - return; - - var coordinates = xform.Coordinates; - var gridUid = xform.GridUid; - - if (_mapManager.TryGetGrid(gridUid, out var grid)) - { - var tileIndices = grid.TileIndicesFor(coordinates); + if (Transform(uid).GridUid is null) + _destructibleSystem.DestroyEntity(uid); - if (_anchorableSystem.TileFree(grid, tileIndices, physics.CollisionLayer, physics.CollisionMask) && - _transformSystem.AnchorEntity(uid, xform)) - { - return; - } - } - - // Wasn't able to get a grid or a free tile, so explode. - _destructibleSystem.DestroyEntity(uid); + if (HasComp(uid)) + _transformSystem.AnchorEntity(uid, Transform(uid)); } private void OnMeleeThrowOnHitAttempt(Entity ent, ref AttemptMeleeThrowOnHitEvent args) { - var (uid, _) = ent; - if (_glimmerSystem.GetGlimmerTier() < GlimmerTier.Dangerous) return; args.Cancelled = true; args.Handled = true; - _lightning.ShootRandomLightnings(uid, 10, 2, "SuperchargedLightning", 2, false); + _lightning.ShootRandomLightnings(ent, 10, 2, "SuperchargedLightning", 2, false); // Check if the parent of the user is alive, which will be the case if the user is an item and is being held. var zapTarget = _transformSystem.GetParentUid(args.User); if (TryComp(zapTarget, out _)) - _electrocutionSystem.TryDoElectrocution(zapTarget, uid, 5, TimeSpan.FromSeconds(3), true, + _electrocutionSystem.TryDoElectrocution(zapTarget, ent, 5, TimeSpan.FromSeconds(3), true, ignoreInsulation: true); } @@ -360,7 +319,8 @@ public override void Update(float frameTime) var currentGlimmerTier = _glimmerSystem.GetGlimmerTier(); var reactives = EntityQuery(); - if (currentGlimmerTier != LastGlimmerTier) { + if (currentGlimmerTier != LastGlimmerTier) + { var glimmerTierDelta = (int) currentGlimmerTier - (int) LastGlimmerTier; var ev = new GlimmerTierChangedEvent(LastGlimmerTier, currentGlimmerTier, glimmerTierDelta); @@ -378,10 +338,9 @@ public override void Update(float frameTime) _revenantSystem.MakeVisible(true); GhostsVisible = true; foreach (var reactive in reactives) - { BeamRandomNearProber(reactive.Owner, 1, 12); - } - } else if (GhostsVisible == true) + } + else if (GhostsVisible == true) { _ghostSystem.MakeVisible(false); _revenantSystem.MakeVisible(false); diff --git a/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs b/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs index f0da85ce453..57c74398b08 100644 --- a/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs +++ b/Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs @@ -4,7 +4,6 @@ using Content.Shared.CCVar; using Content.Shared.Psionics.Glimmer; using Content.Shared.GameTicking; -using Content.Server.CartridgeLoader.Cartridges; namespace Content.Server.Psionics.Glimmer { @@ -17,7 +16,6 @@ public sealed class PassiveGlimmerReductionSystem : EntitySystem [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; - [Dependency] private readonly GlimmerMonitorCartridgeSystem _cartridgeSys = default!; /// List of glimmer values spaced by minute. public List GlimmerValues = new(); diff --git a/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs index 5babb6c446d..c7db2a5229f 100644 --- a/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs +++ b/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs @@ -6,22 +6,22 @@ namespace Content.Server.Psionics.Glimmer /// public sealed partial class GlimmerSourceComponent : Component { - [DataField("accumulator")] + [DataField] public float Accumulator = 0f; - [DataField("active")] + [DataField] public bool Active = true; /// /// Since glimmer is an int, we'll do it like this. /// - [DataField("secondsPerGlimmer")] + [DataField] public float SecondsPerGlimmer = 10f; /// /// True if it produces glimmer, false if it subtracts it. /// - [DataField("addToGlimmer")] + [DataField] public bool AddToGlimmer = true; } } diff --git a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs index 75125569cb5..8694147dc0e 100644 --- a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs +++ b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs @@ -58,10 +58,8 @@ public override void Update(float frameTime) base.Update(frameTime); foreach (var source in EntityQuery()) { - if (!_powerReceiverSystem.IsPowered(source.Owner)) - continue; - - if (!source.Active) + if (!_powerReceiverSystem.IsPowered(source.Owner) + || !source.Active) continue; source.Accumulator += frameTime; @@ -70,13 +68,9 @@ public override void Update(float frameTime) { source.Accumulator -= source.SecondsPerGlimmer; if (source.AddToGlimmer) - { _glimmerSystem.Glimmer++; - } else - { _glimmerSystem.Glimmer--; - } } } } From c8c859a6a8cdf84ef5ecd08e0091edc719b2730f Mon Sep 17 00:00:00 2001 From: OldDanceJacket <98985560+OldDanceJacket@users.noreply.github.com> Date: Sat, 10 Aug 2024 05:00:06 -0700 Subject: [PATCH 062/135] Melee Pt2 (#693) # PT2 of Melee Weapons The Numbers Don't Lie This is part 2 of the ongoing work of Solid and myself going through and touching up the melee combat in the game. In this part I rebalance all of the melee weapons to generally do less damage, more stamina damage, and be more unique in regards to slight range changes, attack speed adjustments, along with every weapon getting slightly adjusted heavy swing changes ranging from attack rates, damage, range, angle, and how many targets you can hit. Majority of weapons will hit the standard amount of targets of 5(the old norm), but a few are lowered to be single target hits. These are usually tightened in the angle that they attack in(old angle range was 60). Similarly all melee weapons have individual stamina costs on their heavy swings, most of these are in the range of 5 or 10, and following this PR the new standard should be 10 as the outliers that would abuse this have been addressed in this PR. --- # Changelog Normally I would do a changelog but this took awhile and I forgo. :cl: ODJ - tweak: Melee Weapons now feel different across the board, from the Wrench to the Chainsaw, try out their normal swings and their heavy attacks! --------- Co-authored-by: VMSolidus Co-authored-by: jcsmithing --- .../Weapons/Melee/MeleeWeaponSystem.cs | 5 +- Content.Server/Execution/ExecutionSystem.cs | 2 +- .../Weapons/Melee/MeleeWeaponSystem.cs | 11 ++- .../Zombies/ZombieSystem.Transform.cs | 2 +- .../Damage/Systems/StaminaSystem.cs | 3 +- .../Weapons/Melee/MeleeSoundSystem.cs | 6 +- .../Weapons/Melee/MeleeWeaponComponent.cs | 71 ++++++++------ .../Weapons/Melee/SharedMeleeWeaponSystem.cs | 93 ++++++++++--------- .../Locale/en-US/damage/damage-examine.ftl | 1 + .../Consumable/Drinks/drinks_bottles.yml | 11 ++- .../Fun/Instruments/instruments_string.yml | 76 ++++++++++++--- .../Prototypes/Entities/Objects/Fun/toys.yml | 10 ++ .../Entities/Objects/Misc/briefcases.yml | 12 +++ .../Entities/Objects/Misc/broken_bottle.yml | 9 +- .../Objects/Misc/fire_extinguisher.yml | 9 +- .../Objects/Specific/Chapel/bibles.yml | 8 +- .../Objects/Specific/Hydroponics/tools.yml | 45 +++++++-- .../Objects/Specific/Janitorial/janitor.yml | 20 +++- .../Objects/Specific/Medical/surgery.yml | 78 +++++++++++++--- .../Entities/Objects/Tools/flashlights.yml | 16 +++- .../Entities/Objects/Tools/gas_tanks.yml | 9 +- .../Entities/Objects/Tools/jaws_of_life.yml | 12 ++- .../Entities/Objects/Tools/toolbox.yml | 14 ++- .../Entities/Objects/Tools/tools.yml | 68 ++++++++++++-- .../Entities/Objects/Tools/welders.yml | 4 +- .../Objects/Weapons/Melee/baseball_bat.yml | 11 ++- .../Objects/Weapons/Melee/chainsaw.yml | 6 +- .../Entities/Objects/Weapons/Melee/cult.yml | 28 ++++-- .../Objects/Weapons/Melee/e_sword.yml | 14 +-- .../Objects/Weapons/Melee/fireaxe.yml | 10 +- .../Entities/Objects/Weapons/Melee/knife.yml | 39 +++++--- .../Entities/Objects/Weapons/Melee/mining.yml | 22 ++++- .../Objects/Weapons/Melee/pickaxe.yml | 32 +++++-- .../Objects/Weapons/Melee/sledgehammer.yml | 10 +- .../Entities/Objects/Weapons/Melee/spear.yml | 32 ++++--- .../Objects/Weapons/Melee/stunprod.yml | 13 ++- .../Entities/Objects/Weapons/Melee/sword.yml | 48 ++++++++-- .../Objects/Weapons/Melee/white_cane.yml | 15 ++- .../Entities/Objects/Weapons/security.yml | 12 ++- 39 files changed, 675 insertions(+), 212 deletions(-) diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 641d56d3d14..cf987e62c7b 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Client.Gameplay; +using Content.Shared.CCVar; using Content.Shared.CombatMode; using Content.Shared.Effects; using Content.Shared.Hands.Components; @@ -16,8 +17,6 @@ using Robust.Shared.Input; using Robust.Shared.Map; using Robust.Shared.Player; -using Robust.Shared.Prototypes; -using Robust.Shared.Timing; namespace Content.Client.Weapons.Melee; @@ -228,7 +227,7 @@ private void ClientHeavyAttack(EntityUid user, EntityCoordinates coordinates, En // This should really be improved. GetEntitiesInArc uses pos instead of bounding boxes. // Server will validate it with InRangeUnobstructed. var entities = GetNetEntityList(ArcRayCast(userPos, direction.ToWorldAngle(), component.Angle, distance, userXform.MapID, user).ToList()); - RaisePredictiveEvent(new HeavyAttackEvent(GetNetEntity(meleeUid), entities.GetRange(0, Math.Min(MaxTargets, entities.Count)), GetNetCoordinates(coordinates))); + RaisePredictiveEvent(new HeavyAttackEvent(GetNetEntity(meleeUid), entities.GetRange(0, Math.Min(component.MaxTargets, entities.Count)), GetNetCoordinates(coordinates))); } private void OnMeleeLunge(MeleeLungeEvent ev) diff --git a/Content.Server/Execution/ExecutionSystem.cs b/Content.Server/Execution/ExecutionSystem.cs index 3b87fa17cad..326aa1d6a49 100644 --- a/Content.Server/Execution/ExecutionSystem.cs +++ b/Content.Server/Execution/ExecutionSystem.cs @@ -251,7 +251,7 @@ private void OnDoafterMelee(EntityUid uid, SharpComponent component, DoAfterEven return; _damageableSystem.TryChangeDamage(victim, melee.Damage * DamageModifier, true); - _audioSystem.PlayEntity(melee.HitSound, Filter.Pvs(weapon), weapon, true, AudioParams.Default); + _audioSystem.PlayEntity(melee.SoundHit, Filter.Pvs(weapon), weapon, true, AudioParams.Default); if (attacker == victim) { diff --git a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs index 22840cde8f5..d63dd093eec 100644 --- a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs @@ -57,6 +57,9 @@ private void OnMeleeExamineDamage(EntityUid uid, MeleeWeaponComponent component, return; _damageExamine.AddDamageExamine(args.Message, damageSpec, Loc.GetString("damage-melee")); + + if (damageSpec * component.HeavyDamageBaseModifier != damageSpec) + _damageExamine.AddDamageExamine(args.Message, damageSpec * component.HeavyDamageBaseModifier, Loc.GetString("damage-melee-heavy")); } protected override bool ArcRaySuccessful(EntityUid targetUid, Vector2 position, Angle angle, Angle arcWidth, float range, MapId mapId, @@ -132,7 +135,7 @@ protected override bool DoDisarm(EntityUid user, DisarmAttackEvent ev, EntityUid if (attemptEvent.Cancelled) return false; - var chance = CalculateDisarmChance(user, target, inTargetHand, combatMode) * _contests.MassContest(user, target); + var chance = CalculateDisarmChance(user, target, inTargetHand, combatMode); if (_random.Prob(chance)) { @@ -212,7 +215,11 @@ private float CalculateDisarmChance(EntityUid disarmer, EntityUid disarmed, Enti chance += malus.Malus; } - return Math.Clamp(chance, 0f, 1f); + return Math.Clamp(chance + * _contests.MassContest(disarmer, disarmed, false, 0.5f) + * _contests.StaminaContest(disarmer, disarmed, false, 0.5f) + * _contests.HealthContest(disarmer, disarmed, false, 0.5f), + 0f, 1f); } public override void DoLunge(EntityUid user, EntityUid weapon, Angle angle, Vector2 localPos, string? animation, bool predicted = true) diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index c87132cc3cb..c6c71b80345 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -143,7 +143,7 @@ public void ZombifyEntity(EntityUid target, MobStateComponent? mobState = null) melee.AltDisarm = false; melee.Range = 1.2f; melee.Angle = 0.0f; - melee.HitSound = zombiecomp.BiteSound; + melee.SoundHit = zombiecomp.BiteSound; if (mobState.CurrentState == MobState.Alive) { diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index 5c46e6055d1..54a88205b2d 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -260,7 +260,8 @@ public bool TryTakeStamina(EntityUid uid, float value, StaminaComponent? compone public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null, EntityUid? source = null, EntityUid? with = null, bool visual = true, SoundSpecifier? sound = null) { - if (!Resolve(uid, ref component, false)) + if (!Resolve(uid, ref component, false) + || value == 0) return; var ev = new BeforeStaminaDamageEvent(value); diff --git a/Content.Shared/Weapons/Melee/MeleeSoundSystem.cs b/Content.Shared/Weapons/Melee/MeleeSoundSystem.cs index 5bf74802026..350642105a5 100644 --- a/Content.Shared/Weapons/Melee/MeleeSoundSystem.cs +++ b/Content.Shared/Weapons/Melee/MeleeSoundSystem.cs @@ -20,7 +20,7 @@ public sealed class MeleeSoundSystem : EntitySystem ///
public void PlaySwingSound(EntityUid userUid, EntityUid weaponUid, MeleeWeaponComponent weaponComponent) { - _audio.PlayPredicted(weaponComponent.SwingSound, weaponUid, userUid); + _audio.PlayPredicted(weaponComponent.SoundSwing, weaponUid, userUid); } /// @@ -32,8 +32,8 @@ public void PlaySwingSound(EntityUid userUid, EntityUid weaponUid, MeleeWeaponCo /// A sound can be supplied by the itself to override everything else public void PlayHitSound(EntityUid targetUid, EntityUid? userUid, string? damageType, SoundSpecifier? hitSoundOverride, MeleeWeaponComponent weaponComponent) { - var hitSound = weaponComponent.HitSound; - var noDamageSound = weaponComponent.NoDamageSound; + var hitSound = weaponComponent.SoundHit; + var noDamageSound = weaponComponent.SoundNoDamage; var playedSound = false; diff --git a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs index 85d2e4675f7..d30e27e98c7 100644 --- a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs +++ b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs @@ -18,13 +18,12 @@ public sealed partial class MeleeWeaponComponent : Component /// /// Does this entity do a disarm on alt attack. /// - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + [DataField, AutoNetworkedField] public bool AltDisarm = true; /// /// Should the melee weapon's damage stats be examinable. /// - [ViewVariables(VVAccess.ReadWrite)] [DataField] public bool Hidden; @@ -32,14 +31,13 @@ public sealed partial class MeleeWeaponComponent : Component /// Next time this component is allowed to light attack. Heavy attacks are wound up and never have a cooldown. /// [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField] - [ViewVariables(VVAccess.ReadWrite)] [AutoPausedField] public TimeSpan NextAttack; /// /// Starts attack cooldown when equipped if true. /// - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField] public bool ResetOnHandSelected = true; /* @@ -51,77 +49,98 @@ public sealed partial class MeleeWeaponComponent : Component /// /// How many times we can attack per second. /// - [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] + [DataField, AutoNetworkedField] public float AttackRate = 1f; + /// + /// When power attacking, the swing speed (in attacks per second) is multiplied by this amount + /// + [DataField, AutoNetworkedField] + public float HeavyRateModifier = 0.8f; /// /// Are we currently holding down the mouse for an attack. /// Used so we can't just hold the mouse button and attack constantly. /// - [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + [AutoNetworkedField] public bool Attacking = false; /// /// If true, attacks will be repeated automatically without requiring the mouse button to be lifted. /// - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + [DataField, AutoNetworkedField] public bool AutoAttack; /// /// Base damage for this weapon. Can be modified via heavy damage or other means. /// [DataField(required: true)] - [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + [AutoNetworkedField] public DamageSpecifier Damage = default!; - [DataField] - [ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 BluntStaminaDamageFactor = FixedPoint2.New(0.5f); + [DataField, AutoNetworkedField] + public FixedPoint2 BluntStaminaDamageFactor = FixedPoint2.New(1f); /// /// Multiplies damage by this amount for single-target attacks. /// - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField, AutoNetworkedField] public FixedPoint2 ClickDamageModifier = FixedPoint2.New(1); // TODO: Temporarily 1.5 until interactionoutline is adjusted to use melee, then probably drop to 1.2 /// /// Nearest edge range to hit an entity. /// - [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] + [DataField, AutoNetworkedField] public float Range = 1.5f; + /// + /// Attack range for heavy swings + /// + [DataField, AutoNetworkedField] + public float HeavyRangeModifier = 1f; + + /// + /// Weapon damage is multiplied by this amount for heavy swings + /// + [DataField, AutoNetworkedField] + public float HeavyDamageBaseModifier = 1.2f; + /// /// Total width of the angle for wide attacks. /// - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField, AutoNetworkedField] public Angle Angle = Angle.FromDegrees(60); - [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] + [DataField, AutoNetworkedField] public EntProtoId Animation = "WeaponArcPunch"; - [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] + [DataField, AutoNetworkedField] public EntProtoId WideAnimation = "WeaponArcSlash"; /// /// Rotation of the animation. /// 0 degrees means the top faces the attacker. /// - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField, AutoNetworkedField] public Angle WideAnimationRotation = Angle.Zero; - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField] public bool SwingLeft; + [DataField, AutoNetworkedField] + public float HeavyStaminaCost = 20f; + + [DataField, AutoNetworkedField] + public int MaxTargets = 5; + // Sounds /// /// This gets played whenever a melee attack is done. This is predicted by the client. /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("soundSwing"), AutoNetworkedField] - public SoundSpecifier SwingSound { get; set; } = new SoundPathSpecifier("/Audio/Weapons/punchmiss.ogg") + [DataField, AutoNetworkedField] + public SoundSpecifier SoundSwing { get; set; } = new SoundPathSpecifier("/Audio/Weapons/punchmiss.ogg") { Params = AudioParams.Default.WithVolume(-3f).WithVariation(0.025f), }; @@ -130,16 +149,14 @@ public sealed partial class MeleeWeaponComponent : Component // then a player may doubt if the target actually took damage or not. // If overwatch and apex do this then we probably should too. - [ViewVariables(VVAccess.ReadWrite)] - [DataField("soundHit"), AutoNetworkedField] - public SoundSpecifier? HitSound; + [DataField, AutoNetworkedField] + public SoundSpecifier? SoundHit; /// /// Plays if no damage is done to the target entity. /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("soundNoDamage"), AutoNetworkedField] - public SoundSpecifier NoDamageSound { get; set; } = new SoundCollectionSpecifier("WeakHit"); + [DataField, AutoNetworkedField] + public SoundSpecifier SoundNoDamage { get; set; } = new SoundCollectionSpecifier("WeakHit"); } /// diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs index e59b4a13fed..b5a537b7e15 100644 --- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs +++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs @@ -4,7 +4,9 @@ using Content.Shared.ActionBlocker; using Content.Shared.Administration.Logs; using Content.Shared.CombatMode; +using Content.Shared.Contests; using Content.Shared.Damage; +using Content.Shared.Damage.Components; using Content.Shared.Damage.Systems; using Content.Shared.Database; using Content.Shared.FixedPoint; @@ -12,7 +14,6 @@ using Content.Shared.Hands.Components; using Content.Shared.Interaction; using Content.Shared.Inventory; -using Content.Shared.Item; using Content.Shared.Item.ItemToggle.Components; using Content.Shared.Physics; using Content.Shared.Popups; @@ -27,35 +28,30 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -using Robust.Shared.Toolshed.Syntax; using ItemToggleMeleeWeaponComponent = Content.Shared.Item.ItemToggle.Components.ItemToggleMeleeWeaponComponent; namespace Content.Shared.Weapons.Melee; public abstract class SharedMeleeWeaponSystem : EntitySystem { - [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!; - [Dependency] protected readonly ActionBlockerSystem Blocker = default!; - [Dependency] protected readonly SharedCombatModeSystem CombatMode = default!; - [Dependency] protected readonly DamageableSystem Damageable = default!; - [Dependency] protected readonly SharedInteractionSystem Interaction = default!; - [Dependency] protected readonly IMapManager MapManager = default!; - [Dependency] protected readonly SharedPopupSystem PopupSystem = default!; - [Dependency] protected readonly IGameTiming Timing = default!; - [Dependency] protected readonly SharedTransformSystem TransformSystem = default!; - [Dependency] private readonly InventorySystem _inventory = default!; - [Dependency] private readonly MeleeSoundSystem _meleeSound = default!; - [Dependency] private readonly SharedPhysicsSystem _physics = default!; - [Dependency] private readonly IPrototypeManager _protoManager = default!; - [Dependency] private readonly StaminaSystem _stamina = default!; + [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!; + [Dependency] protected readonly ActionBlockerSystem Blocker = default!; + [Dependency] protected readonly SharedCombatModeSystem CombatMode = default!; + [Dependency] protected readonly DamageableSystem Damageable = default!; + [Dependency] protected readonly SharedInteractionSystem Interaction = default!; + [Dependency] protected readonly IMapManager MapManager = default!; + [Dependency] protected readonly SharedPopupSystem PopupSystem = default!; + [Dependency] protected readonly IGameTiming Timing = default!; + [Dependency] protected readonly SharedTransformSystem TransformSystem = default!; + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly MeleeSoundSystem _meleeSound = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly IPrototypeManager _protoManager = default!; + [Dependency] private readonly StaminaSystem _stamina = default!; + [Dependency] private readonly ContestsSystem _contests = default!; private const int AttackMask = (int) (CollisionGroup.MobMask | CollisionGroup.Opaque); - /// - /// Maximum amount of targets allowed for a wide-attack. - /// - public const int MaxTargets = 5; - /// /// If an attack is released within this buffer it's assumed to be full damage. /// @@ -80,8 +76,7 @@ public override void Initialize() SubscribeAllEvent(OnStopAttack); #if DEBUG - SubscribeLocalEvent (OnMapInit); + SubscribeLocalEvent(OnMapInit); } private void OnMapInit(EntityUid uid, MeleeWeaponComponent component, MapInitEvent args) @@ -252,7 +247,11 @@ public FixedPoint2 GetHeavyDamageModifier(EntityUid uid, EntityUid user, MeleeWe var ev = new GetHeavyDamageModifierEvent(uid, component.ClickDamageModifier, 1, user); RaiseLocalEvent(uid, ref ev); - return ev.DamageModifier * ev.Multipliers; + return ev.DamageModifier + * ev.Multipliers + * component.HeavyDamageBaseModifier + * _contests.StaminaContest(user, false, 2f) //Taking stamina damage reduces wide swing damage by up to 50% + / _contests.HealthContest(user, false, 0.8f); //Being injured grants up to 20% more wide swing damage } public bool TryGetWeapon(EntityUid entity, out EntityUid weaponUid, [NotNullWhen(true)] out MeleeWeaponComponent? melee) @@ -340,6 +339,8 @@ private bool AttemptAttack(EntityUid user, EntityUid weaponUid, MeleeWeaponCompo if (!CombatMode.IsInCombatMode(user)) return false; + var fireRateSwingModifier = 1f; + switch (attack) { case LightAttackEvent light: @@ -359,6 +360,9 @@ private bool AttemptAttack(EntityUid user, EntityUid weaponUid, MeleeWeaponCompo if (!Blocker.CanAttack(user, disarmTarget, (weaponUid, weapon), true)) return false; break; + case HeavyAttackEvent: + fireRateSwingModifier *= weapon.HeavyRateModifier; + break; default: if (!Blocker.CanAttack(user, weapon: (weaponUid, weapon))) return false; @@ -366,7 +370,7 @@ private bool AttemptAttack(EntityUid user, EntityUid weaponUid, MeleeWeaponCompo } // Windup time checked elsewhere. - var fireRate = TimeSpan.FromSeconds(1f / GetAttackRate(weaponUid, user, weapon)); + var fireRate = TimeSpan.FromSeconds(1f / GetAttackRate(weaponUid, user, weapon) * fireRateSwingModifier); var swings = 0; // TODO: If we get autoattacks then probably need a shotcounter like guns so we can do timing properly. @@ -436,8 +440,9 @@ private bool AttemptAttack(EntityUid user, EntityUid weaponUid, MeleeWeaponCompo protected virtual void DoLightAttack(EntityUid user, LightAttackEvent ev, EntityUid meleeUid, MeleeWeaponComponent component, ICommonSession? session) { - // If I do not come back later to fix Light Attacks being Heavy Attacks you can throw me in the spider pit -Errant - var damage = GetDamage(meleeUid, user, component) * GetHeavyDamageModifier(meleeUid, user, component); + var damage = GetDamage(meleeUid, user, component) + * _contests.StaminaContest(user) //Taking stamina damage reduces light attack damage by up to 25% + / _contests.HealthContest(user, false, 0.8f); //Being injured grants up to 20% more damage; var target = GetEntity(ev.Target); // For consistency with wide attacks stuff needs damageable. @@ -526,7 +531,7 @@ protected virtual void DoLightAttack(EntityUid user, LightAttackEvent ev, Entity } } - protected abstract void DoDamageEffect(List targets, EntityUid? user, TransformComponent targetXform); + protected abstract void DoDamageEffect(List targets, EntityUid? user, TransformComponent targetXform); private bool DoHeavyAttack(EntityUid user, HeavyAttackEvent ev, EntityUid meleeUid, MeleeWeaponComponent component, ICommonSession? session) { @@ -541,9 +546,9 @@ private bool DoHeavyAttack(EntityUid user, HeavyAttackEvent ev, EntityUid meleeU var userPos = TransformSystem.GetWorldPosition(userXform); var direction = targetMap.Position - userPos; - var distance = Math.Min(component.Range, direction.Length()); + var distance = Math.Min(component.Range * component.HeavyRangeModifier, direction.Length()); - var damage = GetDamage(meleeUid, user, component); + var damage = GetDamage(meleeUid, user, component) * GetHeavyDamageModifier(meleeUid, user, component); var entities = GetEntityList(ev.Entities); if (entities.Count == 0) @@ -567,11 +572,9 @@ private bool DoHeavyAttack(EntityUid user, HeavyAttackEvent ev, EntityUid meleeU return true; } - // Naughty input - if (entities.Count > MaxTargets) - { - entities.RemoveRange(MaxTargets, entities.Count - MaxTargets); - } + var maxTargets = component.MaxTargets; + if (entities.Count > maxTargets) + entities.RemoveRange(maxTargets, entities.Count - maxTargets); // Validate client for (var i = entities.Count - 1; i >= 0; i--) @@ -666,6 +669,10 @@ private bool DoHeavyAttack(EntityUid user, HeavyAttackEvent ev, EntityUid meleeU DoDamageEffect(targets, user, Transform(targets[0])); } + if (TryComp(user, out var stamina)) + _stamina.TakeStaminaDamage(user, component.HeavyStaminaCost, stamina); + + return true; } @@ -785,20 +792,20 @@ private void OnItemToggle(EntityUid uid, ItemToggleMeleeWeaponComponent itemTogg meleeWeapon.Damage = itemToggleMelee.ActivatedDamage; } - meleeWeapon.HitSound = itemToggleMelee.ActivatedSoundOnHit; + meleeWeapon.SoundHit = itemToggleMelee.ActivatedSoundOnHit; if (itemToggleMelee.ActivatedSoundOnHitNoDamage != null) { //Setting the deactivated sound on no damage hit to the weapon's regular value before changing it. - itemToggleMelee.DeactivatedSoundOnHitNoDamage ??= meleeWeapon.NoDamageSound; - meleeWeapon.NoDamageSound = itemToggleMelee.ActivatedSoundOnHitNoDamage; + itemToggleMelee.DeactivatedSoundOnHitNoDamage ??= meleeWeapon.SoundNoDamage; + meleeWeapon.SoundNoDamage = itemToggleMelee.ActivatedSoundOnHitNoDamage; } if (itemToggleMelee.ActivatedSoundOnSwing != null) { //Setting the deactivated sound on no damage hit to the weapon's regular value before changing it. - itemToggleMelee.DeactivatedSoundOnSwing ??= meleeWeapon.SwingSound; - meleeWeapon.SwingSound = itemToggleMelee.ActivatedSoundOnSwing; + itemToggleMelee.DeactivatedSoundOnSwing ??= meleeWeapon.SoundSwing; + meleeWeapon.SoundSwing = itemToggleMelee.ActivatedSoundOnSwing; } if (itemToggleMelee.DeactivatedSecret) @@ -809,13 +816,13 @@ private void OnItemToggle(EntityUid uid, ItemToggleMeleeWeaponComponent itemTogg if (itemToggleMelee.DeactivatedDamage != null) meleeWeapon.Damage = itemToggleMelee.DeactivatedDamage; - meleeWeapon.HitSound = itemToggleMelee.DeactivatedSoundOnHit; + meleeWeapon.SoundHit = itemToggleMelee.DeactivatedSoundOnHit; if (itemToggleMelee.DeactivatedSoundOnHitNoDamage != null) - meleeWeapon.NoDamageSound = itemToggleMelee.DeactivatedSoundOnHitNoDamage; + meleeWeapon.SoundNoDamage = itemToggleMelee.DeactivatedSoundOnHitNoDamage; if (itemToggleMelee.DeactivatedSoundOnSwing != null) - meleeWeapon.SwingSound = itemToggleMelee.DeactivatedSoundOnSwing; + meleeWeapon.SoundSwing = itemToggleMelee.DeactivatedSoundOnSwing; if (itemToggleMelee.DeactivatedSecret) meleeWeapon.Hidden = true; diff --git a/Resources/Locale/en-US/damage/damage-examine.ftl b/Resources/Locale/en-US/damage/damage-examine.ftl index 974b8fa9650..9e24d4d2f72 100644 --- a/Resources/Locale/en-US/damage/damage-examine.ftl +++ b/Resources/Locale/en-US/damage/damage-examine.ftl @@ -5,6 +5,7 @@ damage-examinable-verb-message = Examine the damage values. damage-hitscan = hitscan damage-projectile = projectile damage-melee = melee +damage-melee-heavy = power attack damage-throw = throw damage-examine = It does the following damage: diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml index fc35fae1af8..a6752286dd2 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml @@ -47,6 +47,15 @@ components: - type: Sprite state: icon + - type: MeleeWeapon + bluntStaminaDamageFactor: 2.0 + damage: + types: + Blunt: 7.5 + heavyRangeModifier: 1.5 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 25 - type: DamageOnLand damage: types: @@ -54,7 +63,7 @@ - type: DamageOtherOnHit damage: types: - Blunt: 4 + Blunt: 5 - type: Damageable damageContainer: Inorganic - type: Destructible diff --git a/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml b/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml index fab8b56b06f..947a973bbf6 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/Instruments/instruments_string.yml @@ -14,6 +14,19 @@ - type: Sprite sprite: Objects/Fun/Instruments/eguitar.rsi state: icon + - type: MeleeWeapon + soundHit: + path: /Audio/Nyanotrasen/Weapons/electricguitarhit.ogg + range: 1.85 + damage: + types: + Blunt: 6 + Shock: 1 + bluntStaminaDamageFactor: 1.5 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + angle: 75 - type: Item size: Normal sprite: Objects/Fun/Instruments/eguitar.rsi @@ -43,6 +56,19 @@ - type: Sprite sprite: Objects/Fun/Instruments/bassguitar.rsi state: icon + - type: MeleeWeapon + soundHit: + path: /Audio/Nyanotrasen/Weapons/electricguitarhit.ogg + range: 1.85 + damage: + types: + Blunt: 6 + Shock: 1 + bluntStaminaDamageFactor: 1.5 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + angle: 75 - type: Item size: Normal sprite: Objects/Fun/Instruments/bassguitar.rsi @@ -71,6 +97,27 @@ - type: Sprite sprite: Objects/Fun/Instruments/rockguitar.rsi state: icon + - type: MeleeWeapon + soundHit: + path: /Audio/Nyanotrasen/Weapons/electricguitarhit.ogg + range: 1.85 + attackRate: 1.25 + wideAnimationRotation: 45 + damage: + types: + Blunt: 6 + Shock: 1 + bluntStaminaDamageFactor: 1.5 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 15 + angle: 160 + - type: Wieldable + - type: IncreaseDamageOnWield + damage: + types: + Blunt: 2 + Shock: 1 - type: Item size: Normal sprite: Objects/Fun/Instruments/rockguitar.rsi @@ -82,18 +129,6 @@ - type: Tag tags: - StringInstrument - - type: MeleeWeapon - wideAnimationRotation: 45 - damage: - types: - Blunt: 6 - Slash: 2 - - type: Wieldable - - type: IncreaseDamageOnWield #they don't call it an axe for nothing - damage: - types: - Blunt: 4 - Slash: 2 - type: entity parent: BaseHandheldInstrument @@ -145,14 +180,20 @@ types: Blunt: 20 - type: MeleeWeapon + range: 1.5 wideAnimationRotation: 45 damage: types: - Blunt: 5 + Blunt: 7 + bluntStaminaDamageFactor: 2 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + angle: 75 - type: IncreaseDamageOnWield damage: types: - Blunt: 15 + Blunt: 2 - type: entity parent: BaseHandheldInstrument @@ -186,10 +227,15 @@ - type: MeleeWeapon soundHit: path: /Audio/SimpleStation14/Weapons/Melee/banjohit.ogg + range: 1.5 damage: types: Blunt: 7 - bluntStaminaDamageFactor: 1.5 + bluntStaminaDamageFactor: 2 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + angle: 75 - type: entity parent: BaseHandheldInstrument diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index 094f434c39c..66d6713fb22 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -628,6 +628,16 @@ - type: Sprite sprite: Objects/Fun/ducky.rsi state: icon + - type: MeleeWeapon + attackRate: 1.5 + range: 1.3 + damage: + types: + Blunt: 0.1 + heavyDamageBaseModifier: 2 + heavyStaminaCost: 5 + maxTargets: 8 + angle: 25 - type: Clothing quickEquip: false sprite: Objects/Fun/ducky.rsi diff --git a/Resources/Prototypes/Entities/Objects/Misc/briefcases.yml b/Resources/Prototypes/Entities/Objects/Misc/briefcases.yml index 762204701cb..760a0bafb68 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/briefcases.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/briefcases.yml @@ -9,6 +9,18 @@ - type: Storage grid: - 0,0,5,3 + - type: MeleeWeapon + bluntStaminaDamageFactor: 3.0 + attackRate: 0.9 + range: 1.75 + damage: + types: + Blunt: 3.5 + heavyRateModifier: 0.8 + heavyRangeModifier: 0.8 + heavyDamageBaseModifier: 2 + heavyStaminaCost: 5 + maxTargets: 8 - type: Tag tags: - Briefcase diff --git a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml index 32222d0036c..f8dbabd07a1 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml @@ -7,9 +7,16 @@ - type: Sharp - type: MeleeWeapon attackRate: 1.5 + range: 1.3 damage: types: - Slash: 5 + Slash: 4 + heavyRateModifier: 0.8 + heavyRangeModifier: 0.8 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 5 + maxTargets: 3 + angle: 75 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Sprite diff --git a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml index bae33f27f17..f1802e426fb 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml @@ -38,9 +38,16 @@ hasSafety: true - type: MeleeWeapon wideAnimationRotation: 180 + attackRate: 0.8 + bluntStaminaDamageFactor: 2.5 + range: 1.75 damage: types: - Blunt: 10 + Blunt: 8 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 2 + heavyStaminaCost: 15 + maxTargets: 8 soundHit: path: /Audio/Weapons/smash.ogg - type: Tool diff --git a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml index 1162a3ec71b..9ab53cebc96 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml @@ -45,8 +45,12 @@ - type: MeleeWeapon # Nyanotrasen - Bibles do Holy damage damage: types: - Blunt: 3 - Holy: 10 + Blunt: 4 + Holy: 20 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1 + heavyStaminaCost: 5 + maxTargets: 3 - type: Tag tags: - Book diff --git a/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/tools.yml b/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/tools.yml index 727c75c8794..37b8daddc27 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Hydroponics/tools.yml @@ -16,7 +16,14 @@ swingLeft: true damage: types: - Slash: 6 + Slash: 3.5 + Blunt: 3 + heavyRateModifier: 1 + heavyRangeModifier: 1 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 5 + angle: 100 - type: Item sprite: Objects/Tools/Hydroponics/hoe.rsi @@ -34,9 +41,16 @@ state: icon - type: MeleeWeapon wideAnimationRotation: 90 + attackRate: 0.8 damage: types: - Slash: 7 + Pierce: 7 + heavyRateModifier: 0.9 + heavyRangeModifier: 1.25 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 - type: Item sprite: Objects/Tools/Hydroponics/clippers.rsi storedRotation: -90 @@ -53,9 +67,16 @@ state: icon - type: MeleeWeapon wideAnimationRotation: 135 + range: 1.85 damage: types: - Slash: 10 + Slash: 7 + heavyRateModifier: 0.8 + heavyRangeModifier: 1.25 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 120 - type: Item size: Normal - type: Clothing @@ -81,10 +102,13 @@ - type: MeleeWeapon wideAnimationRotation: 135 swingLeft: true + attackRate: 1.25 + range: 1.25 damage: types: - Slash: 8 - Piercing: 2 + Slash: 10 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 - type: Item sprite: Objects/Tools/Hydroponics/hatchet.rsi @@ -104,14 +128,19 @@ wideAnimationRotation: 45 damage: types: - Blunt: 8 - Piercing: 2 # I guess you can stab it into them? + Blunt: 6 + Slash: 2 # I guess you can stab it into them? + heavyRateModifier: 0.8 + heavyRangeModifier: 1.25 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + angle: 80 soundHit: collection: MetalThud - type: Item sprite: Objects/Tools/Hydroponics/spade.rsi - type: Shovel - speedModifier: 0.75 # slower at digging than a full-sized shovel + speedModifier: 0.85 # slower at digging than a full-sized shovel - type: entity name: plant bag diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml index b192401c8b8..de5c33671a8 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml @@ -8,9 +8,17 @@ sprite: Objects/Specific/Janitorial/mop.rsi state: mop - type: MeleeWeapon + range: 1.85 damage: types: - Blunt: 10 + Blunt: 2 + bluntStaminaDamageFactor: 3 + heavyRateModifier: 0.8 + heavyRangeModifier: 1.25 + heavyDamageBaseModifier: 1.25 + heavyStaminaCost: 10 + maxTargets: 2 + angle: 180 soundHit: collection: MetalThud - type: Spillable @@ -48,9 +56,17 @@ sprite: Objects/Specific/Janitorial/advmop.rsi state: advmop - type: MeleeWeapon + range: 1.85 damage: types: - Blunt: 10 + Blunt: 2 + bluntStaminaDamageFactor: 3 + heavyRateModifier: 0.8 + heavyRangeModifier: 1.25 + heavyDamageBaseModifier: 1.25 + heavyStaminaCost: 10 + maxTargets: 2 + angle: 180 soundHit: collection: MetalThud - type: Spillable diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml index aa0cf461872..c81768da4d3 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml @@ -50,9 +50,15 @@ - 0,0,1,0 - 1,1,1,1 - type: MeleeWeapon + attackRate: 0.75 + range: 1.3 damage: types: - Piercing: 10 + Piercing: 8 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 soundHit: path: /Audio/Items/drill_hit.ogg - type: StaticPrice @@ -80,10 +86,16 @@ - type: MeleeWeapon wideAnimationRotation: 90 swingLeft: true - attackRate: 1.5 + attackRate: 1.25 + range: 1.25 damage: types: - Slash: 8 + Slash: 7.5 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.25 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 soundHit: path: /Audio/Weapons/bladeslice.ogg @@ -111,7 +123,7 @@ - type: MeleeWeapon damage: types: - Slash: 12 + Slash: 8 - type: entity name: laser scalpel @@ -121,6 +133,11 @@ components: - type: Sprite state: laser + - type: MeleeWeapon + damage: + types: + Slash: 6.5 + Heat: 1 - type: Item heldPrefix: laser @@ -179,7 +196,19 @@ qualities: - Sawing speed: 1.0 -# No melee for regular saw because have you ever seen someone use a band saw as a weapon? It's dumb. + - type: MeleeWeapon + attackRate: 0.75 + range: 1.35 + damage: + types: + Blunt: 2.5 + Slash: 6.5 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.0 + heavyStaminaCost: 20 + maxTargets: 8 + angle: 20 +# ~~No melee for regular saw because have you ever seen someone use a band saw as a weapon? It's dumb.~~ No, I'm going to saw through your bones. - type: entity name: choppa @@ -192,9 +221,17 @@ - type: Item heldPrefix: improv - type: MeleeWeapon + attackRate: 0.85 damage: - groups: - Brute: 10 + types: + Blunt: 3 + Slash: 7 + bluntStaminaDamageFactor: 3 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.0 + heavyStaminaCost: 20 + maxTargets: 8 + angle: 20 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Tool @@ -214,9 +251,18 @@ heldPrefix: electric storedRotation: 90 - type: MeleeWeapon + attackRate: 1.15 + range: 1.4 + bluntStaminaDamageFactor: 3.0 damage: - groups: - Brute: 15 + types: + Blunt: 4.5 + Slash: 5.5 + heavyRateModifier: 0.5 + heavyDamageBaseModifier: 1 + heavyStaminaCost: 15 + maxTargets: 8 + angle: 360 soundHit: path: /Audio/Items/drill_hit.ogg - type: Tool @@ -236,10 +282,18 @@ heldPrefix: advanced storedRotation: 90 - type: MeleeWeapon - attackRate: 1.5 + attackRate: 1.25 + range: 1.4 + bluntStaminaDamageFactor: 5.0 damage: - groups: - Brute: 15 + types: + Blunt: 4.5 + Slash: 7.5 + heavyRateModifier: 0.5 + heavyDamageBaseModifier: 1 + heavyStaminaCost: 15 + maxTargets: 8 + angle: 360 soundHit: path: /Audio/Items/drill_hit.ogg - type: Tool diff --git a/Resources/Prototypes/Entities/Objects/Tools/flashlights.yml b/Resources/Prototypes/Entities/Objects/Tools/flashlights.yml index d22e9190921..2b75a7e3dd9 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/flashlights.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/flashlights.yml @@ -54,6 +54,14 @@ shader: unshaded visible: false map: [ "light" ] + - type: MeleeWeapon + attackRate: 0.8 + bluntStaminaDamageFactor: 1.5 + damage: + types: + Blunt: 6 + soundHit: + collection: MetalThud - type: Item sprite: Objects/Tools/flashlight.rsi storedRotation: -90 @@ -108,9 +116,15 @@ map: [ "light" ] - type: MeleeWeapon wideAnimationRotation: 90 + attackRate: 0.8 damage: types: - Blunt: 10 + Blunt: 6.5 + bluntStaminaDamageFactor: 1.5 + heavyRateModifier: 0.9 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 soundHit: collection: MetalThud - type: Item diff --git a/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml b/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml index 2f281e141a1..f739de251cb 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml @@ -34,9 +34,16 @@ - type: MeleeWeapon wideAnimationRotation: 45 attackRate: 0.8 + range: 1.75 damage: types: - Blunt: 10 + Blunt: 8 + bluntStaminaDamageFactor: 2.5 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 15 + maxTargets: 1 + angle: 140 - type: PhysicalComposition materialComposition: Steel: 185 diff --git a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml index 8e2b7597970..36d2f1308fb 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml @@ -44,9 +44,18 @@ changeSound: /Audio/Items/change_jaws.ogg - type: MeleeWeapon wideAnimationRotation: 90 + attackRate: 0.75 + range: 1.75 damage: types: Blunt: 10 + Slash: 2 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 10 + maxTargets: 1 + angle: 20 soundHit: collection: MetalThud @@ -87,4 +96,5 @@ - type: MeleeWeapon damage: types: - Blunt: 14 + Blunt: 12 + Slash: 2 diff --git a/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml b/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml index 9e35443cd4b..6702ae39d69 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml @@ -21,9 +21,15 @@ - type: Item size: Ginormous - type: MeleeWeapon + attackRate: 0.9 + range: 1.75 damage: types: - Blunt: 12 + Blunt: 9 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.8 + heavyStaminaCost: 10 + angle: 80.5 soundHit: path: "/Audio/Weapons/smash.ogg" - type: Tag @@ -134,7 +140,7 @@ - type: MeleeWeapon damage: types: - Blunt: 20 + Blunt: 11.5 - type: entity name: golden toolbox @@ -147,6 +153,10 @@ state: icon - type: Item sprite: Objects/Tools/Toolboxes/toolbox_gold.rsi + - type: MeleeWeapon + damage: + types: + Blunt: 12 - type: entity id: ToolboxThief diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index d135b2f29bb..a6926f1d8c3 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -31,10 +31,16 @@ - state: cutters-cutty-thingy - type: MeleeWeapon wideAnimationRotation: -90 + attackRate: 0.9 + range: 1.6 damage: types: - Piercing: 2 - attackRate: 2 #open and close that shit on their arm like hell! because you sure aren't doing any damage with this + Blunt: 6.5 + heavyRateModifier: 0.9 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 4 + angle: 60 soundHit: path: "/Audio/Items/wirecutter.ogg" - type: Tool @@ -91,10 +97,15 @@ storedRotation: -90 - type: MeleeWeapon wideAnimationRotation: -90 - attackRate: 1 + attackRate: 1.35 damage: types: Piercing: 6 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 soundHit: path: "/Audio/Weapons/bladeslice.ogg" - type: Tool @@ -146,10 +157,16 @@ state: storage - type: MeleeWeapon wideAnimationRotation: 135 - attackRate: 1.5 + attackRate: 0.9 + range: 1.6 damage: types: - Blunt: 4.5 + Blunt: 6.5 + bluntStaminaDamageFactor: 1.5 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.75 + heavyStaminaCost: 5 + angle: 100 soundHit: collection: MetalThud - type: Tool @@ -198,9 +215,12 @@ state: storage - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 1.25 damage: types: - Blunt: 8 + Blunt: 6 + bluntStaminaDamageFactor: 2 + heavyStaminaCost: 5 soundHit: collection: MetalThud - type: Tool @@ -252,6 +272,16 @@ - state: icon - state: green-unlit shader: unshaded + - type: MeleeWeapon + attackRate: 0.75 + damage: + types: + Shock: 2 + heavyRateModifier: 0.9 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 - type: Item size: Small - type: Clothing @@ -391,10 +421,16 @@ price: 100 - type: MeleeWeapon wideAnimationRotation: -90 - attackRate: 1.5 + attackRate: 0.9 + range: 1.4 damage: types: - Piercing: 10 + Piercing: 8 + heavyRateModifier: 0.9 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 soundHit: path: "/Audio/Items/drill_hit.ogg" @@ -600,9 +636,16 @@ state: icon - type: MeleeWeapon wideAnimationRotation: 45 + attackRate: 0.8 + range: 2.0 damage: types: - Blunt: 14 + Blunt: 8 + bluntStaminaDamageFactor: 1.5 + heavyRateModifier: 0.9 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 10 + angle: 100 soundHit: collection: MetalThud - type: Item @@ -642,9 +685,16 @@ - Belt - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 0.9 damage: types: Blunt: 7 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.5 + heavyStaminaCost: 5 + maxTargets: 1 + angle: 20 soundHit: collection: MetalThud - type: Tool diff --git a/Resources/Prototypes/Entities/Objects/Tools/welders.yml b/Resources/Prototypes/Entities/Objects/Tools/welders.yml index e141f35caeb..8214ec56f34 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/welders.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/welders.yml @@ -55,7 +55,7 @@ collection: MetalThud activatedDamage: types: - Heat: 8 + Heat: 7 - type: ItemToggleSize activatedSize: Large - type: ItemToggleHot @@ -75,7 +75,7 @@ wideAnimationRotation: -90 damage: types: - Blunt: 5 #i mean... i GUESS you could use it like that + Blunt: 6 #i mean... i GUESS you could use it like that soundHit: collection: MetalThud - type: RefillableSolution diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml index 834d35a5297..8780d377e05 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml @@ -9,17 +9,24 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 + range: 1.6 damage: types: - Blunt: 10 + Blunt: 7.5 Structural: 5 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.5 + heavyDamageBaseModifier: 1.75 + heavyStaminaCost: 15 + maxTargets: 2 + angle: 120 soundHit: collection: MetalThud - type: Wieldable - type: IncreaseDamageOnWield damage: types: - Blunt: 5 + Blunt: 4 Structural: 10 - type: Item size: Normal diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml index bfdd94add6c..b2727b334c6 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/chainsaw.yml @@ -15,7 +15,6 @@ state: icon - type: MeleeWeapon autoAttack: true - angle: 0 wideAnimationRotation: -135 attackRate: 4 damage: @@ -23,6 +22,11 @@ Slash: 2 Blunt: 2 Structural: 4 + heavyRateModifier: 0.5 + heavyDamageBaseModifier: 1.0 + heavyStaminaCost: 15 + maxTargets: 20 + angle: 160 soundHit: path: /Audio/Weapons/chainsaw.ogg params: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml index ecb6479de70..5e9d789b658 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cult.yml @@ -10,10 +10,14 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 - attackRate: 1.5 + attackRate: 1.25 + range: 1.4 damage: types: - Slash: 12 + Slash: 8 + heavyRateModifier: 0.9 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 - type: Item size: Normal - type: Clothing @@ -35,9 +39,14 @@ - type: MeleeWeapon wideAnimationRotation: -135 attackRate: 0.75 + range: 1.75 damage: types: - Slash: 16 + Slash: 12 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + maxTargets: 6 + angle: 90 - type: Item size: Normal - type: Clothing @@ -62,19 +71,24 @@ - type: MeleeWeapon wideAnimationRotation: -135 attackRate: 0.75 + range: 1.75 damage: types: - Blunt: 10 - Slash: 10 + Blunt: 2 + Slash: 13 Structural: 5 + heavyRateModifier: 0.9 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + angle: 100 soundHit: collection: MetalThud - type: Wieldable - type: IncreaseDamageOnWield damage: types: - Blunt: 5 - Slash: 5 + Blunt: 2 + Slash: 3 Structural: 10 - type: Item size: Ginormous diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index bc376df5eab..0cbc824365d 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -35,8 +35,8 @@ variation: 0.125 activatedDamage: types: - Slash: 15 - Heat: 15 + Slash: 8 + Heat: 10 Structural: 20 - type: Sprite sprite: Objects/Weapons/Melee/e_sword.rsi @@ -49,7 +49,7 @@ map: [ "blade" ] - type: MeleeWeapon wideAnimationRotation: -135 - attackRate: 1 + attackRate: 1.25 damage: types: Blunt: 4.5 @@ -106,8 +106,8 @@ variation: 0.250 activatedDamage: types: - Slash: 10 - Heat: 10 + Slash: 4 + Heat: 8 deactivatedSecret: true - type: ItemToggleActiveSound activeSound: @@ -245,8 +245,8 @@ variation: 0.250 activatedDamage: types: - Slash: 12 - Heat: 12 + Slash: 8 + Heat: 13 Structural: 15 - type: ItemToggleActiveSound activeSound: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml index 93765ec40c3..b30a2855796 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml @@ -18,16 +18,20 @@ damage: types: # axes are kinda like sharp hammers, you know? - Blunt: 5 - Slash: 10 + Blunt: 4 + Slash: 6 Structural: 10 + heavyDamageBaseModifier: 1.0 + heavyStaminaCost: 10 + angle: 100 soundHit: collection: MetalThud - type: Wieldable - type: IncreaseDamageOnWield damage: types: - Slash: 10 + Blunt: 2 + Slash: 5 Structural: 40 - type: Item size: Ginormous diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml index 9cd1bb29408..68f8863d116 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml @@ -12,9 +12,16 @@ - Knife - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 1.25 + range: 1.4 damage: types: - Slash: 10 + Slash: 8 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 3 + angle: 40 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Sprite @@ -60,10 +67,11 @@ state: butch - type: MeleeWeapon wideAnimationRotation: -115 - attackRate: 1.5 + attackRate: 1 damage: types: - Slash: 13 + Slash: 8 + Blunt: 1 - type: Item size: Normal sprite: Objects/Weapons/Melee/cleaver.rsi @@ -87,15 +95,16 @@ - type: MeleeWeapon wideAnimationRotation: -135 attackRate: 1.5 + range: 1.4 damage: types: - Slash: 12 + Slash: 9 - type: EmbeddableProjectile sound: /Audio/Weapons/star_hit.ogg - type: DamageOtherOnHit damage: types: - Slash: 10 + Slash: 9 - type: Item sprite: Objects/Weapons/Melee/combat_knife.rsi - type: DisarmMalus @@ -110,6 +119,13 @@ - type: Sprite sprite: Objects/Weapons/Melee/survival_knife.rsi state: icon + - type: MeleeWeapon + wideAnimationRotation: -135 + attackRate: 1.25 + range: 1.5 + damage: + types: + Slash: 8 - type: Item sprite: Objects/Weapons/Melee/survival_knife.rsi @@ -124,9 +140,10 @@ state: icon - type: MeleeWeapon attackRate: 1.0 + range: 1.75 damage: types: - Slash: 15 + Slash: 10 - type: Item sprite: Objects/Weapons/Melee/kukri_knife.rsi @@ -186,7 +203,8 @@ sprite: Objects/Weapons/Melee/shiv.rsi state: icon - type: MeleeWeapon - attackRate: 1.5 + attackRate: 1.75 + range: 0.75 damage: types: Slash: 5.5 @@ -205,7 +223,6 @@ graph: ReinforcedShiv node: icon - type: MeleeWeapon - attackRate: 1.5 damage: types: Slash: 7 #each "tier" grants an additional 2 damage @@ -224,10 +241,9 @@ graph: PlasmaShiv node: icon - type: MeleeWeapon - attackRate: 1.5 damage: types: - Slash: 9 + Slash: 8.5 - type: Item sprite: Objects/Weapons/Melee/plasma_shiv.rsi - type: Sprite @@ -243,10 +259,9 @@ graph: UraniumShiv node: icon - type: MeleeWeapon - attackRate: 1.5 damage: types: - Slash: 7 + Slash: 6.5 Radiation: 4 - type: Item sprite: Objects/Weapons/Melee/uranium_shiv.rsi diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml index ccf45bf59aa..a1addba2625 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml @@ -43,12 +43,18 @@ capacity: 1 count: 1 - type: MeleeWeapon - attackRate: 1.5 + attackRate: 0.75 + range: 1.75 wideAnimationRotation: -135 damage: types: - Blunt: 10 - Slash: 5 + Blunt: 8 + Slash: 4 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + angle: 120 soundHit: collection: MetalThud - type: Wieldable @@ -79,10 +85,16 @@ - type: MeleeWeapon autoAttack: true wideAnimationRotation: -135 - attackRate: 2 + attackRate: 1.25 + range: 1.4 damage: types: - Slash: 15 + Slash: 9 + heavyRateModifier: 0.9 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 2 + angle: 20 - type: Tag tags: - Knife diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml index 324d4ee878e..6ba659ccb40 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/pickaxe.yml @@ -11,21 +11,27 @@ sprite: Objects/Weapons/Melee/pickaxe.rsi state: pickaxe - type: MeleeWeapon - attackRate: 0.7 + attackRate: 0.75 + range: 1.75 wideAnimationRotation: -135 soundHit: path: "/Audio/Weapons/smash.ogg" params: volume: -3 damage: - groups: - Brute: 5 + types: + Blunt: 6 + Pierce: 3 + bluntStaminaDamageFactor: 2.0 + heavyDamageBaseModifier: 1.75 + heavyStaminaCost: 5 + maxTargets: 2 + angle: 60 - type: Wieldable - type: IncreaseDamageOnWield damage: - groups: - Brute: 10 types: + Blunt: 5 Structural: 30 - type: Item size: Normal @@ -52,16 +58,24 @@ state: handdrill - type: MeleeWeapon autoAttack: true - angle: 0 wideAnimationRotation: -90 soundHit: path: "/Audio/Items/drill_hit.ogg" - attackRate: 3.5 + attackRate: 0.5 + range: 1.4 damage: - groups: - Brute: 3 types: + Blunt: 9 + Slash: 3 Structural: 12 + bluntStaminaDamageFactor: 4.0 + heavyRateModifier: 1 + heavyRangeModifier: 2 + heavyDamageBaseModifier: 1 + heavyStaminaCost: 10 + maxTargets: 3 + angle: 20 + - type: ReverseEngineering # Nyano difficulty: 2 recipes: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml index 0c75015d9aa..ecc84e50073 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml @@ -9,10 +9,18 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 0.8 + range: 1.75 damage: types: - Blunt: 10 + Blunt: 6 Structural: 10 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.75 + heavyStaminaCost: 15 + maxTargets: 10 + angle: 120 soundHit: collection: MetalThud - type: Wieldable diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml index 0def916ddc7..576d0b2a0ce 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml @@ -35,17 +35,24 @@ visible: false - type: MeleeWeapon wideAnimationRotation: -135 + range: 1.75 damage: types: - Piercing: 12 - angle: 0 + Piercing: 7 + Slash: 1 + heavyRateModifier: 0.75 + heavyRangeModifier: 1.25 + heavyDamageBaseModifier: 1.0 + heavyStaminaCost: 5 + maxTargets: 3 + angle: 20 animation: WeaponArcThrust soundHit: path: /Audio/Weapons/bladeslice.ogg - type: DamageOtherOnHit damage: types: - Piercing: 15 + Piercing: 10 - type: Item size: Ginormous - type: Clothing @@ -75,7 +82,8 @@ - type: IncreaseDamageOnWield damage: types: - Piercing: 4 + Piercing: 3 + Slash: 3 - type: Damageable damageContainer: Inorganic - type: Destructible @@ -124,11 +132,12 @@ wideAnimationRotation: -135 damage: types: - Piercing: 15 + Piercing: 8.5 + Slash: 1 - type: DamageOtherOnHit damage: types: - Piercing: 18 + Piercing: 12 - type: Construction graph: SpearReinforced @@ -144,11 +153,12 @@ wideAnimationRotation: -135 damage: types: - Piercing: 18 + Piercing: 9.5 + Slash: 1.5 - type: DamageOtherOnHit damage: types: - Piercing: 21 + Piercing: 14 - type: Construction graph: SpearPlasma @@ -164,13 +174,13 @@ wideAnimationRotation: -135 damage: types: - Piercing: 10 + Piercing: 8 Radiation: 8 - type: DamageOtherOnHit damage: types: - Piercing: 12 - Radiation: 9 + Piercing: 8 + Radiation: 8 - type: Construction graph: SpearUranium diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml index b0b166f6ce8..d8955b4defe 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml @@ -30,16 +30,23 @@ energyPerUse: 70 - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 0.8 + range: 1.4 damage: types: - Blunt: 9 + Blunt: 7.5 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.8 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 5 + maxTargets: 3 angle: 60 animation: WeaponArcThrust - type: StaminaDamageOnHit - damage: 20 + damage: 22 sound: /Audio/Weapons/egloves.ogg - type: StaminaDamageOnCollide - damage: 20 + damage: 22 sound: /Audio/Weapons/egloves.ogg - type: Battery maxCharge: 360 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml index 17e31e5893c..82b99ce37e3 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml @@ -10,12 +10,19 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 - attackRate: 1.5 + attackRate: 1.25 + range: 1.75 soundHit: path: /Audio/SimpleStation14/Weapons/Melee/rapierhit.ogg damage: types: Slash: 17 #cmon, it has to be at least BETTER than the rest. + heavyRateModifier: 0.8 + heavyRangeModifier: 1 + heavyDamageBaseModifier: 1 + heavyStaminaCost: 5 + maxTargets: 7 + angle: 80 - type: Reflect enabled: true reflectProb: .5 @@ -43,11 +50,18 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 1.5 soundHit: path: /Audio/SimpleStation14/Weapons/Melee/rapierhit.ogg damage: types: - Slash: 15 + Slash: 12 + heavyRateModifier: 0.5 + heavyRangeModifier: 3 #Superior Japanese folded steel + heavyDamageBaseModifier: 1.25 + heavyStaminaCost: 10 + maxTargets: 1 + angle: 20 - type: Item size: Normal sprite: DeltaV/Objects/Weapons/Melee/katana.rsi #DeltaV @@ -66,7 +80,7 @@ wideAnimationRotation: -60 damage: types: - Slash: 30 + Slash: 25 - type: Item size: Normal sprite: Objects/Weapons/Melee/energykatana.rsi @@ -99,9 +113,15 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 0.8 damage: types: Slash: 15 + heavyRateModifier: 0.8 + heavyRangeModifier: 1.25 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + angle: 80 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Item @@ -121,10 +141,19 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 - attackRate: 0.75 + attackRate: 0.65 + range: 1.85 damage: types: - Slash: 20 + Slash: 19 + Blunt: 1 + bluntStaminaDamageFactor: 25.0 + heavyRateModifier: 0.5 + heavyRangeModifier: 1 + heavyDamageBaseModifier: 1 + heavyStaminaCost: 20 + maxTargets: 10 + angle: 200 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Item @@ -150,9 +179,16 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 1.25 damage: types: - Slash: 16 + Slash: 12 + heavyRateModifier: 0.8 + heavyRangeModifier: 1.2 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 + maxTargets: 3 + angle: 40 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Item diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml index 6b24c96e309..123de813cbd 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml @@ -12,16 +12,23 @@ sprite: Objects/Weapons/Melee/white_cane.rsi - type: MeleeWeapon wideAnimationRotation: 45 + attackRate: 0.9 + range: 1.6 damage: types: - Blunt: 5 - - type: StaminaDamageOnHit - damage: 5 + Blunt: 6 + bluntStaminaDamageFactor: 2.5 + heavyRateModifier: 0.5 + heavyRangeModifier: 1.75 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 0 + maxTargets: 1 + angle: 20 - type: Wieldable - type: IncreaseDamageOnWield damage: types: - Blunt: 3 + Blunt: 2 - type: UseDelay delay: 1 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/security.yml b/Resources/Prototypes/Entities/Objects/Weapons/security.yml index 9ac737e9cbb..a952713dd5f 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/security.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/security.yml @@ -35,6 +35,10 @@ types: Blunt: 7 bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.75 + heavyDamageBaseModifier: 1.75 + heavyStaminaCost: 5 + maxTargets: 3 angle: 60 animation: WeaponArcSlash - type: StaminaDamageOnHit @@ -93,12 +97,16 @@ state: icon - type: MeleeWeapon wideAnimationRotation: -135 + attackRate: 0.8 damage: types: - Blunt: 20 + Blunt: 15 soundHit: collection: MetalThud - bluntStaminaDamageFactor: 1.5 + bluntStaminaDamageFactor: 2 + heavyRateModifier: 1 + heavyDamageBaseModifier: 1.2 + heavyStaminaCost: 10 - type: Item size: Normal - type: Clothing From c5fb2026ec7477fd32e6eec1b052f5641e6b8ee1 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 10 Aug 2024 12:00:29 +0000 Subject: [PATCH 063/135] Automatic Changelog Update (#693) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 3f94c100b5a..58afb71648b 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5147,3 +5147,11 @@ Entries: penalties upon joining. id: 6244 time: '2024-08-09T17:28:01.0000000+00:00' +- author: ODJ + changes: + - type: Tweak + message: >- + Melee Weapons now feel different across the board, from the Wrench to + the Chainsaw, try out their normal swings and their heavy attacks! + id: 6245 + time: '2024-08-10T12:00:06.0000000+00:00' From cb6e6ae8b60f3442642b1b7e7ee3afc2ee29e142 Mon Sep 17 00:00:00 2001 From: Rane <60792108+Elijahrane@users.noreply.github.com> Date: Sat, 10 Aug 2024 08:03:11 -0400 Subject: [PATCH 064/135] Rename Mantis (#709) "Mantis" was going to be the original name, but the doubling as detective lead me to needing to add the qualifier "forensic" to make that part clearer. The "Mantis" was already there to imply the psionic part. For "psionic mantis" defenders, I propose an alternative renaming scheme: Mystagogue -> Psionic Mystagogue Mantis -> Psionic Mantis Cyborg -> Robotic Cyborg Chaplain -> Religious Chaplain Players either already know what a mantis is, or they've got little enough playtime that there's still some intrigue left in the setting and it's something they can learn by observation. Weird names are mostly restricted to one dept here and a tinge harder time understanding it is what I'd call "Mystery" rather than something that's undesirable here. The mechanic the mantis interacts with - psionics - is also somewhat hidden and esoteric. # Media ![image](https://github.com/user-attachments/assets/8706c0cd-97a3-4ed6-a0e4-e23012a461a7) ![image](https://github.com/user-attachments/assets/7e6296fb-52ca-4d4e-b40d-2e166520d4b5) # Changelog :cl: Rane - tweak: Renamed "Psionic Mantis" to "Mantis", as it was originally going to be called. --- Resources/Locale/en-US/deltav/prototypes/access/accesses.ftl | 2 +- Resources/Locale/en-US/nyanotrasen/job/job-names.ftl | 4 ++-- Resources/Locale/en-US/psionics/stamp-component.ftl | 2 +- Resources/Maps/hammurabi.yml | 2 +- Resources/Prototypes/Access/misc.yml | 2 +- Resources/Prototypes/Access/research.yml | 2 +- .../Prototypes/Nyanotrasen/Entities/Clothing/Belt/belts.yml | 2 +- .../Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml | 2 +- .../Nyanotrasen/Entities/Clothing/OuterClothing/coats.yml | 2 +- .../Entities/Clothing/OuterClothing/wintercoats.yml | 2 +- .../Prototypes/Nyanotrasen/Entities/Clothing/Shoes/boots.yml | 2 +- .../Nyanotrasen/Entities/Clothing/Uniforms/jumpsuits.yml | 4 ++-- .../Prototypes/Nyanotrasen/Entities/Markers/Spawners/jobs.yml | 2 +- .../Entities/Objects/Devices/Misc/identification_cards.yml | 2 +- .../Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml | 2 +- .../Prototypes/Nyanotrasen/Entities/Objects/Misc/paper.yml | 2 +- .../Entities/Structures/Storage/Closets/Lockers/lockers.yml | 2 +- .../Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml | 2 +- Resources/Prototypes/Roles/Jobs/Science/research_director.yml | 2 +- Resources/ServerInfo/Rules.txt | 2 +- 20 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Resources/Locale/en-US/deltav/prototypes/access/accesses.ftl b/Resources/Locale/en-US/deltav/prototypes/access/accesses.ftl index 2c5a3c871c0..3ebfe8bf1b1 100644 --- a/Resources/Locale/en-US/deltav/prototypes/access/accesses.ftl +++ b/Resources/Locale/en-US/deltav/prototypes/access/accesses.ftl @@ -1,5 +1,5 @@ id-card-access-level-orders = Orders -id-card-access-level-mantis = Psionic Mantis +id-card-access-level-mantis = Mantis id-card-access-level-chief-justice = Chief Justice id-card-access-level-prosecutor = Prosecutor id-card-access-level-justice = Justice diff --git a/Resources/Locale/en-US/nyanotrasen/job/job-names.ftl b/Resources/Locale/en-US/nyanotrasen/job/job-names.ftl index bc99a777f1a..8660d214615 100644 --- a/Resources/Locale/en-US/nyanotrasen/job/job-names.ftl +++ b/Resources/Locale/en-US/nyanotrasen/job/job-names.ftl @@ -3,8 +3,8 @@ job-name-guard = Prison Guard job-name-mail-carrier = Courier job-name-martialartist = Martial Artist job-name-prisoner = Prisoner -job-name-mantis = Psionic Mantis +job-name-mantis = Mantis # Role timers JobMailCarrier = Courier -JobForensicMantis = Psionic Mantis +JobForensicMantis = Mantis diff --git a/Resources/Locale/en-US/psionics/stamp-component.ftl b/Resources/Locale/en-US/psionics/stamp-component.ftl index 0434e6d26ac..381278f8cf9 100644 --- a/Resources/Locale/en-US/psionics/stamp-component.ftl +++ b/Resources/Locale/en-US/psionics/stamp-component.ftl @@ -1 +1 @@ -stamp-component-stamped-name-mantis = Psionic Mantis +stamp-component-stamped-name-mantis = Mantis diff --git a/Resources/Maps/hammurabi.yml b/Resources/Maps/hammurabi.yml index 022c647ba76..0afaa64934e 100644 --- a/Resources/Maps/hammurabi.yml +++ b/Resources/Maps/hammurabi.yml @@ -26862,7 +26862,7 @@ entities: - uid: 18085 components: - type: MetaData - name: psionic mantis office/epistemics hall APC + name: mantis office/epistemics hall APC - type: Transform pos: -31.5,-37.5 parent: 1 diff --git a/Resources/Prototypes/Access/misc.yml b/Resources/Prototypes/Access/misc.yml index f717c57a000..f402c7544a0 100644 --- a/Resources/Prototypes/Access/misc.yml +++ b/Resources/Prototypes/Access/misc.yml @@ -34,7 +34,7 @@ - Atmospherics - Mail # Nyanotrasen - MailCarrier, see Resources/Prototypes/Nyanotrasen/Roles/Jobs/Cargo/mail-carrier.yml - Orders # DeltaV - Orders, see Resources/Prototypes/DeltaV/Access/cargo.yml - - Mantis # DeltaV - Psionic Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml + - Mantis # DeltaV - Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml - Paramedic # DeltaV - Add Paramedic access - Psychologist # DeltaV - Add Psychologist access - Boxer # DeltaV - Add Boxer access diff --git a/Resources/Prototypes/Access/research.yml b/Resources/Prototypes/Access/research.yml index f0de2c93db4..3e3b0432b45 100644 --- a/Resources/Prototypes/Access/research.yml +++ b/Resources/Prototypes/Access/research.yml @@ -11,4 +11,4 @@ tags: - ResearchDirector - Research - - Mantis # DeltaV - Psionic Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml + - Mantis # DeltaV - Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Belt/belts.yml index 4f2ac846efa..8847f8d03a9 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Belt/belts.yml @@ -1,7 +1,7 @@ - type: entity parent: ClothingBeltStorageBase id: ClothingBeltMantis - name: psionic mantis' belt # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' belt description: Perfect for storing all of your equipment. components: - type: Sprite diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml index 2cd9785d989..deaca17558a 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml @@ -124,7 +124,7 @@ - type: entity parent: ClothingHeadBase id: ClothingHeadHatFezMantis - name: psionic mantis' fez # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' fez description: A fine red fez with a gold tassel. components: - type: Sprite diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/coats.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/coats.yml index a16f6cd2212..75f8c7ddd01 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/coats.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/coats.yml @@ -1,7 +1,7 @@ - type: entity parent: ClothingOuterStorageBase id: ClothingOuterCoatMantis - name: psionic mantis' jacket # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' jacket description: Modeled after an ancient infantry uniform, this jacket may guard you against the unknown in your journey for the truth. components: - type: Sprite diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml index b83cd75fc11..748ae0e9a4d 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml @@ -47,7 +47,7 @@ - type: entity parent: ClothingOuterWinterCoat id: ClothingOuterWinterCoatMantis - name: psionic mantis' winter coat # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' winter coat description: Solve cold cases in style. components: - type: Sprite diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Shoes/boots.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Shoes/boots.yml index 4b1cec27f6c..207abcba801 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Shoes/boots.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Shoes/boots.yml @@ -1,7 +1,7 @@ - type: entity parent: ClothingShoesBaseButcherable id: ClothingShoesBootsMantis - name: psionic mantis' boots # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' boots description: Soft, comfortable, and good for rough terrain. components: - type: Sprite diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Uniforms/jumpsuits.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Uniforms/jumpsuits.yml index 11f6d32b5c3..b238ef7b063 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Uniforms/jumpsuits.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Uniforms/jumpsuits.yml @@ -72,7 +72,7 @@ - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitMantis - name: psionic mantis' uniform # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' uniform description: Modeled after an ancient infantry uniform, this uniform has superior mobility for tense situations. components: - type: Sprite @@ -83,7 +83,7 @@ - type: entity parent: ClothingUniformSkirtBase id: ClothingUniformSkirtMantis - name: psionic mantis' jumpskirt # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' jumpskirt description: Adapted from an ancient infantry uniform, this jumpskirt has superior mobility for tense situations. components: - type: Sprite diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/jobs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/jobs.yml index ebe73808e53..62a24bd75b9 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/jobs.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/jobs.yml @@ -65,7 +65,7 @@ - type: entity id: SpawnPointForensicMantis parent: SpawnPointJobBase - name: psionic mantis # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis components: - type: SpawnPoint job_id: ForensicMantis diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/Misc/identification_cards.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/Misc/identification_cards.yml index 94efc40530c..4338b836854 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/Misc/identification_cards.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/Misc/identification_cards.yml @@ -82,7 +82,7 @@ - type: entity parent: IDCardStandard id: ForensicMantisIDCard - name: psionic mantis ID card # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis ID card components: - type: Sprite layers: diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml index 4e6115ba339..d898124b771 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml @@ -99,7 +99,7 @@ - type: entity parent: BasePDA id: ForensicMantisPDA - name: psionic mantis PDA # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis PDA description: Smells like illegal substances. components: - type: Pda diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Misc/paper.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Misc/paper.yml index 22361c9aef6..b381aaa0c7e 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Misc/paper.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Misc/paper.yml @@ -1,5 +1,5 @@ - type: entity - name: psionic mantis' seal # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' seal parent: RubberStampBase id: RubberStampMantis suffix: DO NOT MAP diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Storage/Closets/Lockers/lockers.yml b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Storage/Closets/Lockers/lockers.yml index 2744f965e07..fe25a9cc53c 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Storage/Closets/Lockers/lockers.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Storage/Closets/Lockers/lockers.yml @@ -2,7 +2,7 @@ id: LockerForensicMantis parent: LockerDetective suffix: Empty - name: psionic mantis' cabinet # DeltaV - Rename Forensic Mantis to Psionic Mantis + name: mantis' cabinet description: You'll never know what's inside until you collapse the quantum superposition of all possible mysteries. components: # Because it holds a traitor objective, StrongMetallic, diff --git a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml index 31c08140ac7..e2f99548429 100644 --- a/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml +++ b/Resources/Prototypes/Nyanotrasen/Roles/Jobs/Epistemics/forensicmantis.yml @@ -18,7 +18,7 @@ access: - Research - Maintenance - - Mantis # DeltaV - Psionic Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml + - Mantis # DeltaV - Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml special: - !type:AddComponentSpecial components: diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml index 6f965b31b49..747ee41b840 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml @@ -21,7 +21,7 @@ - Command - Maintenance - ResearchDirector - - Mantis # DeltaV - Psionic Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml + - Mantis # DeltaV - Mantis, see Resources/Prototypes/DeltaV/Access/epistemics.yml - Chapel # DeltaV - Chaplain is in Epistemics - Cryogenics special: # Nyanotrasen - Mystagogue can use the Bible diff --git a/Resources/ServerInfo/Rules.txt b/Resources/ServerInfo/Rules.txt index 9d5ed774b08..c16976b944c 100644 --- a/Resources/ServerInfo/Rules.txt +++ b/Resources/ServerInfo/Rules.txt @@ -92,7 +92,7 @@ Players that are revived by using a defibrillator CAN recall what killed them an [color=#a4885c]11.[/color] Psionics - Players that have psionic powers are allowed to use them at-will to accomplish their roleplay goals. It should be noted that in-character consequences can happen as a result of their use, including being stripped of psionic powers or even death. - - As a psionic mantis, it is not your goal to hunt down psionics. Do not mindbreak others against their will solely because they have psionic powers. + - As a mantis, it is not your goal to hunt down psionics. Do not mindbreak others against their will solely because they have psionic powers. [color=#a4885c]12.[/color] Don't rush for or prepare equipment unrelated to your job for no purpose other than to have it "just in case" (referred to as "Powergaming"). - A medical doctor does not need insulated gloves, and the Head of Personnel does not need to give themselves armory access so they can go grab a gun. Have an actual reason for needing these things. From 07c8eba9f7daf37090aa5fd629fc607be36a9900 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 10 Aug 2024 12:03:36 +0000 Subject: [PATCH 065/135] Automatic Changelog Update (#709) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 58afb71648b..1abacbd8fe1 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5155,3 +5155,11 @@ Entries: the Chainsaw, try out their normal swings and their heavy attacks! id: 6245 time: '2024-08-10T12:00:06.0000000+00:00' +- author: Rane + changes: + - type: Tweak + message: >- + Renamed "Psionic Mantis" to "Mantis", as it was originally going to be + called. + id: 6246 + time: '2024-08-10T12:03:12.0000000+00:00' From 6a12eabbaa1daa99e58d4c4355d507f878141d9b Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Sun, 11 Aug 2024 04:59:22 +0800 Subject: [PATCH 066/135] =?UTF-8?q?New=20Trait:=20Liquor=20Lifeline=20?= =?UTF-8?q?=F0=9F=8D=BA=F0=9F=A9=B9=20(#706)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description **Liquor Lifeline** 🍺 is a new trait (-3 points) that makes you slowly heal Brute and Burn (except Caustic) damage when drunk, healing more the drunker you are. Inspired by the SS13 /tg/station quirk called Drunken Resilience. Strength of Liquor Lifeline healing in terms of its Brute damage healed per tick compared to Bicaridine: - 0.1u to 0.5u Ethanol - 10% Bicaridine - 0.5u to 7u Ethanol - 20% Bicaridine - 7u to 11u Ethanol - 40% Bicaridine - 11u to 15u Ethanol - 80% Bicaridine - 15u+ Ethanol **(drunk poisoning starts)** - 120% Bicaridine ## Media **Trait entry** ![image](https://github.com/user-attachments/assets/31e8cb3a-c5d5-4596-8934-4ad1256b4981) # Changelog :cl: Skubman - add: Add Liquor Lifeline (-3 points), a new positive trait that makes you slowly heal Brute and Burn damage when drunk, healing more the drunker you are. The trait also gives you the benefits of Alcohol Tolerance. - tweak: The cost of the Alcohol Tolerance trait has been reduced from -2 points to -1 point. - add: Dwarves receive the Liquor Lifeline trait for free. --------- Signed-off-by: Angelo Fallaria --- .../Body/Components/MetabolizerComponent.cs | 3 +- .../Assorted/LiquorLifelineComponent.cs | 11 +++ .../Traits/Assorted/LiquorLifelineSystem.cs | 39 ++++++++ Resources/Locale/en-US/traits/traits.ftl | 9 +- Resources/Prototypes/Body/Organs/dwarf.yml | 4 +- .../Chemistry/metabolizer_types.yml | 4 + .../Entities/Mobs/Species/dwarf.yml | 2 + .../Reagents/Consumable/Drink/alcohol.yml | 88 +++++++++++++++---- .../Prototypes/Traits/inconveniences.yml | 7 +- Resources/Prototypes/Traits/skills.yml | 31 ++++++- 10 files changed, 175 insertions(+), 23 deletions(-) create mode 100644 Content.Server/Traits/Assorted/LiquorLifelineComponent.cs create mode 100644 Content.Server/Traits/Assorted/LiquorLifelineSystem.cs diff --git a/Content.Server/Body/Components/MetabolizerComponent.cs b/Content.Server/Body/Components/MetabolizerComponent.cs index 90c99df7db2..7fe7d23cf34 100644 --- a/Content.Server/Body/Components/MetabolizerComponent.cs +++ b/Content.Server/Body/Components/MetabolizerComponent.cs @@ -1,4 +1,5 @@ using Content.Server.Body.Systems; +using Content.Server.Traits.Assorted; using Content.Shared.Body.Prototypes; using Content.Shared.FixedPoint; using Robust.Shared.Prototypes; @@ -44,7 +45,7 @@ public sealed partial class MetabolizerComponent : Component /// List of metabolizer types that this organ is. ex. Human, Slime, Felinid, w/e. /// [DataField] - [Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends + [Access(typeof(MetabolizerSystem), typeof(LiquorLifelineSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends public HashSet>? MetabolizerTypes = null; /// diff --git a/Content.Server/Traits/Assorted/LiquorLifelineComponent.cs b/Content.Server/Traits/Assorted/LiquorLifelineComponent.cs new file mode 100644 index 00000000000..124d0fa3d72 --- /dev/null +++ b/Content.Server/Traits/Assorted/LiquorLifelineComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared.Damage; + +namespace Content.Server.Traits.Assorted; + +/// +/// This is used for the Liquor Lifeline trait. +/// +[RegisterComponent] +public sealed partial class LiquorLifelineComponent : Component +{ +} diff --git a/Content.Server/Traits/Assorted/LiquorLifelineSystem.cs b/Content.Server/Traits/Assorted/LiquorLifelineSystem.cs new file mode 100644 index 00000000000..49618548d3f --- /dev/null +++ b/Content.Server/Traits/Assorted/LiquorLifelineSystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Shared.Body.Components; + +namespace Content.Server.Traits.Assorted; + +public sealed class LiquorLifelineSystem : EntitySystem +{ + [Dependency] private readonly BodySystem _bodySystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnSpawn); + } + + private void OnSpawn(Entity entity, ref ComponentInit args) + { + if (!TryComp(entity, out var body)) + return; + + if (!_bodySystem.TryGetBodyOrganComponents(entity, out var metabolizers, body)) + return; + + foreach (var (metabolizer, _) in metabolizers) + { + if (metabolizer.MetabolizerTypes is null + || metabolizer.MetabolismGroups is null) + continue; + + foreach (var metabolismGroup in metabolizer.MetabolismGroups) + { + // Add the LiquorLifeline metabolizer type to the liver and equivalent organs. + if (metabolismGroup.Id == "Alcohol") + metabolizer.MetabolizerTypes.Add("LiquorLifeline"); + } + } + } +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 16cae663009..ac4eb206c6e 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -18,7 +18,14 @@ trait-name-LightweightDrunk = Lightweight Drunk trait-description-LightweightDrunk = Alcohol has a stronger effect on you trait-name-HeavyweightDrunk = Alcohol Tolerance -trait-description-HeavyweightDrunk = Alcohol is afraid of you. +trait-description-HeavyweightDrunk = + Alcohol is afraid of you. + +trait-name-LiquorLifeline = Liquor Lifeline +trait-description-LiquorLifeline = + Forget the doctor — just hit the bar for your "ethanol prescription"! + While drunk, you slowly heal [color=red]Brute[/color], [color=orange]Heat[/color], [color=orange]Shock[/color], and [color=orange]Cold[/color] damage, scaling with how drunk you are. + You also gain the benefits of [color=lightblue]Alcohol Tolerance[/color]. trait-name-Muted = Muted trait-description-Muted = You can't speak diff --git a/Resources/Prototypes/Body/Organs/dwarf.yml b/Resources/Prototypes/Body/Organs/dwarf.yml index 8da0cb1666f..497bc190cd1 100644 --- a/Resources/Prototypes/Body/Organs/dwarf.yml +++ b/Resources/Prototypes/Body/Organs/dwarf.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity id: OrganDwarfHeart parent: OrganHumanHeart name: dwarf heart @@ -12,7 +12,7 @@ name: dwarf liver components: - type: Metabolizer - metabolizerTypes: [Dwarf] + metabolizerTypes: [Dwarf, LiquorLifeline] - type: entity id: OrganDwarfStomach diff --git a/Resources/Prototypes/Chemistry/metabolizer_types.yml b/Resources/Prototypes/Chemistry/metabolizer_types.yml index 4d48dab9925..316b8f02b53 100644 --- a/Resources/Prototypes/Chemistry/metabolizer_types.yml +++ b/Resources/Prototypes/Chemistry/metabolizer_types.yml @@ -48,3 +48,7 @@ - type: metabolizerType id: Vampiric name: vampiric + +- type: metabolizerType + id: LiquorLifeline + name: liquorlifeline diff --git a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml index b38ea2634fd..055c6522ddc 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml @@ -58,6 +58,8 @@ understands: - GalacticCommon - SolCommon + - type: LightweightDrunk + boozeStrengthMultiplier: 0.5 - type: entity parent: BaseSpeciesDummy diff --git a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml index 12f5a80185a..e31087c309e 100644 --- a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml +++ b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml @@ -164,41 +164,95 @@ conditions: - !type:ReagentThreshold min: 15 - - !type:OrganType - type: Dwarf - shouldHave: false damage: types: Poison: 1 - # dwarves take less toxin damage and heal a marginal amount of brute - - !type:HealthChange + - !type:ChemVomit + probability: 0.04 conditions: - !type:ReagentThreshold - min: 15 + reagent: Ethanol + min: 12 + # dwarves immune to vomiting from alcohol - !type:OrganType type: Dwarf - damage: + shouldHave: false + # Drunken Resilience + - !type:HealthChange + conditions: + - !type:OrganType + type: LiquorLifeline + - !type:ReagentThreshold + reagent: Ethanol + min: 0.10 + max: 0.49 + damage: # NOTE: all damage sets for LiquorLifeline are halved due to + groups: # LightweightDrunkComponent making ethanol half as potent + Brute: -0.4 types: - Poison: 0.2 + Heat: -0.13 + Shock: -0.13 + Cold: -0.13 - !type:HealthChange conditions: + - !type:OrganType + type: LiquorLifeline - !type:ReagentThreshold - min: 15 + reagent: Ethanol + min: 0.50 + max: 6.99 + damage: + groups: + Brute: -0.8 + types: + Heat: -0.26 + Shock: -0.26 + Cold: -0.26 + - !type:HealthChange + conditions: - !type:OrganType - type: Dwarf + type: LiquorLifeline + - !type:ReagentThreshold + reagent: Ethanol + min: 7.00 + max: 10.99 damage: groups: - Brute: -1 - - !type:ChemVomit - probability: 0.04 + Brute: -1.6 + types: + Heat: -0.53 + Shock: -0.53 + Cold: -0.53 + - !type:HealthChange conditions: + - !type:OrganType + type: LiquorLifeline - !type:ReagentThreshold reagent: Ethanol - min: 12 - # dwarves immune to vomiting from alcohol + min: 11 + max: 14.99 + damage: + groups: + Brute: -3.2 + types: + Heat: -1.06 + Shock: -1.06 + Cold: -1.06 + - !type:HealthChange + conditions: - !type:OrganType - type: Dwarf - shouldHave: false + type: LiquorLifeline + - !type:ReagentThreshold + reagent: Ethanol + min: 15 # Overdose threshold + damage: + groups: + Brute: -4.8 + Burn: -4.8 + types: + Heat: -1.60 + Shock: -1.60 + Cold: -1.60 - !type:Drunk boozePower: 2 diff --git a/Resources/Prototypes/Traits/inconveniences.yml b/Resources/Prototypes/Traits/inconveniences.yml index 2dcc30cd97c..5e1e4e4b3f8 100644 --- a/Resources/Prototypes/Traits/inconveniences.yml +++ b/Resources/Prototypes/Traits/inconveniences.yml @@ -1,4 +1,4 @@ -- type: trait +- type: trait id: LightweightDrunk category: Physical requirements: @@ -11,6 +11,11 @@ inverted: true traits: - HeavyweightDrunk + - LiquorLifeline + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Dwarf components: - type: LightweightDrunk boozeStrengthMultiplier: 2 diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index 56a8549c933..40198b724ed 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -36,7 +36,7 @@ - type: trait id: HeavyweightDrunk category: Physical - points: -2 + points: -1 requirements: - !type:CharacterJobRequirement inverted: true @@ -47,7 +47,36 @@ inverted: true traits: - LightweightDrunk + - LiquorLifeline + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Dwarf + components: + - type: LightweightDrunk + boozeStrengthMultiplier: 0.5 + +- type: trait + id: LiquorLifeline + category: Physical + points: -3 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - LightweightDrunk + - HeavyweightDrunk + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Dwarf components: + - type: LiquorLifeline - type: LightweightDrunk boozeStrengthMultiplier: 0.5 From 643df55879dcf76e3d106fb09b25eb3f2a8cce6d Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 10 Aug 2024 20:59:46 +0000 Subject: [PATCH 067/135] Automatic Changelog Update (#706) --- Resources/Changelog/Changelog.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 1abacbd8fe1..232c5b81535 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5163,3 +5163,18 @@ Entries: called. id: 6246 time: '2024-08-10T12:03:12.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Add Liquor Lifeline (-3 points), a new positive trait that makes you + slowly heal Brute and Burn damage when drunk, healing more the drunker + you are. The trait also gives you the benefits of Alcohol Tolerance. + - type: Tweak + message: >- + The cost of the Alcohol Tolerance trait has been reduced from -2 points + to -1 point. + - type: Add + message: Dwarves receive the Liquor Lifeline trait for free. + id: 6247 + time: '2024-08-10T20:59:22.0000000+00:00' From b9bf6e63b6997386cb7f5e4f35d079d361cf860a Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sat, 10 Aug 2024 17:30:42 -0400 Subject: [PATCH 068/135] NyanoCombat 2, Part 1: Simple Melee Refactor (#605) # Description Done in partnership with @OldDanceJacket This is a simple refactor of the Melee System, which introduces some new implementations of Contests, but more importantly lightly refactors melee so that "Light Attack"(Left Click) and "Heavy Attack"(Right Click) are now no longer hardcoded to be the same thing, and now can have different modifiers. We've set things up so that weapons can have different behaviors and bonuses if they are used in a heavy attack as opposed to a light attack, including range and damage. In addition to simple code cleanup, I have done the following things: - Max Number of targets per Power Attack(Wide Swing) is now set via a CVar instead of a constant, but is still defaulted to 5. All Blunt Weapons have been changed to - Deal 100% of Blunt as Stamina(up from 50%) by default - BluntDamageStaminaFactor can now be overridden by specific weapons Light Attacks have been changed to: - Deal up to 25% less damage scaling with taken stamina damage - Deal up to 20% more damage with being injured Heavy Attacks have been changed to: - Deal up to 50% less damage scaling with taken stamina damage - Deal up to 20% more damage with being injured - Now deal (by default) 10 points of stamina damage to the wielder - In a separate PR, nearly every weapon in the game is going to have their Wide Swing(Now "Power Attack") mode stats looked at. - When examining the damage a weapon deals, if it has any damage modifiers when power attacking, these values will be shown in addition to the light attack damage. Heavy attacks can now have separate modifiers for: - Attack Range (multiply against light attack range) - Attack Damage (multiply against light attack damage) - Attack Speed (multiply against light attack speed) - Stamina Cost (overriding the default) We will be building upon this PR throughout the week with additional PRs, to include a full rework of melee weapon values across the entire board. For the most part, this PR is primarily here to give new options for contributors to balance melee weapons. # Note For Maintainers: @OldDanceJacket will be following this up with his own PR containing Part 2, which will include a comprehensive rework of the damage values for every melee weapon in the entire game. Due to this, I can't actually make that much in the way of significant changes to the components in review without messing with his side of things. I also have my own Part 3 that I will be working in partnership with ODJ on throughout this week, which will consist of a pack of combat-system related Traits. # Changelog :cl: @VMSolidus and @OldDanceJacket - add: Being injured now lets you deal up to 20% more damage in melee combat to simulate the adrenaline rush from taking a hit. - add: Taking stamina damage now makes you deal less damage in melee. Up to 25% less for Light Attacks, and 50% less for Power Attacks - add: Wide Swing has been reworked as "Power Attack". Power attacks cost 20 stamina(by default) to perform, and their effects can differ from Light attacks on a per-weapon basis. Individual weapons can also have different stamina costs to power attack with. --------- Signed-off-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- Content.Client/Weapons/Melee/MeleeWeaponSystem.cs | 2 +- Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index cf987e62c7b..98528c691d4 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -222,7 +222,7 @@ private void ClientHeavyAttack(EntityUid user, EntityCoordinates coordinates, En var userPos = TransformSystem.GetWorldPosition(userXform); var direction = targetMap.Position - userPos; - var distance = MathF.Min(component.Range, direction.Length()); + var distance = MathF.Min(component.Range * component.HeavyRangeModifier, direction.Length()); // This should really be improved. GetEntitiesInArc uses pos instead of bounding boxes. // Server will validate it with InRangeUnobstructed. diff --git a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs index d30e27e98c7..2708a07c6eb 100644 --- a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs +++ b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs @@ -133,7 +133,6 @@ public sealed partial class MeleeWeaponComponent : Component [DataField, AutoNetworkedField] public int MaxTargets = 5; - // Sounds /// From e6173420a32c30f8b6c1c679d7b8e625edfe604f Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 10 Aug 2024 21:31:03 +0000 Subject: [PATCH 069/135] Automatic Changelog Update (#605) --- Resources/Changelog/Changelog.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 232c5b81535..f19db16825b 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5178,3 +5178,21 @@ Entries: message: Dwarves receive the Liquor Lifeline trait for free. id: 6247 time: '2024-08-10T20:59:22.0000000+00:00' +- author: VMSolidus + changes: + - type: Add + message: >- + Being injured now lets you deal up to 20% more damage in melee combat to + simulate the adrenaline rush from taking a hit. + - type: Add + message: >- + Taking stamina damage now makes you deal less damage in melee. Up to 25% + less for Light Attacks, and 50% less for Power Attacks + - type: Add + message: >- + Wide Swing has been reworked as "Power Attack". Power attacks cost 20 + stamina(by default) to perform, and their effects can differ from Light + attacks on a per-weapon basis. Individual weapons can also have + different stamina costs to power attack with. + id: 6248 + time: '2024-08-10T21:30:42.0000000+00:00' From 80c3d63c9b3be54e86f3b6fbb1d74c5254d4bbc2 Mon Sep 17 00:00:00 2001 From: Rane <60792108+Elijahrane@users.noreply.github.com> Date: Sat, 10 Aug 2024 17:34:21 -0400 Subject: [PATCH 070/135] Remove Hugging Interaction Popup From Humanoids (#710) # Description Reasoning: 1) Hugging your coworkers isn't necessarily always inappropriate, but it's something that should take a bit more intention than it does now. 2) Event subs in this game right now still have no good method of handling multiple subscriptions to the same event. The hugging event is occupying 2 pieces of prime real estate - the empty hand interaction, which is the most common, and the humanoid interaction, which is the most common and most important. And for what? Spamming popups and chat for something that could just be an emote. 3) Because of the above, it's too easy to accidentally hug people while doing something else - the lack of intersectionality makes people just ignore hugging because they assume it means nothing and was not intentional. This does not lead to good roleplay outcomes. 4) I left the petting stuff on animals because that's much more common and appropriate and you're less likely to be trying to do other complex interactions with them. Also, since they're usually NPCs, it doesn't matter if they get desensitized to the interaction as meaningless, or at least it's out of scope. # Changelog :cl: Rane - remove: Removed the spammable hugging on click. Consider using emotes for this instead. --- .../en-US/interaction/interaction-popup-component.ftl | 6 ------ .../Prototypes/DeltaV/Entities/Mobs/Player/vulpkanin.yml | 5 ----- Resources/Prototypes/Entities/Mobs/Player/arachne.yml | 5 ----- Resources/Prototypes/Entities/Mobs/Player/harpy.yml | 5 ----- Resources/Prototypes/Entities/Mobs/Player/skeleton.yml | 7 +------ Resources/Prototypes/Entities/Mobs/Species/base.yml | 5 ----- .../Prototypes/Nyanotrasen/Entities/Mobs/Player/Oni.yml | 5 ----- .../Nyanotrasen/Entities/Mobs/Player/felinid.yml | 5 ----- 8 files changed, 1 insertion(+), 42 deletions(-) diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl index bb56233ff14..a6eacf13c5d 100644 --- a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl +++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl @@ -77,12 +77,6 @@ comp-window-knock = *knock knock* fence-rattle-success = *rattle* -## Hugging players - -hugging-success-generic = You hug {THE($target)}. -hugging-success-generic-others = { CAPITALIZE(THE($user)) } hugs {THE($target)}. -hugging-success-generic-target = { CAPITALIZE(THE($user)) } hugs you. - ## Other petting-success-tesla = You pet {THE($target)}, violating the laws of nature and physics. diff --git a/Resources/Prototypes/DeltaV/Entities/Mobs/Player/vulpkanin.yml b/Resources/Prototypes/DeltaV/Entities/Mobs/Player/vulpkanin.yml index 06abe8c45fa..718dc3ca559 100644 --- a/Resources/Prototypes/DeltaV/Entities/Mobs/Player/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Entities/Mobs/Player/vulpkanin.yml @@ -5,11 +5,6 @@ id: MobVulpkanin components: - type: CombatMode - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-generic - interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-generic-others - type: MindContainer showExamineInfo: true - type: Input diff --git a/Resources/Prototypes/Entities/Mobs/Player/arachne.yml b/Resources/Prototypes/Entities/Mobs/Player/arachne.yml index bebf42f31ba..cd4123fa80d 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/arachne.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/arachne.yml @@ -5,11 +5,6 @@ id: MobArachne components: - type: CombatMode - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-generic - interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-generic-others - type: MindContainer showExamineInfo: true - type: Input diff --git a/Resources/Prototypes/Entities/Mobs/Player/harpy.yml b/Resources/Prototypes/Entities/Mobs/Player/harpy.yml index 1f4eb696c65..fa6aa98d93c 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/harpy.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/harpy.yml @@ -5,11 +5,6 @@ id: MobHarpy components: - type: CombatMode - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-generic - interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-generic-others - type: MindContainer showExamineInfo: true - type: Input diff --git a/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml index bf41f2dda6e..d2a3225c070 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml @@ -3,12 +3,7 @@ parent: BaseMobSkeletonPerson id: MobSkeletonPerson components: - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-generic - interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-generic-others - - type: PotentialPsionic #Nyano - Summary: makes potentially psionic. + - type: PotentialPsionic #Nyano - Summary: makes potentially psionic. - type: entity name: skeleton pirate diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index c4906f6f975..9fb241c40d7 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -180,11 +180,6 @@ - type: Dna - type: MindContainer showExamineInfo: true - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-generic - interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-generic-others - type: CanHostGuardian - type: NpcFactionMember factions: diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/Oni.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/Oni.yml index 562b9c564ec..e1c867691a1 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/Oni.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/Oni.yml @@ -5,11 +5,6 @@ id: MobOni components: - type: CombatMode - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-generic - interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-generic-others - type: MindContainer showExamineInfo: true - type: Input diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml index db7936cc5b4..9b79c556707 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/felinid.yml @@ -5,11 +5,6 @@ id: MobFelinid components: - type: CombatMode - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-generic - interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-generic-others - type: MindContainer showExamineInfo: true - type: Input From c006ec8ecfc6a960812e6e785281b558df84d804 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 10 Aug 2024 21:34:48 +0000 Subject: [PATCH 071/135] Automatic Changelog Update (#710) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f19db16825b..20054168fd9 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5196,3 +5196,11 @@ Entries: different stamina costs to power attack with. id: 6248 time: '2024-08-10T21:30:42.0000000+00:00' +- author: Rane + changes: + - type: Remove + message: >- + Removed the spammable hugging on click. Consider using emotes for this + instead. + id: 6249 + time: '2024-08-10T21:34:22.0000000+00:00' From 79b3190683300e9f53a825b3a09afff019c62238 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sat, 10 Aug 2024 17:36:09 -0400 Subject: [PATCH 072/135] NyanoCombat 2, Part 3: Physical Traits (#607) # Description Done in partnership with @OldDanceJacket This PR adds 9 additional physical traits to the game, 5 positive, and 4 negative. While this PR is intended to go with NyanoCombat 2, Part 1 and 2, I have made this PR function completely standalone. It does not require either of the two other PRs. ## Positive Traits - **Will To Live**: Increases your Dead threshold by 10 - **Tenacity**: Increases your Crit threshold by 5 - **Vigor**: Increases your maximum Stamina by 10 - **High Adrenaline**: You gain up to 10% more damage with all melee attacks when injured. - **Masochism**: You ignore the first 10% of stamina damage penalties to melee attacks. If NyanoCombat 2 Part 1 isn't merged yet, this makes you deal up to 10% more melee damage when you receive stamina damage. - **Martial Artist**: Your unarmed melee attacks have bonus range, and deal 50% more damage(for every species in the game, this means 7.5 instead of 5 damage). This trait is identical to one that the Boxer job receives for free, thus it cannot be taken by Boxers. ## Negative Traits - **Will To Die**: Decreases your Dead threshold by 15 - **Glass Jaw**: Decreases your Crit Threshold by 10 - **Lethargy**: Decreases your maximum Stamina by 15 - **Adrenal Dysfunction**: Your melee attacks are penalized by up to 20% when injured. If NyanoCombat 2 Part 1 is merged, this cancels out the natural bonus everyone globally gets to melee when injured. - **Low Pain Tolerance**: Your melee attacks are penalized by up to 15% when receiving stamina damage. If NyanoCombat 2 Part 1 is merged, this stacks with the natural penalties everyone globally gets to melee when taking stamina damage. # TODO - [ ] Let ODJ look over these for balance. # Media ![image](https://github.com/user-attachments/assets/242e8b50-8a5e-4079-bf1d-f952ceeade38) # Changelog :cl: VMSolidus and Skubman - add: 11 new Physical Traits have been added to the game! 6 positive traits, and 5 negative traits. --------- Signed-off-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Co-authored-by: Angelo Fallaria Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- .../Components/AdrenalineComponent.cs | 28 +++ .../Components/CritModifierComponent.cs | 16 ++ .../Components/DeadModifierComponent.cs | 16 ++ .../Components/PainToleranceComponent.cs | 28 +++ .../StaminaCritModifierComponent.cs | 16 ++ .../Systems/TraitStatModifierSystem.cs | 63 ++++++ Resources/Locale/en-US/traits/traits.ftl | 59 +++++ Resources/Prototypes/Traits/physical.yml | 208 ++++++++++++++++++ 8 files changed, 434 insertions(+) create mode 100644 Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs create mode 100644 Resources/Prototypes/Traits/physical.yml diff --git a/Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs b/Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs new file mode 100644 index 00000000000..a0c58edb106 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/AdrenalineComponent.cs @@ -0,0 +1,28 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies the Melee System implementation of Health Contest +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class AdrenalineComponent : Component +{ + /// + /// When true, multiplies by the inverse of the resulting Contest. + /// + [DataField] + public bool Inverse { get; private set; } = false; + + /// + /// Used as the RangeModifier input for a Health Contest. + /// + [DataField] + public float RangeModifier { get; private set; } = 1; + + /// + /// Used as the BypassClamp input for a Health Contest. + /// + [DataField] + public bool BypassClamp { get; private set; } = false; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs new file mode 100644 index 00000000000..6cf11e3f7fb --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/CritModifierComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies CritThreshold +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class CritModifierComponent : Component +{ + /// + /// The amount that an entity's critical threshold will be incremented by. + /// + [DataField] + public int CritThresholdModifier { get; private set; } = 0; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs new file mode 100644 index 00000000000..b4ac1bf64fc --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/DeadModifierComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies DeadThreshold +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class DeadModifierComponent : Component +{ + /// + /// The amount that an entity's DeadThreshold will be incremented by. + /// + [DataField] + public int DeadThresholdModifier { get; private set; } = 0; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs b/Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs new file mode 100644 index 00000000000..03b3bb116a8 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/PainToleranceComponent.cs @@ -0,0 +1,28 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies the Melee System implementation of Stamina Contest +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class PainToleranceComponent : Component +{ + /// + /// When true, multiplies by the inverse of the resulting Contest. + /// + [DataField] + public bool Inverse { get; private set; } = false; + + /// + /// Used as the RangeModifier input for a Stamina Contest. + /// + [DataField] + public float RangeModifier { get; private set; } = 1; + + /// + /// Used as the BypassClamp input for a Stamina Contest. + /// + [DataField] + public bool BypassClamp { get; private set; } = false; +} \ No newline at end of file diff --git a/Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs b/Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs new file mode 100644 index 00000000000..28c8ab9b089 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/StaminaCritModifierComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Traits.Assorted.Components; + +/// +/// This is used for any trait that modifies stamina CritThreshold +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class StaminaCritModifierComponent : Component +{ + /// + /// The amount that an entity's stamina critical threshold will be incremented by. + /// + [DataField] + public int CritThresholdModifier { get; private set; } = 0; +} diff --git a/Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs b/Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs new file mode 100644 index 00000000000..85ecf151dd9 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Systems/TraitStatModifierSystem.cs @@ -0,0 +1,63 @@ +using Content.Shared.Contests; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.Traits.Assorted.Components; +using Content.Shared.Weapons.Melee.Events; +using Content.Shared.Damage.Components; + +namespace Content.Shared.Traits.Assorted.Systems; + +public sealed partial class TraitStatModifierSystem : EntitySystem +{ + [Dependency] private readonly ContestsSystem _contests = default!; + [Dependency] private readonly MobThresholdSystem _threshold = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnCritStartup); + SubscribeLocalEvent(OnDeadStartup); + SubscribeLocalEvent(OnStaminaCritStartup); + SubscribeLocalEvent(OnAdrenalineGetDamage); + SubscribeLocalEvent(OnPainToleranceGetDamage); + } + + private void OnCritStartup(EntityUid uid, CritModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var threshold)) + return; + + var critThreshold = _threshold.GetThresholdForState(uid, Mobs.MobState.Critical, threshold); + if (critThreshold != 0) + _threshold.SetMobStateThreshold(uid, critThreshold + component.CritThresholdModifier, Mobs.MobState.Critical); + } + + private void OnDeadStartup(EntityUid uid, DeadModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var threshold)) + return; + + var deadThreshold = _threshold.GetThresholdForState(uid, Mobs.MobState.Dead, threshold); + if (deadThreshold != 0) + _threshold.SetMobStateThreshold(uid, deadThreshold + component.DeadThresholdModifier, Mobs.MobState.Dead); + } + + private void OnStaminaCritStartup(EntityUid uid, StaminaCritModifierComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var stamina)) + return; + + stamina.CritThreshold += component.CritThresholdModifier; + } + + private void OnAdrenalineGetDamage(EntityUid uid, AdrenalineComponent component, ref GetMeleeDamageEvent args) + { + var modifier = _contests.HealthContest(uid, component.BypassClamp, component.RangeModifier); + args.Damage *= component.Inverse ? 1 / modifier : modifier; + } + + private void OnPainToleranceGetDamage(EntityUid uid, PainToleranceComponent component, ref GetMeleeDamageEvent args) + { + var modifier = _contests.StaminaContest(uid, component.BypassClamp, component.RangeModifier); + args.Damage *= component.Inverse ? 1 / modifier : modifier; + } +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index ac4eb206c6e..46ee8572a0b 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -86,6 +86,64 @@ trait-description-Foreigner = For one reason or another you do not speak this station's primary language. Instead, you have a translator issued to you that only you can use. +trait-name-WillToLive = Will To Live +trait-description-WillToLive = + You have an unusually strong "will to live", and will resist death more than others. + Your damage threshold for becoming Dead is increased by 10 points. + +trait-name-WillToDie = Will To Die +trait-description-WillToDie = + You have an unusually weak "will to live", and will succumb to injuries sooner than others. + Your damage threshold for becoming Dead is decreased by 15 points. + +trait-name-Tenacity = Tenacity +trait-description-Tenacity = + Whether it be through raw grit, willpower, or subtle bionic augmentations, you are hardier than others. + Your damage threshold for becoming Critical is increased by 5 points. + +trait-name-GlassJaw = Glass Jaw +trait-description-GlassJaw = + Your body is more fragile than others, resulting in a greater susceptibility to critical injuries + Your damage threshold for becoming Critical is decreased by 10 points. + +trait-name-HighAdrenaline = High Adrenaline +trait-description-HighAdrenaline = + Whether by natural causes, genetic or bionic augmentation, you have a more potent adrenal gland. + When injured, your melee attacks deal up to 10% more damage, in addition to the natural bonuses from adrenaline. + The standard adrenaline bonuses to melee damage are up to a 20% increase. + +trait-name-AdrenalDysfunction = Adrenal Dysfunction +trait-description-AdrenalDysfunction = + Your adrenal gland is completely nonfunctional, or potentially missing outright. + Your melee attacks do not benefit from Adrenaline when injured. + The standard adrenaline bonuses to melee damage are up to a 20% increase. + +trait-name-Masochism = Masochism +trait-description-Masochism = + Deriving enjoyment from your own pain, you are not as inhibited by it as others. + You ignore the first 10% of stamina damage penalties to your melee attacks. + +trait-name-LowPainTolerance = Low Pain Tolerance +trait-description-LowPainTolerance = + Your tolerance for pain is far below average, and its effects are more inhibiting. + Your melee damage is penalized by up to an additional 15% when taking stamina damage. + +trait-name-MartialArtist = Martial Artist +trait-description-MartialArtist = + You have received formal training in unarmed combat, whether with Fists, Feet, or Claws. + Your unarmed melee attacks have a small range increase, and deal 50% more damage. + This does not apply to any form of armed melee, only the weapons you were naturally born with. + +trait-name-Vigor = Vigor +trait-description-Vigor = + Whether by pure determination, fitness, or bionic augmentations, your endurance is enhanced. + Your stamina is increased by 10 points. + +trait-name-Lethargy = Lethargy +trait-description-Lethargy = + You become tired faster than others, making you more vulnerable to exhaustion and fatigue. + Your stamina is decreased by 15 points. + trait-name-SignLanguage = Sign Language trait-description-SignLanguage = You can understand and use Galactic Sign Language (GSL). @@ -129,3 +187,4 @@ trait-name-WeaponsGeneralist = Weapons Generalist trait-description-WeaponsGeneralist = You are a jack of all trades with melee weapons, enabling you to be versatile with your weapon arsenal. Your melee damage bonus for all Brute damage types (Blunt, Slash, Piercing) becomes 25%. + diff --git a/Resources/Prototypes/Traits/physical.yml b/Resources/Prototypes/Traits/physical.yml new file mode 100644 index 00000000000..85d074ffe95 --- /dev/null +++ b/Resources/Prototypes/Traits/physical.yml @@ -0,0 +1,208 @@ +- type: trait + id: WillToLive + category: Physical + points: -2 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - WillToDie + components: + - type: DeadModifier + deadThresholdModifier: 10 + +- type: trait + id: WillToDie + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - WillToLive + components: + - type: DeadModifier + deadThresholdModifier: -15 + +- type: trait + id: Tenacity + category: Physical + points: -2 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - GlassJaw + components: + - type: CritModifier + critThresholdModifier: 5 + +- type: trait + id: GlassJaw + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Tenacity + components: + - type: CritModifier + critThresholdModifier: -10 + +- type: trait + id: Vigor + category: Physical + points: -3 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Lethargy + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Oni + components: + - type: StaminaCritModifier + critThresholdModifier: 10 + +- type: trait + id: Lethargy + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Vigor + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Felinid + components: + - type: StaminaCritModifier + critThresholdModifier: -15 + +- type: trait + id: HighAdrenaline + category: Physical + points: -3 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - AdrenalDysfunction + components: + - type: Adrenaline + rangeModifier: 0.4 + inverse: true + +- type: trait + id: AdrenalDysfunction + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - HighAdrenaline + components: + - type: Adrenaline + rangeModifier: 0.8 + +- type: trait + id: Masochism + category: Physical + points: -3 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - LowPainTolerance + components: + - type: PainTolerance + rangeModifier: 0.4 + inverse: true + +- type: trait + id: LowPainTolerance + category: Physical + points: 1 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - !type:CharacterTraitRequirement + inverted: true + traits: + - Masochism + components: + - type: PainTolerance + rangeModifier: 0.6 + +- type: trait + id: MartialArtist + category: Physical + points: -2 + requirements: + - !type:CharacterJobRequirement + inverted: true + jobs: + - Borg + - MedicalBorg + - Boxer + components: + - type: Boxer + modifiers: + coefficients: + Blunt: 1.5 + Slash: 1.5 + Piercing: 1.5 From 98693301365b2c9770de8cc73fea12b0a76db3b1 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 10 Aug 2024 21:36:39 +0000 Subject: [PATCH 073/135] Automatic Changelog Update (#607) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 20054168fd9..8fe9f12d886 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5204,3 +5204,11 @@ Entries: instead. id: 6249 time: '2024-08-10T21:34:22.0000000+00:00' +- author: VMSolidus and Skubman + changes: + - type: Add + message: >- + 11 new Physical Traits have been added to the game! 6 positive traits, + and 5 negative traits. + id: 6250 + time: '2024-08-10T21:36:09.0000000+00:00' From e4b925b0ea1a1689260de814dadd114ca9c7aeaf Mon Sep 17 00:00:00 2001 From: BlueHNT <79374236+BlueHNT@users.noreply.github.com> Date: Sat, 10 Aug 2024 23:36:48 +0200 Subject: [PATCH 074/135] Adds BeardTag (#608) # Description Adds `BeardTag = "HidesBeard"` for helmets which cover entire head, masks which should hide beards and such. --- # Changelog :cl: - add: Added `HidesBeard` tag --- .../Clothing/EntitySystems/ClothingSystem.cs | 11 ++++++++++- Resources/Prototypes/tags.yml | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs index 087e2ecedab..b407b867f74 100644 --- a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs @@ -28,6 +28,10 @@ public abstract class ClothingSystem : EntitySystem [ValidatePrototypeId] private const string NoseTag = "HidesNose"; + [ValidatePrototypeId] + + private const string BeardTag = "HidesBeard"; + public override void Initialize() { base.Initialize(); @@ -106,7 +110,7 @@ private void ToggleVisualLayer(EntityUid equipee, HumanoidVisualLayers layer, st { if (_tagSystem.HasTag(item, tag)) { - if (tag == NoseTag) //Special check needs to be made for NoseTag, due to masks being toggleable + if (tag == NoseTag || tag == BeardTag) // Special check for NoseTag or BeardTag, due to masks being toggleable { if (TryComp(item, out MaskComponent? mask) && TryComp(item, out ClothingComponent? clothing)) { @@ -139,6 +143,8 @@ protected virtual void OnGotEquipped(EntityUid uid, ClothingComponent component, ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Hair, HairTag); if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, NoseTag)) ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Snout, NoseTag); + if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, BeardTag)) + ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.FacialHair, BeardTag); } protected virtual void OnGotUnequipped(EntityUid uid, ClothingComponent component, GotUnequippedEvent args) @@ -148,6 +154,8 @@ protected virtual void OnGotUnequipped(EntityUid uid, ClothingComponent componen ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Hair, HairTag); if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, NoseTag)) ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Snout, NoseTag); + if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, BeardTag)) + ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.FacialHair, BeardTag); } private void OnGetState(EntityUid uid, ClothingComponent component, ref ComponentGetState args) @@ -166,6 +174,7 @@ private void OnMaskToggled(Entity ent, ref ItemMaskToggledEve //TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix SetEquippedPrefix(ent, args.IsToggled ? args.equippedPrefix : null, ent); ToggleVisualLayer(args.Wearer, HumanoidVisualLayers.Snout, NoseTag); + ToggleVisualLayer(args.Wearer, HumanoidVisualLayers.FacialHair, BeardTag); } private void OnPickedUp(Entity ent, ref GettingPickedUpAttemptEvent args) diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 786f641ddd1..928da630f6f 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -704,6 +704,9 @@ - type: Tag id: HidesNose # for non-standard noses. +- type: Tag + id: HidesBeard # for full coverage helmet / masks where beard shouldn't show + - type: Tag id: HighRiskItem From 9c74822d999ec2e0f7a7cf2d1fc2caae49b5e0f5 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 10 Aug 2024 21:37:36 +0000 Subject: [PATCH 075/135] Automatic Changelog Update (#608) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 8fe9f12d886..4a92df64a45 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5212,3 +5212,9 @@ Entries: and 5 negative traits. id: 6250 time: '2024-08-10T21:36:09.0000000+00:00' +- author: BlueHNT + changes: + - type: Add + message: Added `HidesBeard` tag + id: 6251 + time: '2024-08-10T21:36:49.0000000+00:00' From eb64404e7481afb9bb2292f03ac8f37d2b51a9f9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 10 Aug 2024 19:04:05 -0700 Subject: [PATCH 076/135] Update Credits (#719) --- Resources/Credits/GitHub.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 6e47a71e43f..ba4a72af1fb 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, angelofallars, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, clement-or, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, Hmeister-real, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, ShadowCommander, Shadowtheprotogen546, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, stalengd, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, Tmanzxd, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, angelofallars, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlueHNT, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, clorl, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, Fansana, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, gluesniffler, GNF54, Golinth, GoodWheatley, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, HerCoyote23, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, ShadowCommander, Shadowtheprotogen546, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, SleepyScarecrow, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, stalengd, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, Tmanzxd, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, whateverusername0, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem From 09a8b9153c6a94ecb7ae97fbad61a645eced7ee2 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Sun, 11 Aug 2024 10:08:36 +0800 Subject: [PATCH 077/135] Increase Trait Limit From 5 To 10 (#720) # Description Given the big influx of new traits, a maximum of 5 traits can feel constricting, as often you'll have unspent points but not enough trait slots to buy more traits. This doubles the default trait limit from 5 to 10 to increase player choice and allow more unique trait setups. Since the base trait points have not been increased, players will still need to take negative traits if they want to have more positive traits than before. ## Changelog :cl: Skubman - tweak: The maximum trait limit has increased from 5 traits to 10 traits. --- Content.Shared/CCVar/CCVars.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 3fc7e7247e6..ff2a915b1ba 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -361,7 +361,7 @@ public static readonly CVarDef /// How many traits a character can have at most. /// public static readonly CVarDef GameTraitsMax = - CVarDef.Create("game.traits_max", 5, CVar.REPLICATED); + CVarDef.Create("game.traits_max", 10, CVar.REPLICATED); /// /// How many points a character should start with. From 393116752ca73fba533ef404f0e7c0cafc1d6737 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sun, 11 Aug 2024 02:09:03 +0000 Subject: [PATCH 078/135] Automatic Changelog Update (#720) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 4a92df64a45..c3101c7a468 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5218,3 +5218,9 @@ Entries: message: Added `HidesBeard` tag id: 6251 time: '2024-08-10T21:36:49.0000000+00:00' +- author: Skubman + changes: + - type: Tweak + message: The maximum trait limit has increased from 5 traits to 10 traits. + id: 6252 + time: '2024-08-11T02:08:37.0000000+00:00' From 8b0c7540a50210973fb3a43ad0da71e509232f95 Mon Sep 17 00:00:00 2001 From: Tmanzxd <164098915+Tmanzxd@users.noreply.github.com> Date: Sun, 11 Aug 2024 18:46:46 -0500 Subject: [PATCH 079/135] Make Security Dripped Out Again (#660) Leadup to PR #656. The Loadout fix for #145. Adds and makes a lot of loadout options for Security. Full Change Log Below: **Change Notes:** - Changed Wizden Security Vest sprites to DeltaV Sprites. - Removed Wizden Security Vests from loadouts (can be re-added later in another PR if sentiment changes.) - Added Plate Carriers and Durathread Vests to loadouts - Made non-specialist Security apparel generic to Security. Charge Batong with style now! - Added Flashes to Security Loadouts. - Added Security Armor Vests to Security Loadouts. - Added Detective Coats and Vests to Security Loadouts. - Added Warden Armored Jacket to Warden Loadouts. - Added Head of Security's Trenchcoat to Loadouts. - Added Security gear & accessories to Loadouts. - Added Brigmedic and Corpsman items for Corpsman! - Added SecGlasses to Loadouts! --------- Signed-off-by: Tmanzxd <164098915+Tmanzxd@users.noreply.github.com> Co-authored-by: VMSolidus Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- Resources/Migrations/eeMigrations.yml | 4 + .../Fills/Backpacks/StarterGear/backpack.yml | 22 +- .../Fills/Backpacks/StarterGear/duffelbag.yml | 27 +- .../Fills/Backpacks/StarterGear/satchel.yml | 26 +- .../Clothing/Back/backpacks.yml/backpacks.yml | 15 - .../Clothing/Back/backpacks.yml/duffelbag.yml | 15 - .../Clothing/Back/backpacks.yml/satchel.yml | 15 - .../DeltaV/Roles/Jobs/Security/brigmedic.yml | 6 +- .../Entities/Clothing/OuterClothing/armor.yml | 1 - .../Entities/Clothing/OuterClothing/vests.yml | 9 + .../Clothing/OuterClothing/wintercoats.yml | 5 +- .../Prototypes/Loadouts/Jobs/security.yml | 422 ++++++++++++++---- Resources/Prototypes/Loadouts/items.yml | 14 + 13 files changed, 428 insertions(+), 153 deletions(-) create mode 100644 Resources/Migrations/eeMigrations.yml delete mode 100644 Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml delete mode 100644 Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml delete mode 100644 Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml diff --git a/Resources/Migrations/eeMigrations.yml b/Resources/Migrations/eeMigrations.yml new file mode 100644 index 00000000000..682c3c412bf --- /dev/null +++ b/Resources/Migrations/eeMigrations.yml @@ -0,0 +1,4 @@ +# 2024-03-08 +ClothingBackpackSatchelBrigmedicDeltaVFilled: ClothingBackpackSatchelBrigmedicFilled +ClothingBackpackDuffelBrigmedicDeltaVFilled: ClothingBackpackDuffelBrigmedicFilled +ClothingBackpackBrigmedicDeltaVFilled: ClothingBackpackBrigmedicFilled diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml index 4d33ec98a90..5faab3d7ad2 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml @@ -21,8 +21,23 @@ components: - type: StorageFill contents: - - id: Flash -# - id: MagazinePistol # DeltaV - Security doesn't get an extra mag + - id: MagazinePistol + +- type: entity + noSpawn: true + parent: ClothingBackpackBrigmedic + id: ClothingBackpackBrigmedicFilled + components: + - type: StorageFill + contents: + - id: EmergencyRollerBedSpawnFolded + - id: BodyBagFolded + - id: Portafib + - id: BruteAutoInjector + amount: 2 + - id: BurnAutoInjector + amount: 2 + - id: MagazinePistol - type: entity noSpawn: true @@ -31,10 +46,11 @@ components: - type: StorageFill contents: - - id: Flash - id: ForensicPad - id: ForensicScanner + + - type: entity noSpawn: true parent: ClothingBackpackMedical diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml index 3cac13ab53e..0dfcf774584 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml @@ -14,33 +14,38 @@ - type: entity noSpawn: true - parent: ClothingBackpackDuffelSecurity - id: ClothingBackpackDuffelSecurityFilled + parent: ClothingBackpackDuffelBrigmedic + id: ClothingBackpackDuffelBrigmedicFilled components: - type: StorageFill contents: - - id: Flash -# - id: MagazinePistol # DeltaV - Security doesn't get an extra mag + - id: EmergencyRollerBedSpawnFolded + - id: BodyBagFolded + - id: Portafib + # - id: Flash + - id: BruteAutoInjector + amount: 2 + - id: BurnAutoInjector + amount: 2 - type: entity noSpawn: true parent: ClothingBackpackDuffelSecurity - id: ClothingBackpackDuffelSecurityFilledDetective + id: ClothingBackpackDuffelSecurityFilled components: - type: StorageFill contents: - - id: Flash - - id: ForensicPad - - id: ForensicScanner + - id: MagazinePistol - type: entity noSpawn: true - parent: ClothingBackpackDuffelBrigmedic - id: ClothingBackpackDuffelBrigmedicFilled + parent: ClothingBackpackDuffelSecurity + id: ClothingBackpackDuffelSecurityFilledDetective components: - type: StorageFill contents: - - id: Flash + - id: ForensicPad + - id: ForensicScanner - type: entity noSpawn: true diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml index 89ae8fdf477..f74207ca18e 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml @@ -28,33 +28,37 @@ - type: entity noSpawn: true - parent: ClothingBackpackSatchelSecurity - id: ClothingBackpackSatchelSecurityFilled + parent: ClothingBackpackSatchelBrigmedic + id: ClothingBackpackSatchelBrigmedicFilled components: - type: StorageFill contents: - - id: Flash -# - id: MagazinePistol # DeltaV - Security doesn't get an extra mag + - id: EmergencyRollerBedSpawnFolded + - id: BodyBagFolded + - id: Portafib + - id: BruteAutoInjector + amount: 2 + - id: BurnAutoInjector + amount: 2 - type: entity noSpawn: true parent: ClothingBackpackSatchelSecurity - id: ClothingBackpackSatchelSecurityFilledDetective + id: ClothingBackpackSatchelSecurityFilled components: - type: StorageFill contents: - - id: Flash - - id: ForensicPad - - id: ForensicScanner + - id: MagazinePistol - type: entity noSpawn: true - parent: ClothingBackpackSatchelBrigmedic - id: ClothingBackpackSatchelBrigmedicFilled + parent: ClothingBackpackSatchelSecurity + id: ClothingBackpackSatchelSecurityFilledDetective components: - type: StorageFill contents: - - id: Flash + - id: ForensicPad + - id: ForensicScanner - type: entity noSpawn: true diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml deleted file mode 100644 index 2fbc17d2585..00000000000 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/backpacks.yml +++ /dev/null @@ -1,15 +0,0 @@ -- type: entity - noSpawn: true - parent: ClothingBackpackBrigmedic - id: ClothingBackpackBrigmedicDeltaVFilled - components: - - type: StorageFill - contents: - - id: EmergencyRollerBedSpawnFolded - - id: BodyBagFolded - - id: Portafib - # - id: Flash - - id: BruteAutoInjector - amount: 2 - - id: BurnAutoInjector - amount: 2 diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml deleted file mode 100644 index bcd12b5e1b1..00000000000 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/duffelbag.yml +++ /dev/null @@ -1,15 +0,0 @@ -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelBrigmedic - id: ClothingBackpackDuffelBrigmedicDeltaVFilled - components: - - type: StorageFill - contents: - - id: EmergencyRollerBedSpawnFolded - - id: BodyBagFolded - - id: Portafib - # - id: Flash - - id: BruteAutoInjector - amount: 2 - - id: BurnAutoInjector - amount: 2 diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml deleted file mode 100644 index 31dc027a21e..00000000000 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Back/backpacks.yml/satchel.yml +++ /dev/null @@ -1,15 +0,0 @@ -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelBrigmedic - id: ClothingBackpackSatchelBrigmedicDeltaVFilled - components: - - type: StorageFill - contents: - - id: EmergencyRollerBedSpawnFolded - - id: BodyBagFolded - - id: Portafib - # - id: Flash - - id: BruteAutoInjector - amount: 2 - - id: BurnAutoInjector - amount: 2 diff --git a/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml b/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml index f4b2fe95e14..681cb95be71 100644 --- a/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml +++ b/Resources/Prototypes/DeltaV/Roles/Jobs/Security/brigmedic.yml @@ -35,7 +35,7 @@ equipment: jumpsuit: ClothingUniformJumpsuitBrigmedic outerClothing: ClothingOuterArmorPlateCarrier - back: ClothingBackpackBrigmedicDeltaVFilled + back: ClothingBackpackBrigmedicFilled shoes: ClothingShoesBootsCombatFilled gloves: ClothingHandsGlovesNitrile eyes: ClothingEyesHudMedical @@ -45,5 +45,5 @@ belt: ClothingBeltCorpsmanWebbingFilled pocket1: WeaponPistolMk58Nonlethal innerClothingSkirt: ClothingUniformJumpskirtBrigmedic - satchel: ClothingBackpackSatchelBrigmedicDeltaVFilled - duffelbag: ClothingBackpackDuffelBrigmedicDeltaVFilled + satchel: ClothingBackpackSatchelBrigmedicFilled + duffelbag: ClothingBackpackDuffelBrigmedicFilled diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index b62658270eb..eb580d64996 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -1,7 +1,6 @@ # Numbers for armor here largely taken from /tg/. # NOTE: Half of the kind of armor you're probably thinking of is in vests.yml. These should probably be merged some day. -#Basic armor vest - type: entity parent: ClothingOuterBaseMedium id: ClothingOuterArmorBasic diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml index b867abfeed3..784084652c1 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml @@ -51,6 +51,15 @@ sprite: Clothing/OuterClothing/Vests/detvest.rsi - type: Clothing sprite: Clothing/OuterClothing/Vests/detvest.rsi + - type: Armor #Based on /tg/ but slightly compensated to fit the fact that armor stacks in SS14. + modifiers: + coefficients: + Blunt: 0.70 + Slash: 0.70 + Piercing: 0.70 #Can save you, but bullets will still hurt. Will take about 10 shots from a Viper before critting, as opposed to 7 while unarmored and 16~ with a bulletproof vest. + Heat: 0.80 + - type: ExplosionResistance + damageCoefficient: 0.90 #Hazard vest - type: entity diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/wintercoats.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/wintercoats.yml index aa4a7b50e65..160c606cc41 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/wintercoats.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/wintercoats.yml @@ -248,6 +248,7 @@ Slash: 0.75 Piercing: 0.75 Heat: 0.75 + Caustic: 0.75 #not the full 90% from ss13 because of the head - type: entity parent: ClothingOuterWinterCoatToggleable @@ -417,12 +418,12 @@ sprite: Clothing/OuterClothing/WinterCoats/coatsec.rsi - type: ToggleableClothing clothingPrototype: ClothingHeadHatHoodWinterSec - - type: Armor # DeltaV - adds resists to coat + - type: Armor modifiers: coefficients: Blunt: 0.85 Slash: 0.85 - Piercing: 0.85 # DeltaV - not as resistant as pre-rebase, but still better than nothing + Piercing: 0.85 #Can save you, but bullets will still hurt. Will take about 10 shots from a Viper before critting, as opposed to 7 while unarmored and 16~ with a bulletproof vest. Heat: 0.75 - type: entity diff --git a/Resources/Prototypes/Loadouts/Jobs/security.yml b/Resources/Prototypes/Loadouts/Jobs/security.yml index f1c64730378..527c9391c0a 100644 --- a/Resources/Prototypes/Loadouts/Jobs/security.yml +++ b/Resources/Prototypes/Loadouts/Jobs/security.yml @@ -9,11 +9,9 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - SecurityOfficer - - SecurityCadet - - Warden + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingUniformJumpsuitSecBlue @@ -27,11 +25,9 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - SecurityOfficer - - SecurityCadet - - Warden + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingUniformJumpsuitSecGrey @@ -41,11 +37,9 @@ cost: 1 exclusive: true requirements: - - !type:CharacterJobRequirement - jobs: - - SecurityOfficer - - SecurityCadet - - Warden + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingUniformJumpskirtSecGrey @@ -55,11 +49,9 @@ cost: 1 exclusive: true requirements: - - !type:CharacterJobRequirement - jobs: - - SecurityOfficer - - SecurityCadet - - Warden + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingUniformJumpskirtSecBlue @@ -198,19 +190,16 @@ - type: loadout id: LoadoutUniformJumpsuitSecFormal category: Jobs - cost: 2 + cost: 1 exclusive: true requirements: - !type:CharacterSpeciesRequirement inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Detective - - SecurityOfficer - - Warden - - HeadOfSecurity + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingUniformJumpsuitSecFormal @@ -224,14 +213,12 @@ inverted: true species: - Harpy - - !type:CharacterJobRequirement - jobs: - - Detective - - SecurityOfficer - - Warden - - HeadOfSecurity + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingUniformJumpsuitSecSummer + # Mask - type: loadout id: LoadoutSecurityMaskGasSwat @@ -257,92 +244,176 @@ species: - Diona - Harpy - - !type:CharacterJobRequirement - jobs: - - Detective - - SecurityOfficer - - SecurityCadet - - Warden - - HeadOfSecurity + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingShoesBootsJack +- type: loadout + id: LoadoutClothingShoesBootsCombat + category: Jobs + cost: 1 + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Diona + - Harpy + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingShoesBootsCombat + # Eyes - type: loadout id: LoadoutSecurityEyesHudSecurity category: Jobs - cost: 2 + cost: 1 exclusive: true requirements: - - !type:CharacterJobRequirement - jobs: - - SecurityOfficer - - Warden - - HeadOfSecurity - - Brigmedic + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingEyesHudSecurity +- type: loadout + id: ClothingEyesGlassesSunglasses + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingEyesGlassesSunglasses + - type: loadout id: LoadoutSecurityEyesEyepatchHudSecurity category: Jobs - cost: 2 + cost: 1 exclusive: true requirements: - - !type:CharacterJobRequirement - jobs: - - SecurityOfficer - - Warden - - HeadOfSecurity - - Brigmedic + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingEyesEyepatchHudSecurity - type: loadout id: LoadoutSecurityEyesHudSecurityPrescription category: Jobs - cost: 2 + cost: 1 exclusive: true requirements: - - !type:CharacterJobRequirement - jobs: - - SecurityOfficer - - Warden - - HeadOfSecurity - - Brigmedic + - !type:CharacterDepartmentRequirement + departments: + - Security - !type:CharacterTraitRequirement traits: - Nearsighted items: - ClothingEyesPrescriptionHudSecurity +- type: loadout + id: LoadoutClothingEyesGlassesSecurity + category: Jobs + cost: 4 + exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingEyesGlassesSecurity + +#Backpack +#Will need to add a backpack category later on, that will be part of an starting inventory loadout refactor. + # Head - type: loadout id: LoadoutSecurityHeadHatBeret category: Jobs cost: 1 exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingHeadHatBeretSecurity + +- type: loadout + id: LoadoutClothingHeadHelmetBasic + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingHeadHelmetBasic + +- type: loadout + id: LoadoutClothingHeadHatBeretBrigmedic + category: Jobs + cost: 1 + exclusive: true requirements: - !type:CharacterJobRequirement jobs: - - SecurityOfficer - - Warden - - HeadOfSecurity - Brigmedic items: - - ClothingHeadHatBeretSecurity + - ClothingHeadHatBeretBrigmedic - type: loadout - id: LoadoutSecurityHeadHelmetInsulated + id: LoadoutClothingHeadHatBeretCorpsman category: Jobs - cost: 3 + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Brigmedic + items: + - ClothingHeadHatBeretCorpsman + +- type: loadout + id: LoadoutClothingHeadHatBeretWarden + category: Jobs + cost: 1 + exclusive: true requirements: - !type:CharacterJobRequirement jobs: - - SecurityOfficer - Warden + items: + - ClothingHeadHatBeretWarden + +- type: loadout + id: LoadoutClothingHeadHatBeretHoS + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: - HeadOfSecurity - - Brigmedic + items: + - ClothingHeadHatBeretHoS + +- type: loadout + id: LoadoutSecurityHeadHelmetInsulated + category: Jobs + cost: 2 + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security items: - ClothingHeadHelmetInsulated @@ -352,33 +423,230 @@ category: Jobs cost: 1 exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingBeltSecurityWebbingFilled + +- type: loadout + id: LoadoutClothingBeltCorpsmanWebbing + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Brigmedic + items: + - ClothingBeltCorpsmanWebbingFilled + +- type: loadout + id: LoadoutClothingBeltSecurity + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingBeltSecurity + +#Gloves + +- type: loadout + id: LoadoutClothingHandsGlovesNitrile + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Brigmedic + items: + - ClothingHandsGlovesNitrile + +- type: loadout + id: LoadoutClothingOuterArmorPlateCarrier + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingOuterArmorPlateCarrier + +- type: loadout + id: LoadoutClothingOuterArmorDuraVest + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - ClothingOuterArmorDuraVest + +- type: loadout + id: LoadoutClothingOuterCoatDetective + category: Jobs + cost: 2 + exclusive: true requirements: - !type:CharacterJobRequirement jobs: - Detective - - SecurityOfficer - - SecurityCadet + items: + - ClothingOuterCoatDetective + +- type: loadout + id: LoadoutOuterVestDetective + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Detective + items: + - ClothingOuterVestDetective + +- type: loadout + id: LoadoutClothingOuterCoatWarden + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: - Warden + items: + - ClothingOuterCoatWarden + +- type: loadout + id: LoadoutClothingOuterCoatHoSTrench + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: - HeadOfSecurity items: - - ClothingBeltSecurityWebbingFilled + - ClothingOuterCoatHoSTrench +- type: loadout + id: LoadoutClothingOuterWinterHoS + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - HeadOfSecurity + items: + - ClothingOuterWinterHoS + +# Neck +- type: loadout + id: LoadoutClothingNeckCloakHos + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - HeadOfSecurity + items: + - ClothingNeckCloakHos + +- type: loadout + id: LoadoutClothingNeckMantleHOS + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - HeadOfSecurity + items: + - ClothingNeckMantleHOS + +- type: loadout + id: LoadoutBedsheetBrigmedic + category: Jobs + cost: 1 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Brigmedic + items: + - BedsheetBrigmedic + + # Equipment - type: loadout id: LoadoutSecurityCombatKnife category: Jobs - cost: 1 + cost: 2 requirements: - - !type:CharacterSpeciesRequirement - species: - - Diona - - Harpy - !type:CharacterDepartmentRequirement departments: - Security items: - CombatKnife +- type: loadout + id: LoadoutSecurityFlash + category: Jobs + cost: 1 + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - Flash + +- type: loadout + id: LoadoutSecurityDisabler + category: Jobs + cost: 2 + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - WeaponDisabler + +- type: loadout + id: LoadoutMagazinePistolRubber + category: Jobs + cost: 2 + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + items: + - MagazinePistolRubber + +- type: loadout + id: LoadoutSpeedLoaderMagnumRubber + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Detective + items: + - SpeedLoaderMagnumRubber + # TODO: Make this replace the secoff handgun and make it cheaper # # Species # - type: loadout diff --git a/Resources/Prototypes/Loadouts/items.yml b/Resources/Prototypes/Loadouts/items.yml index e09d02c463a..c7d540d676e 100644 --- a/Resources/Prototypes/Loadouts/items.yml +++ b/Resources/Prototypes/Loadouts/items.yml @@ -469,6 +469,20 @@ - Brigmedic #Misc Items +- type: loadout + id: LoadoutItemFlash + category: Items + cost: 1 + items: + - Flash + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + - !type:CharacterJobRequirement + jobs: + - Brigmedic + - type: loadout id: LoadoutItemPAI category: Items From 84c338a554ee32e0e6a912b0b4f753b7697ab986 Mon Sep 17 00:00:00 2001 From: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Date: Mon, 12 Aug 2024 03:22:27 +0100 Subject: [PATCH 080/135] Ports 78 From Floofstation - Fix Crew Monitor (#717) # Description Crew Monitor right now only shows Good! or Bad! (dead). Should show more states, this fixes it. # Changelog :cl: Xavier - fix: Crew monitor not working properly, now displays correctly. --- Content.Shared/Medical/SuitSensor/SharedSuitSensor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Medical/SuitSensor/SharedSuitSensor.cs b/Content.Shared/Medical/SuitSensor/SharedSuitSensor.cs index e3ca466b085..27539dd22bd 100644 --- a/Content.Shared/Medical/SuitSensor/SharedSuitSensor.cs +++ b/Content.Shared/Medical/SuitSensor/SharedSuitSensor.cs @@ -24,7 +24,7 @@ public SuitSensorStatus(NetEntity suitSensorUid, string name, string job, string public bool IsAlive; public int? TotalDamage; public int? TotalDamageThreshold; - public float? DamagePercentage => TotalDamageThreshold == null || TotalDamage == null ? null : TotalDamage / TotalDamageThreshold; + public float? DamagePercentage => TotalDamageThreshold == null || TotalDamage == null ? null : TotalDamage / (float) TotalDamageThreshold; public NetCoordinates? Coordinates; } From 572123e20de6882e4886ae0a1e2950c349e5fea1 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Mon, 12 Aug 2024 02:22:52 +0000 Subject: [PATCH 081/135] Automatic Changelog Update (#717) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index c3101c7a468..8358513a784 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5224,3 +5224,9 @@ Entries: message: The maximum trait limit has increased from 5 traits to 10 traits. id: 6252 time: '2024-08-11T02:08:37.0000000+00:00' +- author: Xavier + changes: + - type: Fix + message: Crew monitor not working properly, now displays correctly. + id: 6253 + time: '2024-08-12T02:22:27.0000000+00:00' From feb552982002f381eac363214af19835b0612b2a Mon Sep 17 00:00:00 2001 From: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Date: Mon, 12 Aug 2024 03:22:58 +0100 Subject: [PATCH 082/135] Various Floofstation Ports. (#716) # Description Various minor yaml and QOL ports from Floofstation. Changelog entries go in order of author. I'm considering just copying over the changelog at some point. # Changelog :cl: AeraAuling, ShatteredSwords and Cynical24 - add: Added the Explorer's Labcoat and a Hairflower into Loadouts. - fix: Fixed Epistemics being unable to take Survival Boxes - fix: Fixed the NearSighted trait making you unable to take glasses in your loadout - add: Added a variety of Cowboy Hats into loadouts. --- .../Entities/Clothing/Eyes/glasses.yml | 33 +++++++++++ .../Prototypes/Loadouts/Jobs/science.yml | 14 +++++ Resources/Prototypes/Loadouts/eyes.yml | 5 -- Resources/Prototypes/Loadouts/head.yml | 56 +++++++++++++++++++ Resources/Prototypes/Loadouts/items.yml | 1 - 5 files changed, 103 insertions(+), 6 deletions(-) diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml index 9af8edb0028..0f6c4acfcb5 100644 --- a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml +++ b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml @@ -234,3 +234,36 @@ - type: Clothing sprite: Clothing/Eyes/Glasses/ninjavisor.rsi - type: FlashImmunity + +- type: entity #Fake goggles, the latest in anti-valid hunting technology + parent: ClothingEyesBase + id: ClothingEyesGlassesThermalBudget + name: red goggles + description: These don't have any real function, but they do look cool! + components: + - type: Sprite + sprite: Clothing/Eyes/Glasses/thermal.rsi + - type: Clothing + sprite: Clothing/Eyes/Glasses/thermal.rsi + +- type: entity + parent: ClothingEyesBase + id: ClothingEyesGlassesChemicalBudget + name: purple goggles + description: These don't have any real function, but they do look cool! + components: + - type: Sprite + sprite: Clothing/Eyes/Glasses/science.rsi + - type: Clothing + sprite: Clothing/Eyes/Glasses/science.rsi + +- type: entity + parent: ClothingEyesBase + id: ClothingEyesGlassesMesonBudget + name: green goggles + description: These don't have any real function, but they do look cool! + components: + - type: Sprite + sprite: Clothing/Eyes/Glasses/meson.rsi + - type: Clothing + sprite: Clothing/Eyes/Glasses/meson.rsi diff --git a/Resources/Prototypes/Loadouts/Jobs/science.yml b/Resources/Prototypes/Loadouts/Jobs/science.yml index fb382a8c2ca..04b226e2ba2 100644 --- a/Resources/Prototypes/Loadouts/Jobs/science.yml +++ b/Resources/Prototypes/Loadouts/Jobs/science.yml @@ -75,6 +75,20 @@ items: - ClothingOuterCoatLabSeniorResearcher +- type: loadout + id: LoadoutScienceOuterExplorerLabcoat + category: Jobs + cost: 2 + exclusive: true + requirements: + - !type:CharacterJobRequirement + jobs: + - Scientist + - ResearchAssistant + - ResearchDirector + items: + - ClothingOuterExplorerCoat + - type: loadout id: LoadoutScienceHatBeret category: Jobs diff --git a/Resources/Prototypes/Loadouts/eyes.yml b/Resources/Prototypes/Loadouts/eyes.yml index fed07c6bd6f..02d411be078 100644 --- a/Resources/Prototypes/Loadouts/eyes.yml +++ b/Resources/Prototypes/Loadouts/eyes.yml @@ -9,11 +9,6 @@ id: LoadoutEyesGlasses category: Eyes cost: 1 - requirements: - - !type:CharacterTraitRequirement - inverted: true - traits: - - Nearsighted items: - ClothingEyesGlasses diff --git a/Resources/Prototypes/Loadouts/head.yml b/Resources/Prototypes/Loadouts/head.yml index e76e2f17ecd..1b47e307b7d 100644 --- a/Resources/Prototypes/Loadouts/head.yml +++ b/Resources/Prototypes/Loadouts/head.yml @@ -91,6 +91,54 @@ departments: - Security +- type: loadout + id: LoadoutHeadHatCowboyBrown + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyBrown + +- type: loadout + id: LoadoutHeadHatCowboyBlack + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyBlack + +- type: loadout + id: LoadoutHeadHatCowboyGrey + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyGrey + +- type: loadout + id: LoadoutHeadHatCowboyRed + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyRed + +- type: loadout + id: LoadoutHeadHatCowboyWhite + category: Head + cost: 2 + exclusive: true + items: + - ClothingHeadHatCowboyWhite + +- type: loadout + id: LoadoutHeadHatCowboyBountyHunter + category: Head + cost: 3 + exclusive: true + items: + - ClothingHeadHatCowboyBountyHunter + - type: loadout id: LoadoutHeadTinfoil category: Head @@ -107,6 +155,14 @@ items: - ClothingHeadHatBellhop +- type: loadout + id: LoadoutHeadPoppy + category: Head + cost: 1 + exclusive: true + items: + - FoodPoppy + # Color Hats - type: loadout id: LoadoutHeadHatBluesoft diff --git a/Resources/Prototypes/Loadouts/items.yml b/Resources/Prototypes/Loadouts/items.yml index c7d540d676e..87ba2e71d42 100644 --- a/Resources/Prototypes/Loadouts/items.yml +++ b/Resources/Prototypes/Loadouts/items.yml @@ -293,7 +293,6 @@ - Security - Medical - Engineering - - Epistemics - !type:CharacterJobRequirement inverted: true jobs: From a425aeb9226fafaaf8a4f5d76b4b3e7d08ed4b12 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Mon, 12 Aug 2024 02:23:26 +0000 Subject: [PATCH 083/135] Automatic Changelog Update (#716) --- Resources/Changelog/Changelog.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 8358513a784..fe9c55442ed 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5230,3 +5230,17 @@ Entries: message: Crew monitor not working properly, now displays correctly. id: 6253 time: '2024-08-12T02:22:27.0000000+00:00' +- author: DangerRevolution + changes: + - type: Add + message: Added the Explorer's Labcoat and a Hairflower into Loadouts. + - type: Fix + message: Fixed Epistemics being unable to take Survival Boxes + - type: Fix + message: >- + Fixed the NearSighted trait making you unable to take glasses in your + loadout + - type: Add + message: Added a variety of Cowboy Hats into loadouts. + id: 6254 + time: '2024-08-12T02:22:58.0000000+00:00' From e0f18e8a9d1117f2b25ee9e1b067c735a990086b Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Tue, 13 Aug 2024 00:43:10 +0800 Subject: [PATCH 084/135] Add Home Run Bat (Traitor Item) (#722) # Description Adds the home run bat as a new item for traitors, a new traitor weapon that knocks targets back significantly. The home run bat has the same Nyanocombat stats as the baseball bat, with differences: damage has been reduced by around 25%, same as the baseball bat, and the Stamina damage on power attacks is 25. Originally made for Delta-V (https://github.com/DeltaV-Station/Delta-v/pull/1476) ## Media
![image](https://github.com/user-attachments/assets/3502145f-cae2-4ce0-9ae2-a0f2eeb48c8b) ![image](https://github.com/user-attachments/assets/f508a367-d2bb-4283-bd47-de4b4b272637)
## Changelog :cl: musicmanvr - add: Added the Home Run Bat for Syndicate operatives. Send your foes flying! --------- Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> --- .../Locale/en-US/store/uplink-catalog.ftl | 3 ++ .../Prototypes/Catalog/uplink_catalog.yml | 12 +++++++ .../Objects/Weapons/Melee/home_run_bat.yml | 34 ++++++++++++++++++ .../home_run_bat.rsi/equipped-BACKPACK.png | Bin 0 -> 6578 bytes .../Weapons/Melee/home_run_bat.rsi/icon.png | Bin 0 -> 832 bytes .../Melee/home_run_bat.rsi/inhand-left.png | Bin 0 -> 6023 bytes .../Melee/home_run_bat.rsi/inhand-right.png | Bin 0 -> 6020 bytes .../Weapons/Melee/home_run_bat.rsi/meta.json | 34 ++++++++++++++++++ .../home_run_bat.rsi/wielded-inhand-left.png | Bin 0 -> 6115 bytes .../home_run_bat.rsi/wielded-inhand-right.png | Bin 0 -> 6059 bytes 10 files changed, 83 insertions(+) create mode 100644 Resources/Prototypes/Entities/Objects/Weapons/Melee/home_run_bat.yml create mode 100644 Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/icon.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/meta.json create mode 100644 Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/wielded-inhand-left.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/wielded-inhand-right.png diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index 592cf59d2fe..67d221d9b61 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -421,3 +421,6 @@ uplink-barber-scissors-desc = A good tool to give your fellow agent a nice hairc uplink-backpack-syndicate-name = Syndicate backpack uplink-backpack-syndicate-desc = Lightweight explosion-proof а backpack for holding various traitor goods + +uplink-home-run-bat-name = Home Run Bat +uplink-home-run-bat-desc = Rigged bat pre-coated in blood for Syndicate tee-ball practice. Launch your foes! diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 1f30c2cb7d2..a1a60e3fef0 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -101,6 +101,18 @@ tags: - NukeOpsUplink +- type: listing + id: BaseBallBatHomeRun + name: uplink-home-run-bat-name + description: uplink-home-run-bat-desc + productEntity: BaseBallBatHomeRun + icon: + entity: BaseBallBatHomeRun + cost: + Telecrystal: 16 + categories: + - UplinkWeapons + # Explosives - type: listing diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/home_run_bat.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/home_run_bat.yml new file mode 100644 index 00000000000..5cb5795c8a5 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/home_run_bat.yml @@ -0,0 +1,34 @@ +- type: entity + parent: BaseBallBat + id: BaseBallBatHomeRun + name: home run bat + description: Heavy metal bat with an extra kick. + components: + - type: Sprite + sprite: Objects/Weapons/Melee/home_run_bat.rsi + state: icon + - type: MeleeWeapon + damage: + types: + Blunt: 11 + bluntStaminaDamageFactor: 2.0 + heavyRateModifier: 0.5 + heavyDamageBaseModifier: 1.75 + heavyStaminaCost: 25 + maxTargets: 2 + angle: 120 + soundHit: + collection: ExplosionSmall + - type: MeleeRequiresWield # You can't hit a home run with one hand, jimbo. + - type: MeleeThrowOnHit + speed: 30 + lifetime: 5 + - type: Item + size: Large + - type: Tool + speed: 0.5 # it's very heavy, it rolls slower than a wooden bat + - type: UseDelay + delay: 2 + - type: PhysicalComposition + materialComposition: + Steel: 350 # it's not made of wood diff --git a/Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/equipped-BACKPACK.png b/Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/equipped-BACKPACK.png new file mode 100644 index 0000000000000000000000000000000000000000..0f42b7f14722c161fe8a70dcf80b0b80978d0eb6 GIT binary patch literal 6578 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 KHY+soJpO+t%!wHQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/icon.png b/Resources/Textures/Objects/Weapons/Melee/home_run_bat.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..33eec9258c605efe223d8b839537c73a7916fa37 GIT binary patch literal 832 zcmV-G1Hb%EX>4Tx04R}tkv&MmP!xqvQ>7vm2MdaH$WWc^q9Tr^6^me@v=v%)FnQ@8G-*gu zTpR`0f`dPcRRd-%s4f0|q}xvF5~ zSU?>rB*zc_2ft@)mS(2iq+lHAf3fY42_Ucww41j5eQew96TtrrTxnf@y#>sFlHTlU zkt1Mu8@RacYVsa%xdV(n>5?HilAlT_m4Np%`lbRfatjQuxpV8BeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{009_DL_t(o!|m3+4uUWg1>l3Suq!Js;KV}GSKz%#x-i*U z5(g8ehB{z0;9^Z7g;;6Jpm$~O#?Nl;Z4 z0Q9;Lp({Mka{$1JQV1a?$A+$ON-6e1fU6LAa1KO~cKpT_o@E(sU55wfxJ1!p4{TlG zM@q2)aK7Isaciq!jK7)=jImkVN&vOt02txcd%zT5JOlFUC2Wc>3NXeQW3xM+)c`u& z6#hDZP24zuZQLk;3*2}a+QvVgfiz9~IF8XY%~zeiD1gN4x<*-+)-N!@n)qx0ANXVd zU${1aPkazSy}`C^>ji)B19Fp*=ejR^a4A)f)K!WQ(yPDWXX**~%GuHPbiSnk0000< KMNUMnLSTY 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 Bc0d3C literal 0 HcmV?d00001 From f57327eacb1efeeeac17012d889df619d49dcc8c Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Mon, 12 Aug 2024 16:43:37 +0000 Subject: [PATCH 085/135] Automatic Changelog Update (#722) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index fe9c55442ed..c13b19a328f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5244,3 +5244,9 @@ Entries: message: Added a variety of Cowboy Hats into loadouts. id: 6254 time: '2024-08-12T02:22:58.0000000+00:00' +- author: musicmanvr + changes: + - type: Add + message: Added the Home Run Bat for Syndicate operatives. Send your foes flying! + id: 6255 + time: '2024-08-12T16:43:11.0000000+00:00' From 376b8f1048a3532876541cc9333c6f9f44dcb21d Mon Sep 17 00:00:00 2001 From: SleepyScarecrow <136123749+SleepyScarecrow@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:46:04 -0400 Subject: [PATCH 086/135] Added Showers (#661) # Description Added in showers. A pure RP furniture item. --- # TODO - [x] Sound effects - [x] Wallmount - [x] Add in Showers --- ![Display](https://github.com/user-attachments/assets/c8499c33-a9ce-4d2d-9003-ed8517afb0b9) --- # Changelog :cl: Tilkku - add: Added showers --- Content.Server/Shower/ShowerSystem.cs | 8 ++ Content.Shared/Showers/SharedShowerSystem.cs | 92 ++++++++++++++++++ Content.Shared/Showers/ShowerComponent.cs | 43 ++++++++ .../Audio/Ambience/Objects/shower_enable.ogg | Bin 0 -> 6313 bytes .../Audio/Ambience/Objects/shower_running.ogg | Bin 0 -> 32475 bytes .../Locale/en-US/shower/shower-component.ftl | 2 + .../Entities/Structures/Furniture/shower.yml | 46 +++++++++ .../Construction/Graphs/furniture/shower.yml | 29 ++++++ .../Recipes/Construction/furniture.yml | 32 ++++-- .../Structures/Furniture/shower.rsi/meta.json | 25 +++++ .../Furniture/shower.rsi/shower.png | Bin 0 -> 540 bytes .../Furniture/shower.rsi/shower_on.png | Bin 0 -> 8123 bytes 12 files changed, 270 insertions(+), 7 deletions(-) create mode 100644 Content.Server/Shower/ShowerSystem.cs create mode 100644 Content.Shared/Showers/SharedShowerSystem.cs create mode 100644 Content.Shared/Showers/ShowerComponent.cs create mode 100644 Resources/Audio/Ambience/Objects/shower_enable.ogg create mode 100644 Resources/Audio/Ambience/Objects/shower_running.ogg create mode 100644 Resources/Locale/en-US/shower/shower-component.ftl create mode 100644 Resources/Prototypes/Entities/Structures/Furniture/shower.yml create mode 100644 Resources/Prototypes/Recipes/Construction/Graphs/furniture/shower.yml create mode 100644 Resources/Textures/Structures/Furniture/shower.rsi/meta.json create mode 100644 Resources/Textures/Structures/Furniture/shower.rsi/shower.png create mode 100644 Resources/Textures/Structures/Furniture/shower.rsi/shower_on.png diff --git a/Content.Server/Shower/ShowerSystem.cs b/Content.Server/Shower/ShowerSystem.cs new file mode 100644 index 00000000000..44034d5fa98 --- /dev/null +++ b/Content.Server/Shower/ShowerSystem.cs @@ -0,0 +1,8 @@ +using Content.Shared.Showers; + +namespace Content.Server.Shower; + +public sealed class ShowerSystem : SharedShowerSystem +{ + +} diff --git a/Content.Shared/Showers/SharedShowerSystem.cs b/Content.Shared/Showers/SharedShowerSystem.cs new file mode 100644 index 00000000000..be3af6228f2 --- /dev/null +++ b/Content.Shared/Showers/SharedShowerSystem.cs @@ -0,0 +1,92 @@ +using Content.Shared.Interaction; +using Content.Shared.Verbs; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Random; +using Robust.Shared.Utility; + +namespace Content.Shared.Showers +{ + public abstract class SharedShowerSystem : EntitySystem + { + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent>(OnToggleShowerVerb); + SubscribeLocalEvent(OnActivateInWorld); + } + private void OnMapInit(EntityUid uid, ShowerComponent component, MapInitEvent args) + { + if (_random.Prob(0.5f)) + component.ToggleShower = true; + UpdateAppearance(uid); + } + private void OnToggleShowerVerb(EntityUid uid, ShowerComponent component, GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess || args.Hands == null) + return; + + AlternativeVerb toggleVerb = new() + { + Act = () => ToggleShowerHead(uid, args.User, component) + }; + + if (component.ToggleShower) + { + toggleVerb.Text = Loc.GetString("shower-turn-on"); + toggleVerb.Icon = + new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/open.svg.192dpi.png")); + } + else + { + toggleVerb.Text = Loc.GetString("shower-turn-off"); + toggleVerb.Icon = + new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/close.svg.192dpi.png")); + } + args.Verbs.Add(toggleVerb); + } + private void OnActivateInWorld(EntityUid uid, ShowerComponent comp, ActivateInWorldEvent args) + { + if (args.Handled) + return; + + args.Handled = true; + ToggleShowerHead(uid, args.User, comp); + + _audio.PlayPvs(comp.EnableShowerSound, uid); + } + public void ToggleShowerHead(EntityUid uid, EntityUid? user = null, ShowerComponent? component = null, MetaDataComponent? meta = null) + { + if (!Resolve(uid, ref component)) + return; + + component.ToggleShower = !component.ToggleShower; + + UpdateAppearance(uid, component); + } + private void UpdateAppearance(EntityUid uid, ShowerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + _appearance.SetData(uid, ShowerVisuals.ShowerVisualState, component.ToggleShower ? ShowerVisualState.On : ShowerVisualState.Off); + + if (component.ToggleShower) + { + if (component.PlayingStream == null) + { + component.PlayingStream = _audio.PlayPvs(component.LoopingSound, uid, AudioParams.Default.WithLoop(true).WithMaxDistance(5)).Value.Entity; + } + } + else + { + component.PlayingStream = _audio.Stop(component.PlayingStream); + component.PlayingStream = null; + } + } + } +} \ No newline at end of file diff --git a/Content.Shared/Showers/ShowerComponent.cs b/Content.Shared/Showers/ShowerComponent.cs new file mode 100644 index 00000000000..339205546bd --- /dev/null +++ b/Content.Shared/Showers/ShowerComponent.cs @@ -0,0 +1,43 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Showers +{ + /// + /// showers that can be enabled + /// + [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] + public sealed partial class ShowerComponent : Component + { + /// + /// Toggles shower. + /// + [DataField, AutoNetworkedField] + public bool ToggleShower; + + [DataField("enableShowerSound")] + public SoundSpecifier EnableShowerSound = new SoundPathSpecifier("/Audio/Ambience/Objects/shower_enable.ogg"); + + public EntityUid? PlayingStream; + + [DataField("loopingSound")] + public SoundSpecifier LoopingSound = new SoundPathSpecifier("/Audio/Ambience/Objects/shower_running.ogg"); + + } + + + [Serializable, NetSerializable] + public enum ShowerVisuals : byte + { + ShowerVisualState, + } + + [Serializable, NetSerializable] + public enum ShowerVisualState : byte + { + Off, + On + } +} + diff --git a/Resources/Audio/Ambience/Objects/shower_enable.ogg b/Resources/Audio/Ambience/Objects/shower_enable.ogg new file mode 100644 index 0000000000000000000000000000000000000000..98f41fbffb1f09fc9f89803ad557e6977ab6cc3d GIT binary patch literal 6313 zcmb_gc|6qH`#&?(456{aSaOF9#+DIfNtk4r5F^_pX@)eG3eln%nMzD$8A78hGo+eI zHA-F4Vk{v^lOioD>Z-KSa;xw8jN85U`}^bf`u*|yygtTr&hwn-oag;4=b2d%6B7u~ z;IC(<;xsXY--Ac#qf$2}F<8mS6sl$QG{^t?^#3~43S{Nq53&*kN7q`%md$qm`S0hk z+_WBB$PQ&~T5q)?DTWZwVg$>y6TAsF);8AGi>z%4rnKm&6eep!3}M-ZR94c)4GGa3 zHj|J&P&1}=7*Uo6qkt;_cnZ#JhKPBnPD6wn9Gd&xl zawr{{y?H?ZSs>60@lW!$9OWlh<3qX<#|V&mPKfDBR3Jj?fWv4((gE@`S0#yr$YpAH z<|NkQAtlg*)G>rgAYUj*>T!V73&LJn(kVNHi;q!BnuTbQAo~75G;{4P^iRvlgk>LG zM7@mKKpxdhK80w3L%r!af^F0skOx3TrD@JnQx%-fSw+we0M0d0!!uuFdA;7v+eXS* z<**qD&R8htwMXEUBMd#Tj&;O%dzEQfmD!22tj@C*H_!fY$x61|3jqHBjn+*X7}>fg z0I-p!Io0+Do`n_&!;WA$drqPO8vuDIr{r0$;rq_$*89b`KK##jdRqbjV3%nWUhbC* zum(EXOUr3$;fk6RJ=LXiDLqT;gjtVCyNS%cz>{uRgB@?3r-swsPP+gHz*-Ia?94VJ ztO19iVd9=xLx9wCqtMQ6V@BAASvbl?e%j4OxIzX6w6TT2!BL9jj9jO;z(kRK%e^OnoN;c%1=J+Mq+Zw68t|O^JFkU zgK;ypqw?SZIT|vhNl>5Ov{{geB!k{EnvrLck!OKXM}dWR;o_U;kk_~0-FHsV-Jpbf zlL>1k6CT}-el!_9csF`=ar8rR!fNU2)%Q~V`<0o_mIv$u&mijX^*SK%Qj|F-4+U_5 zU2UH;;syP2fEZR_%qouAR$RNS?AShinFw?YL=8UdDw*4i!isBHM`{sgA3vT`Q+ND$ zY*`KKe}B=H1}6Ye0AOxgqMm1>URxq!l?-8m93TL&G(c}zl0{pA?Q&@29rs%w!vhwk z1coI1asm`Vp0?!0@a=$5K%#K5_Z?f`|Kp1Qiv}?G^jb^OXwRk#k~6!ayvkPRQ#eO9VAix|#62K6IWcaECPpYaqcf zv&l0JvT$SxVKdH9qQ_C9%rxL>P&)`5HHvpWQ;C9sT$(~<6plhND1t6U>%l(@4m^uI zNJIlHrN=-*aOb*Vi2@CZ7m1-ndBNv(Igo@rDTP$GjO*6UFD!5{A@cfYB%#=!8Yg4G zz>4)1wdzn=mb^YXWc1Vbi^MwfB!s9Q?+$(;jmi>1#tXe76$*7OhexGa7W3#`{K7sr zPhnOb&70UzK;sgN2B=hWF^>^%DS5y+X$MzKGb|f)R&nh-xo%Ju++2w4Q749{f~p)b z#3CNUf+#M545$iYAS|H86NLj5l4zPSz~~Z-2Vza@T9G}3_*GnS!$9n~;JhYnA3QE2 zw_Ylxiz<2e<+9DWWa$v&qyuDl6D0+-T+4=VxOuHKDZvsly6hz3X(I7xKV4KOrb9-X zPV!0di(xltx!NkY2UKM#p)V!X%QkP7Z62Czim3W)a|u4#PjnYD?8L!wP!&FId|K6o zfmo4vG9r0g3_}}*fh9=2)3wsT9K|+;7YJU6&*~)zcubrQhsRK%2sM~J-gP_%grSrP zgNMlMaljIHcP@ z|AAB_l2Fi3kCV*_1w48#d3vsZ7Dq0oA!~WGI7fKKlAf0M5u^;NPsu-n=5$b0Lh)pkqz-q zP#7XdPDOkolrk)2Fq5TpL|6*b1R@7xmL5l~6XTgD#ZokAQP%@(#rV* z30iOf9t+5+z>CtDmno}0bqIWj;T)QdQ0CVaX)c!KV;lySu`=*Unft{Vn5XC{KWZm_34 zNoSUYZ4?pYVSp>)2E2}nT=1TZES<^(qcB8(GOl;_Xe-`d)9C`}E{D z&X_feVR?Yz=ZyJ{YhA@FW}K{->g`bVzz0y5TT05(x|{G!4wWRKr}Z?BhI3Vy2sN3f z8mIJkSY7-46y6hwI?y%pHFU~|yf+3VJwy7m-3 zZz(gY`ud2Rk$aSpOu!X9hV7&Q%CM@m^u(EqE$zJnkH;oH0|ixWSgihf&}gK&p8leU zM$5iH%0DGeGm$Tl2scGRZ4=%*E1m7j4DyYQ-4Gui&tjz|?_jYw8D7thv@D2H#N+)Q zWDHzZf3}X?eed8g^Elp`n6F!NeOuLI9ZWFaG7gJ^uk5V?%AV(n?+x4R`%Qx>kM>#5 zV!si7zNxe8lndO&(UWRn-WwuE3{WLgu&LW_A8{!9ZE!W?d-;a?V@Gnb7X9wIMReNz zRw-HKe#7i|d*AexOrt^bJG-j(&=R@6&DRGT4!$F5xi>CdMq2)TQSWULS-hwoZ&GHi zSzh$A-|6NCmq+QBFC`>+e#>Z{9EtrH@m{=Y%ia&H>-TRyh(4%$WWRg_hB1tO?2{A# zv-moT^BmKZ@#+Bob#rl2Tx-47S9;j;)T_h&v~9On_0Ak?JGbKS*V>=y4TCI~Z(l2I zJx(uP;kfCu@b=h_FX`XJAs6C?e6-acIb?Xy*rlG-_Tt_!D-mnZ0^hZJ6?Fs{zPqyRI2^K z*{VaEEgs^3PYyhIi{w&6{1_W#SIWy&a@2Pz+ofYIVFl&i-Yo7o-uCU?$NuY6%LcZ* zpBi@l&VLlLM(3TV^OR1|%1h2pKPEm;P%6T6yQ<_sw#~ckv0Rio07F%*JE1q(0JYu= zd{W=-zW=I;;iX53K%yyi$|vLqJ}$i7_;CEyA3t7&G`D)&9r}Ln)$+_vQ+HN?y!`mF)2s_|O7}B@9*FMr7@1fde7ZH|RC-j}aK1LcuH&Vj zXj=1P8*DJa_{pGybvv`s;4Ml3#^(kpn6{9eB7JZMkx=gxTldX(k+ z`ZYuN{mzNn2CYRKAHX&VUd+o;p!kpOqaW@hYiU-1j=|@?FgbzJ>4S^!p1k3Xay^7< zM|F)@0Obr2zwPFI0&uUnWJLt{@o@7Pklmnfc8LQjnrLg~Ua+ps&(cr7fMdAam;oMZ z%wW&4t|7@mWnVFIy91*3&fam)bH+@5fg8qk=_{P|yczOGuU(Hivkd#?_R|N|(M7v^ zYMT5e%u@${`({%0BsM5A>2&7M1*t+^w679qNkknx)Lb$zpP)1`53Rz6Y8Bti{&|0X zp>LKP@Q*BeIq{<(^}{4kjA^=9v}2TIm+_;3K)8-q3!S_0;L$Im)g~*(zojP3)Anq) zvptv<^1Jtrk#FD9kza~7WnBD`=DiGnmF%x6#=w87d~(;U*AC_cHD9V+_O^1gslET# zXeAY3>Jy%>4!#islR$*&yrL;-T!uemq~VXlFP#BaO~>rw45n9PYVCL4CS%GQ-FsW@ zS>s^}tHeg~XWlQcjEuiI-#u+A%SS;c^9=?Q34bYiwLohUod*bpUN7fo;Z=hwu*YYB z+8od#Uid`I8C_xK)H`e;*|!+zj~Naw850c}TGqVAtdO&)R9MedD0#bF{Y&FP;%n2P z^H!@zwnrb8p72N*5y$f;_v}mzM}Zb;X}C8^1Nehe&3J#5>-GJNu63VwU$8*;V%V1k z-!PTri61IlZdJzkQ2;x8%V4Mb6}_`8B7Vjw3VnVRs`voD)pEXA5!~1(07(^QCRP#%^c_~shywx z)!XS_$C0r=>*q6`L^YsUoU!lzGn+deXSc!z+H#5hM&%(FSl-<~e76DfoocNw3pYg9yyi`yOwvgq^hVJ8@{6mTe}Pa;72Y z@afY&ed7%$o-AJ8qhfgY*!de#EptwbZ(4rnwgez@Zz;7Fn8QrDF*3Cg?P4~;|78B{ z`8-!eAi0}U!B|woZr|75Y4oOlNNpp3s`H^_(gj3lT`SsOX3tE?-m?GRIdyq~ya#r2 z%ij0vpPMJWGTv3b8oTjG=75n0g*&>6BlPCRw>reH?38L3w zXRgihj6^4zf9cd^m+jO|GR<;Y>p1+bbdW!MKz%PN-P7!hY4N zGd^>>TW=jzee&_}?nYypZ^&x*wP%YY+~DfHDHXF$d`O2Wuf1G(C-Gt+iY4B6KtIHJK zG7xfG&b|Qy${tqp2V-?-vd@L+Ixm=&`)X%=!_ea$x4L}>Q->cl`;{D_1)s_%DOq}a z&2c>XqSUEyLFecx0D@zv+jSNy_bmEE8!OSSu=c=S-RH4T?Zk!ernk?&I%c4kDL44= zruOL9wZGTAK6oo>CH?-HFE=h2ngoG7)SddwoR+ZAwe+Z~vw9{jPh9eCGpbl~Ww=Ry zX`}Fc+3`oz!q>SC^STyp^zm~UKJ@e4&rhCby$3Rk1tQ)o*zK6j%ikmeeXw&SZk%W z*M{}h%PQ&J1J(OWZ5-1Kn>x0Jua)9QD8et3D?S!PH<}uY`e?AGjhj;CK4&heU;iNP zW|#Yxi0nhHf2J)P{#kdg)waF+?AOl`Lxo2S-9pE!Rt^>$=oaLcThFz4?HuHlJn!b# zb>E``OUrE~clHhMxE0ZHaWY@=8aI(ES#)a2mWayQ{huQD@UG?lX^S*7+qGy#?t%Bb zd>i{-jR6J+7hhtZsE7)%d7n_*mHU`~Y4MLuHKYX9&1tQH@wxc;^|@my-8Pz}-^~sg zUHxj3Vm}mix!bR4C^g|M(|DfigwUy@|w4Rguv9^4F$lK8m{Vq>l9et}c zFXXM_@9~e;7;hMO)HZZz^@pFECxbM>k}1`2l(W0pCx=Mxs~h5SFz% z|L)ZGZQ&X%JFVjlnu%fDLaPQff}-`siw<_?LHU!;2Q?4zov&wU0JOc`?8cMJ>W=cRb;&8OvV=}e-@7e` zSKdr8=G{OC;sF>7(J@h9bH18le#+J_SjXkbODSWZOTXSolkQq>{LT1r@cy^W6^Uwq U{o_ulkNzwETg}LC^=tJ118M3~A^-pY literal 0 HcmV?d00001 diff --git a/Resources/Audio/Ambience/Objects/shower_running.ogg b/Resources/Audio/Ambience/Objects/shower_running.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9114b0c7dab2c22c6643e931cee75fce5294017f GIT binary patch literal 32475 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 Dp-e$q literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/shower/shower-component.ftl b/Resources/Locale/en-US/shower/shower-component.ftl new file mode 100644 index 00000000000..8713fb0c1f7 --- /dev/null +++ b/Resources/Locale/en-US/shower/shower-component.ftl @@ -0,0 +1,2 @@ +shower-turn-on = Turn On +shower-turn-off = Turn Off \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Furniture/shower.yml b/Resources/Prototypes/Entities/Structures/Furniture/shower.yml new file mode 100644 index 00000000000..694202efdc6 --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Furniture/shower.yml @@ -0,0 +1,46 @@ +- type: entity + name: shower + id: Shower + description: A shower, complete with bluespace water. + placement: + mode: SnapgridCenter + snap: + - Wallmount + components: + - type: Sprite + sprite: Structures/Furniture/shower.rsi + drawdepth: WallMountedItems + layers: + - state: shower + map: ["enabled", "enum.ShowerVisualState.Off" ] + - type: Appearance + - type: Rotatable + - type: Transform + noRot: false + - type: Clickable + - type: Shower + - type: Physics + bodyType: Static + canCollide: false + - type: InteractionOutline + - type: Damageable + - type: Construction + graph: Shower + node: shower + damageContainer: Inorganic + damageModifierSet: Metallic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: GenericVisualizer + visuals: + enum.ShowerVisuals.ShowerVisualState: + ShowerVisualState.Off: + On: { state: shower_on } + Off: { state: shower } + diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/furniture/shower.yml b/Resources/Prototypes/Recipes/Construction/Graphs/furniture/shower.yml new file mode 100644 index 00000000000..eb0618473b8 --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/Graphs/furniture/shower.yml @@ -0,0 +1,29 @@ +- type: constructionGraph + id: Shower + start: start + graph: + - node: start + edges: + - to: shower + completed: + - !type:SnapToGrid { } + steps: + - material: Steel + amount: 5 + doAfter: 1 + - node: shower + entity: Shower + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: SheetSteel1 + amount: 5 + - !type:EmptyAllContainers {} + - !type:DestroyEntity {} + conditions: + - !type:EntityAnchored + anchored: false + steps: + - tool: Welding + doAfter: 2 diff --git a/Resources/Prototypes/Recipes/Construction/furniture.yml b/Resources/Prototypes/Recipes/Construction/furniture.yml index 5f7ec9c92d8..3ed0c9b9611 100644 --- a/Resources/Prototypes/Recipes/Construction/furniture.yml +++ b/Resources/Prototypes/Recipes/Construction/furniture.yml @@ -596,6 +596,24 @@ - !type:TileNotBlocked #bathroom +- type: construction + name: shower + id: Shower + graph: Shower + startNode: start + targetNode: shower + category: construction-category-furniture + description: A shower, complete with bluespace water. + icon: + sprite: Structures/Furniture/shower.rsi + state: shower + objectType: Structure + placementMode: SnapgridCenter + canRotate: true + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked + - type: construction name: toilet id: ToiletEmpty @@ -732,7 +750,7 @@ objectType: Structure placementMode: SnapgridCenter canBuildInImpassable: true - + - type: construction id: CurtainsBlack name: black curtains @@ -762,7 +780,7 @@ objectType: Structure placementMode: SnapgridCenter canBuildInImpassable: true - + - type: construction id: CurtainsCyan name: cyan curtains @@ -777,7 +795,7 @@ objectType: Structure placementMode: SnapgridCenter canBuildInImpassable: true - + - type: construction id: CurtainsGreen name: green curtains @@ -792,7 +810,7 @@ objectType: Structure placementMode: SnapgridCenter canBuildInImpassable: true - + - type: construction id: CurtainsOrange name: orange curtains @@ -807,7 +825,7 @@ objectType: Structure placementMode: SnapgridCenter canBuildInImpassable: true - + - type: construction id: CurtainsPink name: pink curtains @@ -822,7 +840,7 @@ objectType: Structure placementMode: SnapgridCenter canBuildInImpassable: true - + - type: construction id: CurtainsPurple name: purple curtains @@ -837,7 +855,7 @@ objectType: Structure placementMode: SnapgridCenter canBuildInImpassable: true - + - type: construction id: CurtainsRed name: red curtains diff --git a/Resources/Textures/Structures/Furniture/shower.rsi/meta.json b/Resources/Textures/Structures/Furniture/shower.rsi/meta.json new file mode 100644 index 00000000000..8e48a41e2f3 --- /dev/null +++ b/Resources/Textures/Structures/Furniture/shower.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by Dakodragon, DiscordID: 56038550335922176", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "shower", + "directions": 4 + }, + { + "name": "shower_on", + "directions": 4, + "delays": [ + [ 0.3, 0.3, 0.3 ], + [ 0.3, 0.3, 0.3 ], + [ 0.3, 0.3, 0.3 ], + [ 0.3, 0.3, 0.3 ] + ] + } + ] +} diff --git a/Resources/Textures/Structures/Furniture/shower.rsi/shower.png b/Resources/Textures/Structures/Furniture/shower.rsi/shower.png new file mode 100644 index 0000000000000000000000000000000000000000..4ebce554d1c8cdd1ceeedee1a184cbd75da84ec4 GIT binary patch literal 540 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z_jtNEhE&XX zd)vP2kb?y42lLZrjUw|DroLblGir_IxLw6$>sX|3+xWIDTQEOCLV#_ziCE*5&8>cB zn>OSm{hRcidG?8xpYxaxo-t?g=QwoXNYvv=Du?2%T`wAM&$;V;UHF9*^9rLA62aeX ztb(l=qH9E4E4kJ^4)IgrINZMR*o;4y+q|?N)YwTc6=6ttRykuw-cy03wVwrcMMSPo zWtZu9Up(c|^@kJUXIIK4tu-u+EoM3*f4F|9y`zsnTiW*9iB@yP_Uo0d*YaXlSh}V* zX#VfL2eQ6?_?&Mx`&c)7l*bSIXF-QbWsD1B8NNG2U0QwofvInyr;y?FO|MsOd7rz} zefFJ?{GFNRhzp>@fw%r2us_cmwRa?z(ut~S&evmrKrBSx|#yz&%cg?y)6_$#4 zt!#hvR_u>PSi{%C{6jmIXWaML?O{ifHzNaah7@J#ddWzYh$ VIe-`hE(K2pQJ$`TF6*2UngBiCf@ndAUc(YS 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 TXUzERe~q@fo?4ZPUDW>oqBl@E literal 0 HcmV?d00001 From e14bea6f259e64eef5c9a7d4cebb08467ae87c16 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Mon, 12 Aug 2024 16:46:30 +0000 Subject: [PATCH 087/135] Automatic Changelog Update (#661) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index c13b19a328f..75cc34a090f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5250,3 +5250,9 @@ Entries: message: Added the Home Run Bat for Syndicate operatives. Send your foes flying! id: 6255 time: '2024-08-12T16:43:11.0000000+00:00' +- author: Tilkku + changes: + - type: Add + message: Added showers + id: 6256 + time: '2024-08-12T16:46:05.0000000+00:00' From 6df564aafcabdea28a01c28535ae62329c3b837e Mon Sep 17 00:00:00 2001 From: gluesniffler <159397573+gluesniffler@users.noreply.github.com> Date: Mon, 12 Aug 2024 17:43:52 -0400 Subject: [PATCH 088/135] Hardsuit MRP Descriptions (#725) # Description Copying over the original description from #617 > This is a significantly pared down version of #492 > Focusing only on a small category of item descriptions just to get the ball rolling. > > Space Station 14 is actually missing the other two suit-names that were at one point present and commonplace in SS13. The term "Hardsuit" is itself one of three classifications of space suit, based on a book series that I read as a teenager. The full list is as follows. > > Vacsuit: Vacuum-Protection-Suit > Hardsuit: Hardened Vacsuit > Tacsuit: Tactical Combat Hardsuit > Vacsuits are a catch-all shorthand for civilian space suits. They offer no actual protection from anything other than the cold void. > Hardsuits are a form of "Up-armored" vacsuit, and are more like industrial PPE in space. You wear a hardsuit because it's there to protect you while you're welding, shipbreaking, asteroid mining, and so on. > Tacsuits are a variant on the idea of a hardsuit, but instead of having an industrial purpose, they are explicitly for military purposes, and aren't for civilian use at all. > > I've opened this up on draft because Mocho was asking to help me with it. > > Generally, the hardsuits need to be explicitly associated with a specific in-universe corporation. With descriptions changed to better suit a hypothetical setting that we'd wish to write. > > For instance, much of the equipment used by Security would likely be products of Five-Points-Armory, a corporation that NT prefers to buy their security equipment from for the simple fact that it's cheap, yet gets the job done. Rewrote hardsuit descriptions to match the original request, but from the POV of a character as suggested by @DangerRevolution. The descriptions also have a rough template which goes along the lines of... {Type of suit} produced by {corporation} + {optional visual attributes} + the label/tag says {hint at protective stats} + it feels {light or heavy depending on speed stats}. In the commits you can also find that I had lengthier but more fleshed out descs for each of the hardsuits. But they went into detail your character wouldn't feasibly be able to know at a glance (how do I know this suit is made of plastitanium plating, and that the other has ceramic TPS plates?). Feel free to ask for mix and matching between the two. **Also I moved the paramedic voidsuit to be a hardsuit, because for whatever reason it wasn't one already.** Even had all of the properties that a normal hardsuit does. :trollface: --- # Changelog :cl: - tweak: Changed hardsuit descriptions to be slightly less LRP. - tweak: Changed paramedic voidsuit from a softsuit to a hardsuit. --------- Co-authored-by: VMSolidus --- .../clothing/head/hardsuit-helmets.ftl | 102 +++++++++++++ .../clothing/outerClothing/hardsuits.ftl | 135 ++++++++++++++++++ .../Catalog/Fills/Lockers/suit_storage.yml | 3 +- .../Entities/Clothing/Head/eva-helmets.yml | 20 --- .../Clothing/Head/hardsuit-helmets.yml | 19 +++ .../Clothing/OuterClothing/hardsuits.yml | 32 +++++ .../Clothing/OuterClothing/softsuits.yml | 53 ++----- .../Clothing/Head/hardsuit-helmets.yml | 4 +- .../Objectives/stealTargetGroups.yml | 2 +- .../paramedhelm.rsi/equipped-HELMET.png | Bin .../paramedhelm.rsi/icon.png | Bin .../paramedhelm.rsi/inhand-left.png | Bin .../paramedhelm.rsi/inhand-right.png | Bin .../paramedhelm.rsi/meta.json | 52 +++---- 14 files changed, 326 insertions(+), 96 deletions(-) create mode 100644 Resources/Locale/en-US/prototypes/entities/clothing/head/hardsuit-helmets.ftl create mode 100644 Resources/Locale/en-US/prototypes/entities/clothing/outerClothing/hardsuits.ftl rename Resources/Textures/Clothing/Head/{Helmets => Hardsuits}/paramedhelm.rsi/equipped-HELMET.png (100%) rename Resources/Textures/Clothing/Head/{Helmets => Hardsuits}/paramedhelm.rsi/icon.png (100%) rename Resources/Textures/Clothing/Head/{Helmets => Hardsuits}/paramedhelm.rsi/inhand-left.png (100%) rename Resources/Textures/Clothing/Head/{Helmets => Hardsuits}/paramedhelm.rsi/inhand-right.png (100%) rename Resources/Textures/Clothing/Head/{Helmets => Hardsuits}/paramedhelm.rsi/meta.json (95%) diff --git a/Resources/Locale/en-US/prototypes/entities/clothing/head/hardsuit-helmets.ftl b/Resources/Locale/en-US/prototypes/entities/clothing/head/hardsuit-helmets.ftl new file mode 100644 index 00000000000..2bbacf2abca --- /dev/null +++ b/Resources/Locale/en-US/prototypes/entities/clothing/head/hardsuit-helmets.ftl @@ -0,0 +1,102 @@ +ent-ClothingHeadHelmetHardsuitBasic = basic vacsuit helmet + .desc = A common vacsuit helmet that provides little more than basic protection from vacuum. +ent-ClothingHeadHelmetHardsuitAtmos = HpI-19t helmet + .desc = The Fotia's standard helmet, it features the same heat protection as the suit, along with some integrated protective gear for the wearer's head. +ent-ClothingHeadHelmetHardsuitEngineering = HpI-19r helmet + .desc = The Lampsi's standard helmet, it features the same radiation protection as the suit, along with some integrated protective gear for the wearer's head. +ent-ClothingHeadHelmetHardsuitSpatio = HpI-20s helmet + .desc = A lightweight helmet designed for the Kriti hardsuit, it allows for better mobility, along with some protection against radiation. +ent-ClothingHeadHelmetHardsuitSalvage = HpI-20a helmet + .desc = A bulky helmet designed for the Lavrion hardsuit, it has reinforced plating to protect the wearer's head in wildlife encounters. +ent-ClothingHeadHelmetHardsuitVoidParamed = ZhP-24m helmet + .desc = A lightweight helmet designed for use with the Sukunabikona hardsuit. Parts of the helmet are made of hard transparent plastics, allowing for better visibility. +ent-ClothingHeadHelmetHardsuitMaxim = mysterious helmet + .desc = An old looking helmet, it seems rather sturdy and lightweight. It also has an ominous red and black color scheme. +ent-ClothingHeadHelmetHardsuitSecurity = FPA-83s helmet + .desc = A bulky helmet deployed with the Baghatur tacsuit. Protects its wearer against ballistics and explosive ordinance, at the cost of some mobility. +ent-ClothingHeadHelmetHardsuitBrigmedic = FPA-84m helmet + .desc = A bulky helmet deployed with the Tsagaan tacsuit. Protects its wearer against ballistics and explosive ordinance, at the cost of some mobility. +ent-ClothingHeadHelmetHardsuitCombatStandard = FPA-85 helmet + .desc = A bulky helmet deployed with the Baghatur Mk.II tacsuit. + Protects its wearer against ballistics and explosive ordinance, at the cost of some mobility. +ent-ClothingHeadHelmetHardsuitCombatOfficer = FPA-85s helmet + .desc = { ent-ClothingHeadHelmetHardsuitCombatStandard.desc } +ent-ClothingHeadHelmetHardsuitCombatMedical = FPA-86 helmet + .desc = A bulky helmet deployed with the Tsagaan Mk.II tacsuit. + Protects its wearer against ballistics and explosive ordinance, at the cost of some mobility. +ent-ClothingHeadHelmetHardsuitCombatCorpsman = FPA-86m helmet + .desc = { ent-ClothingHeadHelmetHardsuitCombatMedical.desc } +ent-ClothingHeadHelmetHardsuitWarden = FPA-92s helmet + .desc = A modified riot-control helmet for use with the Sulde tacsuit. Offers better overall protection than standard tacsuits at the expense of mobility. +ent-ClothingHeadHelmetHardsuitCombatRiot = FPA-93 helmet + .desc = A modified riot-control helmet for use with the Sulde Mk.II tacsuit. + Offers better overall protection than other models at the expense of mobility. +ent-ClothingHeadHelmetHardsuitCombatWarden = FPA-93s helmet + .desc = { ent-ClothingHeadHelmetHardsuitCombatRiot.desc } +ent-ClothingHeadHelmetHardsuitCap = NT-42c helmet + .desc = A special helmet for the Tengri tacsuit, despite its lightweight appearance, it provides good all-around protection to its wearer. +ent-ClothingHeadHelmetHardsuitEngineeringWhite = HpI-24c helmet + .desc = A high-grade helmet used with the Daedalus hardsuit, it has a lighter construction than its standard counterparts, along with more radiation protection. +ent-ClothingHeadHelmetHardsuitMedical = ZhP-25m helmet + .desc = An extraordinarily lightweight helmet designed for use with the Okuninushi hardsuit. + It is primarily made from transparent hard-plastics, providing complete freedom of vision. +ent-ClothingHeadHelmetHardsuitRd = NT-45e helmet + .desc = A heavily armored helmet worn over the Sophia hardsuit. It boasts the same near-immunity to explosions, heat and radiation as the suit, but heavily restricts the wearer's mobility. +ent-ClothingHeadHelmetHardsuitMystagogue = NT-45e helmet + .desc = { ent-ClothingHeadHelmetHardsuitRd.desc } +ent-ClothingHeadHelmetHardsuitSecurityRed = FPA-98s helmet + .desc = A high quality helmet for the Dayicin tacsuit. It offers better overall protection than standard tacsuits without impacting mobility as much. +ent-ClothingHeadHelmetHardsuitCombatAdvanced = FPA-99 helmet + .desc = A high quality helmet for the Dayicin Mk.II tacsuit. + Features a lightweight construction, offering the same protection as a standard tacsuit without impacting mobility as much. +ent-ClothingHeadHelmetHardsuitCombatHoS = FPA-99s helmet + .desc = { ent-ClothingHeadHelmetHardsuitCombatAdvanced.desc } +ent-ClothingHeadHelmetHardsuitLuxury = HpI-20c helmet + .desc = A modified helmet for the Minos hardsuit, fashioned after the Logistics Officer's colors. It's been modified for greater mobility at the expense of physical trauma protection. +ent-ClothingHeadHelmetHardsuitSyndie = CSA-51a helmet + .desc = An armored helmet deployed over a Shanlin tacsuit. This one has been painted blood red. +ent-ClothingHeadHelmetHardsuitSyndieMedic = CSA-51m helmet + .desc = An armored helmet deployed over a Zhongyao tacsuit. features optic integrations for nearly every medical hud on the market. + Designed to enable the survival of combat medics in the most dangerous of environments. +ent-ClothingHeadHelmetHardsuitSyndieElite = CSA-54UA helmet + .desc = An elite version of the Shanlin tacsuit's helmet, featuring improved armor and fireproofing. +ent-ClothingHeadHelmetHardsuitSyndieCommander = CSA-54c helmet + .desc = A bulked up version of the Shanlin tacsuit's helmet, purpose-built for commanders of special operation squads. This one has been painted blood-red. +ent-ClothingHeadHelmetHardsuitCybersun = CSA-80UA helmet + .desc = An incredibly sturdy looking helmet designed for the Guan Yu tacsuit. +ent-ClothingHeadHelmetHardsuitWizard = WZD-84 helmet + .desc = A bizarre, gem-encrusted helmet from unknown origins. It provides some protection to its wearer without restricting their movements. +ent-ClothingHeadHelmetHardsuitLing = organic space helmet + .desc = A spaceworthy biomass of pressure and temperature resistant tissue. +ent-ClothingHeadHelmetHardsuitPirateEVA = pirate helmet + .desc = A pirate vacsuit helmet, very heavy but provides good protection. + .suffix = Pirate +ent-ClothingHeadHelmetHardsuitPirateCap = pirate captain's tacsuit helmet + .desc = A special hardsuit helmet, made for the captain of a pirate ship. + .suffix = Pirate +ent-ClothingHeadHelmetHardsuitSyndieReverseEngineered = NTSA-122 helmet + .desc = A sturdy, lightweight helmet made by the special adquisitions department of Nanotrasen. +ent-ClothingHeadHelmetHardsuitJuggernautReverseEngineered = NTSA-126 helmet + .desc = A very sturdy helmet made by the special acquisitions department of Nanotrasen, based on the "Juggernaut" tacsuit's design. +ent-ClothingHeadHelmetHardsuitERTCentcomm = NT-444c helmet + .desc = A special tacsuit helmet worn by Central Command Officers. +ent-ClothingHeadHelmetHardsuitERTLeader = NT-444l helmet + .desc = A special tacsuit helmet worn by leaders of an emergency response team. +ent-ClothingHeadHelmetHardsuitERTEngineer = NT-444e helmet + .desc = A special hardsuit helmet worn by members of an engineering emergency response team. +ent-ClothingHeadHelmetHardsuitERTMedical = NT-444m helmet + .desc = A special hardsuit helmet worn by members of a medical emergency response team. +ent-ClothingHeadHelmetHardsuitERTSecurity = NT-444s helmet + .desc = A special tacsuit helmet worn by members of a engineering emergency response team. +ent-ClothingHeadHelmetHardsuitERTJanitor = NT-444j helmet + .desc = A special hardsuit helmet worn by members of a janitorial emergency response team. +ent-ClothingHeadHelmetCBURN = NT-444-CBRN helmet + .desc = A pressure resistant and fireproof hood worn by special cleanup units. +ent-ClothingHeadHelmetHardsuitDeathsquad = NT-662ua helmet + .desc = A highly advanced, top of the line helmet used in special operations. +ent-ClothingHeadHelmetHardsuitClown = clown vacsuit helmet + .desc = A colorful clown vacsuit helmet. On closer inspection, it appears to be a normal helmet painted with crayons, and a clown mask glued on top. +ent-ClothingHeadHelmetHardsuitMime = mime vacsuit helmet + .desc = A mime vacsuit helmet. On closer inspection, it appears to be a normal helmet painted with crayons, and a mime mask glued on top. +ent-ClothingHeadHelmetHardsuitSanta = DNK-31 helmet + .desc = A festive-looking hardsuit helmet that provides the jolly gift-giver protection from low-pressure environments. \ No newline at end of file diff --git a/Resources/Locale/en-US/prototypes/entities/clothing/outerClothing/hardsuits.ftl b/Resources/Locale/en-US/prototypes/entities/clothing/outerClothing/hardsuits.ftl new file mode 100644 index 00000000000..84f03af5c92 --- /dev/null +++ b/Resources/Locale/en-US/prototypes/entities/clothing/outerClothing/hardsuits.ftl @@ -0,0 +1,135 @@ +ent-ClothingOuterHardsuitBasic = basic vacsuit + .desc = A common, colonial-era vacsuit of indeterminate make and model. It's strictly better than nothing, but not by much. +ent-ClothingOuterHardsuitAtmos = HpI-19t "Fotia" hardsuit + .desc = A standard-issue hardsuit produced by Hephaestus Industries, used by atmospheric technicians in low & high pressure environments. + The label indicates that its rated for high amounts of thermal exposure. It feels a bit heavy. +ent-ClothingOuterHardsuitEngineering = HpI-19r "Lampsi" hardsuit + .desc = A standard-issue hardsuit produced by Hephaestus Industries, used by engineers in low & high pressure environments. + The label indicates that its rated for moderate amounts of radiation exposure. It feels a bit heavy. +ent-ClothingOuterHardsuitSpatio = HpI-20s "Kriti" hardsuit + .desc = A standard-issue hardsuit produced by Hephaestus Industries, designed for industrial work in low pressure environments. + The label indicates that its rated for moderate amounts of radiation exposure, and it feels somewhat light. +ent-ClothingOuterHardsuitSalvage = HpI-20a "Lavrion" hardsuit + .desc = A sturdy hardsuit produced by Hephaestus Industries, designed for industrial work in low pressure environments. + The labels indicate that it provides protection against most forms of damage. It feels heavy. +ent-ClothingOuterHardsuitVoidParamed = ZhP-24m "Sukunabikona" + .desc = A standard-issue hardsuit manufactured by Zeng-Hu Pharmaceuticals, used by paramedics due to its lightweight frame. + The label mentions that it offers some protection against chemical spills. +ent-ClothingOuterHardsuitMaxim = Mysterious tacsuit + .desc = An old looking tactical combat hardsuit. It has a faded red logo on it along with the words "Maxim". + It feels very sturdy and doesn't seem to have any weight... Though it has an ominous aura to it. +ent-ClothingOuterHardsuitSecurity = FPA-83s - "Baghatur" tacsuit + .desc = A sturdy tactical combat hardsuit mass-produced by Five-Points-Armory, used by the Nanotrasen security force. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels heavy. +ent-ClothingOuterHardsuitBrigmedic = FPA-84m - "Tsagaan" tacsuit + .desc = A sturdy tactical combat hardsuit mass-produced by Five-Points-Armory, used by doctors in the Nanotrasen security force. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels heavy. +ent-ClothingOuterHardsuitCombatStandard = FPA-85 - "Baghatur Mk.II" tacsuit + .desc = A sturdy tactical combat hardsuit mass-produced by Five-Points-Armory. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels heavy. +ent-ClothingOuterHardsuitCombatOfficer = FPA-85s - "Baghatur Mk.II" tacsuit + .desc = A sturdy tactical combat hardsuit mass-produced by Five-Points-Armory, painted with the colors of station security. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels heavy. +ent-ClothingOuterHardsuitCombatMedical = FPA-86 - "Tsagaan Mk.II" tacsuit + .desc = A sturdy tactical combat hardsuit mass-produced by Five-Points-Armory. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels heavy. +ent-ClothingOuterHardsuitCombatCorpsman = FPA-86m - "Tsagaan Mk.II" tacsuit + .desc = A sturdy tactical combat hardsuit mass-produced by Five-Points-Armory, painted with the colors of station security & medical staff. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels heavy. +ent-ClothingOuterHardsuitWarden = FPA-92s - "Sulde" tacsuit + .desc = A specialized tactical combat hardsuit produced by Five-Points-Armory, often used by Wardens in Nanotrasen stations. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels VERY heavy. +ent-ClothingOuterHardsuitCombatRiot = FPA-93 - "Sulde Mk.II" tacsuit + .desc = A specialized tactical combat hardsuit produced by Five-Points-Armory. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels VERY heavy. +ent-ClothingOuterHardsuitCombatWarden = FPA-93s - "Sulde Mk.II" tacsuit + .desc = A specialized tactical combat hardsuit produced by Five-Points-Armory, painted with the colors of station security. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels VERY heavy. +ent-ClothingOuterHardsuitCap = NT-42c - "Tengri" tacsuit + .desc = A formal, tactical combat hardsuit, made in collaboration by Nanotrasen's R&D department with Five-Points-Armory for station captains. + The labels indicate that it provides protection against most forms of damage. It feels somewhat light. +ent-ClothingOuterHardsuitEngineeringWhite = HpI-24c "Daedalus" hardsuit + .desc = A specialized hardsuit produced by Hephaestus Industries, often purchased for use by Nanotrasen senior engineers. + The labels indicate that its rated for high amounts of radiation and pressure. It feels somewhat light. +ent-ClothingOuterHardsuitMedical = ZhP-25m - "Okuninushi" hardsuit + .desc = A hardsuit produced by Zeng-hu Pharmaceuticals, often purchased for use by Nanotrasen senior medical doctors. + The labels claim it protects against damage from most chemical spills. It feels incredibly light. +ent-ClothingOuterHardsuitRd = NT-45e - "Sophia" research hardsuit + .desc = The magnum opus of Nanotrasen's R&D division. The labels on this hardsuit claim that its near-immune to explosions, heat and radiation. + Somehow it also can shrink enough to fit in a bag. It feels VERY heavy. +ent-ClothingOuterHardsuitMystagogue = NT-45e - "Sophia" research hardsuit + .desc = { ent-ClothingOuterHardsuitRd.desc } +ent-ClothingOuterHardsuitSecurityRed = FPA-98s - "Dayicin" tacsuit + .desc = A top-of-the-line tactical combat hardsuit produced by Five-Points-Armory, often purchased for use by Nanotrasen senior security officers. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels somewhat light. +ent-ClothingOuterHardsuitCombatAdvanced = FPA-99 - "Dayicin Mk.II" tacsuit + .desc = A top-of-the-line tactical combat hardsuit produced by Five-Points-Armory. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels somewhat light. +ent-ClothingOuterHardsuitCombatHoS = FPA-99s - "Dayicin Mk.II" tacsuit + .desc = A top-of-the-line tactical combat hardsuit produced by Five-Points-Armory, painted with the colors of station security. + The tags on the suit indicate that its rated for moderate amounts of physical and explosion damage. It feels somewhat light. +ent-ClothingOuterHardsuitLuxury = HpI-20c - "Minos" hardsuit + .desc = A modified mining hardsuit from Hephaestus Industries, fashioned after the Logistics Officer's colors. + The labels indicate that it provides slight protection against most forms of damage. It feels incredibly light. +ent-ClothingOuterHardsuitSyndie = CSA-51a - "Shanlin" tacsuit + .desc = A tactical combat hardsuit produced by the Cybersun-Armaments Corporation, the suit's tags indicate it provides moderate protection against most forms of damage. + This one has been painted blood red. It feels incredibly light. +ent-ClothingOuterHardsuitSyndieMedic = CSA-51m - "Zhongyao" tacsuit + .desc = A tactical combat hardsuit produced by the Cybersun-Armaments Corporation, the suit's tags indicate it provides moderate protection against most forms of damage. + Half of the suit is painted blood red, the rest bears galactic-standard medical markings. It feels incredibly light. +ent-ClothingOuterHardsuitSyndieElite = CSA-54UA - "Shiwei" tacsuit + .desc = An "Up-Armored" tactical combat hardsuit produced by the Cybersun-Armaments Corporation. + The suit's tags indicate its rated for high exposure to radiation, heat and explosions, along with moderate physical trauma protection. + It feels incredibly light. +ent-ClothingOuterHardsuitSyndieCommander = CSA-54c - "Tianming" tacsuit + .desc = A "Commander" tactical combat hardsuit produced by the Cybersun-Armaments Corporation. The suit's tags indicate that it protects greatly against all forms of damage. + This one has been painted blood red. It doesn't seem to have any weight. +ent-ClothingOuterHardsuitJuggernaut = CSA-80UA - "Guan Yu" tacsuit + .desc = The pride and joy of the Cybersun-Armaments Corporation, named after an ancient Sol' War God. Commonly known throughout the galaxy as a "Juggernaut". + Matching its bulky appearance, it protects against all forms of damage. It feels VERY heavy. +ent-ClothingOuterHardsuitWizard = WZD-84 - "Mana" tacsuit + .desc = A bizarre gem-encrusted hardsuit. Famously used by members of the Wizard Federation in their operations. + Contrary to it's appearance, it can protect its wearer from space and considerable amounts of physical trauma, it feels somewhat light. +ent-ClothingOuterHardsuitLing = organic vacsuit + .desc = A suit made of biomass tissue that is somehow capable of resisting the hazards of low pressure and temperature in space. +ent-ClothingOuterHardsuitPirateEVA = pirate vacsuit + .desc = A worn-out heavy space suit of unknown origin that provides some basic protection from the cold harsh realities of deep space. + .suffix = Pirate +ent-ClothingOuterHardsuitPirateCap = pirate captain's tacsuit + .desc = An ancient armored tactical combat hardsuit of unknown origin, provides basic protections from the cold harsh realities of deep space and physical trauma. + It doesn't seem to have any weight either. Perfect for defending against space scurvy and toolbox-wielding scallywags. +ent-ClothingOuterHardsuitSyndieReverseEngineered = NTSA-122 tacsuit + .desc = A suit made by the special adquisitions department of Nanotrasen, the suit's tags indicate it provides moderate protection against most forms of damage. +ent-ClothingOuterHardsuitJuggernautReverseEngineered = NTSA-126 tacsuit + .desc = A suit made by the special acquisitions department of Nanotrasen based on the "Juggernaut" design. + Matching its bulky appearance, it protects against all forms of damage. It feels VERY heavy. +ent-ClothingOuterHardsuitERTCentcomm = NT-444c - "Ophanim" tacsuit + .desc = A highly advanced, tactical combat hardsuit used by Central Command Officers, it seems to be branded with the Nanotrasen logo and a strange looking series number. + The armor appears to be lined with a very sturdy alloy, it doesn't seem to have any weight either. +ent-ClothingOuterHardsuitERTLeader = NT-444l - "Michael" tacsuit + .desc = A highly advanced, tactical combat hardsuit used by Leaders of the Emergency Response Team, it seems to be branded with the Nanotrasen logo and a strange looking series number. + The armor appears to be lined with a very sturdy alloy, it doesn't seem to have any weight either. +ent-ClothingOuterHardsuitERTEngineer = NT-444e - "Uriel" hardsuit + .desc = A highly advanced hardsuit used by Engineers of the Emergency Response Team, it seems to be branded with the Nanotrasen logo and a strange looking series number. + The armor appears to be lined with a very sturdy alloy, it doesn't seem to have any weight either. +ent-ClothingOuterHardsuitERTMedical = NT-444m - "Raphael" hardsuit + .desc = A highly advanced hardsuit used by Doctors of the Emergency Response Team, it seems to be branded with the Nanotrasen logo and a strange looking series number. + The armor appears to be lined with a very sturdy alloy, it doesn't seem to have any weight either. +ent-ClothingOuterHardsuitERTSecurity = NT-444s - "Gabriel" tacsuit + .desc = A highly advanced, tactical combat hardsuit used by Security Officers of the Emergency Response Team, it seems to be branded with the Nanotrasen logo and a strange looking series number. + The armor appears to be lined with a very sturdy alloy, it doesn't seem to have any weight either. +ent-ClothingOuterHardsuitERTJanitor = NT-444j - "Sandalphon" hardsuit + .desc = A highly advanced hardsuit used by Janitors of the Emergency Response Team, it seems to be branded with the Nanotrasen logo and a strange looking series number. + The armor appears to be lined with a very sturdy alloy, it doesn't seem to have any weight either. +ent-ClothingOuterHardsuitDeathsquad = NT-662ua "Samael" tacsuit + .desc = A highly advanced, top of the line tactical combat hardsuit, it seems to be branded with the Nanotrasen logo and a strange looking series number. + You can barely make out the letters "NTIA-DAP" written on it. The armor appears to be lined with a very sturdy alloy, and doesn't seem to have any weight either. +ent-ClothingOuterHardsuitCBURN = NT-444-CBRN -"Jophiel" tacsuit + .desc = A tactical combat hardsuit used by the CBURN subdivision of the Emergency Response Team, it seems to be branded with the Nanotrasen logo and a strange looking series number. + The armor appears to be lined with a rather plain, but sturdy alloy, it doesn't seem to have any weight either. +ent-ClothingOuterHardsuitClown = clown vacsuit + .desc = A custom-made clown vacsuit. On closer inspection, it appears to be a normal vacsuit with paint applied on top. +ent-ClothingOuterHardsuitMime = mime vacsuit + .desc = A custom-made mime vacsuit. On closer inspection, it appears to be a normal vacsuit with suspenders and paint applied on top. +ent-ClothingOuterHardsuitSanta = DNK-31 "Jolly" hardsuit + .desc = A festive hardsuit produced by Donk Co. for their time-limited celebratory events, provides protection for its jolly gift-giver to sleighride safely in space without worrying about asteroid strikes. \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml b/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml index ac5cb47cc97..734bd485a2e 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml @@ -44,7 +44,7 @@ suffix: Prisoner EVA components: - type: StorageFill - contents: + contents: - id: OxygenTankFilled - id: ClothingOuterHardsuitEVAPrisoner - id: ClothingHeadHelmetEVALarge @@ -258,7 +258,6 @@ - id: NitrogenTankFilled - id: OxygenTankFilled - id: ClothingOuterHardsuitVoidParamed - - id: ClothingHeadHelmetVoidParamed - id: ClothingMaskBreathMedical - type: AccessReader access: [ [ "Paramedic" ] ] diff --git a/Resources/Prototypes/Entities/Clothing/Head/eva-helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/eva-helmets.yml index 963bcdedd78..c3c6a617a03 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/eva-helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/eva-helmets.yml @@ -54,26 +54,6 @@ - type: Clothing sprite: Clothing/Head/Helmets/cosmonaut.rsi -#Paramedic Void Helmet -- type: entity - parent: ClothingHeadEVAHelmetBase - id: ClothingHeadHelmetVoidParamed - name: paramedic void helmet - description: A void helmet made for paramedics. - components: - - type: BreathMask - - type: Sprite - sprite: Clothing/Head/Helmets/paramedhelm.rsi - - type: Clothing - sprite: Clothing/Head/Helmets/paramedhelm.rsi - - type: TemperatureProtection - coefficient: 0.1 - - type: Armor - modifiers: - coefficients: - Heat: 0.90 - Radiation: 0.75 - #Ancient Void Helmet - type: entity parent: ClothingHeadEVAHelmetBase diff --git a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml index f1489b0ddd6..6985fe7ec39 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml @@ -156,6 +156,25 @@ Piercing: 0.9 Heat: 0.9 +#Paramedic Void Helmet +- type: entity + parent: ClothingHeadHardsuitBase + id: ClothingHeadHelmetHardsuitVoidParamed + name: paramedic void helmet + description: A void helmet made for paramedics. + components: + - type: BreathMask + - type: Sprite + sprite: Clothing/Head/Hardsuits/paramedhelm.rsi + - type: Clothing + sprite: Clothing/Head/Hardsuits/paramedhelm.rsi + - type: Armor + modifiers: + coefficients: + Heat: 0.90 + Radiation: 0.75 + + #Security Hardsuit - type: entity parent: ClothingHeadHardsuitWithLightBase diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml index 70ab3016469..ba889285a16 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml @@ -163,6 +163,38 @@ - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitSalvage +#Paramedic Voidsuit +- type: entity + parent: ClothingOuterHardsuitBase + id: ClothingOuterHardsuitVoidParamed + name: paramedic hardsuit + description: A hardsuit made for paramedics. + components: + - type: Sprite + sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi + - type: Clothing + sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi + - type: TemperatureProtection + coefficient: 0.1 + - type: PressureProtection + highPressureMultiplier: 0.5 + lowPressureMultiplier: 1000 + - type: Armor + modifiers: + coefficients: + Heat: 0.90 + Radiation: 0.75 + Caustic: 0.5 + - type: StealTarget + stealGroup: ClothingOuterHardsuitVoidParamed + - type: ClothingSpeedModifier + walkModifier: 0.9 + sprintModifier: 0.9 + - type: HeldSpeedModifier + - type: ToggleableClothing + clothingPrototype: ClothingHeadHelmetHardsuitVoidParamed + + - type: entity parent: ClothingOuterHardsuitBase id: ClothingOuterHardsuitMaxim diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/softsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/softsuits.yml index b81b3d1e7f0..115202813c7 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/softsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/softsuits.yml @@ -2,8 +2,8 @@ - type: entity parent: ClothingOuterEVASuitBase id: ClothingOuterHardsuitEVA - name: EVA suit - description: A lightweight space suit with the basic ability to protect the wearer from the vacuum of space during emergencies. + name: vacsuit + description: A lightweight vacsuit with the basic ability to protect the wearer from the vacuum of space during emergencies. components: - type: Sprite sprite: Clothing/OuterClothing/Suits/eva.rsi @@ -20,7 +20,7 @@ - type: entity parent: ClothingOuterEVASuitBase id: ClothingOuterHardsuitSyndicate # TODO: rename to ClothingOuterEVASuitSyndicate - name: syndicate EVA suit + name: syndicate vacsuit description: "Has a tag on the back that reads: 'Totally not property of an enemy corporation, honest!'" components: - type: Sprite @@ -38,8 +38,8 @@ - type: entity parent: ClothingOuterEVASuitBase id: ClothingOuterSuitEmergency - name: emergency EVA suit - description: An emergency EVA suit with a built-in helmet. It's horribly slow and lacking in temperature protection, but enough to bide you time from the harsh vaccuum of space. + name: emergency vacsuit + description: An emergency vacsuit with a built-in helmet. It's horribly slow and lacking in temperature protection, but enough to bide you time from the harsh vaccuum of space. components: - type: Sprite sprite: Clothing/OuterClothing/Suits/eva_emergency.rsi @@ -62,7 +62,7 @@ - type: entity parent: ClothingOuterEVASuitBase id: ClothingOuterHardsuitEVAPrisoner - name: prisoner EVA suit + name: prisoner vacsuit description: A lightweight space suit for prisoners to protect them from the vacuum of space during emergencies. components: - type: Sprite @@ -80,8 +80,8 @@ - type: entity parent: ClothingOuterEVASuitBase id: ClothingOuterHardsuitAncientEVA - name: NTSRA voidsuit #Nanotrasen Space Research Association - description: An ancient space suit, designed by the NTSRA branch of CentCom. It is very finely crafted, allowing for greater mobility than most modern space suits. + name: NTSRA vacsuit #Nanotrasen Space Research Association + description: An ancient vacsuit, designed by the NTSRA branch of CentCom. It is very finely crafted, allowing for greater mobility than most modern vacsuits. components: - type: Sprite sprite: Clothing/OuterClothing/Suits/ancient_voidsuit.rsi @@ -91,40 +91,3 @@ walkModifier: 0.85 sprintModifier: 0.85 - type: HeldSpeedModifier - -#Paramedic Voidsuit -#Despite having resistances and looking like a hardsuit, this parents off the EVA suit so it goes here. -- type: entity - parent: ClothingOuterEVASuitBase - id: ClothingOuterHardsuitVoidParamed - name: paramedic void suit - description: A void suit made for paramedics. - components: - - type: Sprite - sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi - - type: Clothing - sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi - - type: PressureProtection - highPressureMultiplier: 0.5 - lowPressureMultiplier: 1000 - - type: ClothingSpeedModifier - walkModifier: 0.9 - sprintModifier: 0.9 - - type: HeldSpeedModifier - - type: TemperatureProtection - coefficient: 0.1 - - type: Armor - modifiers: - coefficients: - Heat: 0.90 - Radiation: 0.75 - Caustic: 0.5 - - type: GroupExamine - - type: StealTarget - stealGroup: ClothingOuterHardsuitVoidParamed - - type: ToggleableClothing - clothingPrototype: ClothingHeadHelmetVoidParamed - slot: head - - type: ContainerContainer - containers: - toggleable-clothing: !type:ContainerSlot {} diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hardsuit-helmets.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hardsuit-helmets.yml index 6c96d3a56dd..1a83a14bd57 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hardsuit-helmets.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hardsuit-helmets.yml @@ -19,7 +19,7 @@ parent: ClothingHeadHelmetHardsuitSyndie id: ClothingHeadHelmetHardsuitSyndieReverseEngineered noSpawn: true - name: SA-123 combat hardsuit helmet + name: SA-122 combat hardsuit helmet description: An advanced hardsuit helmet designed for work in special operations. components: - type: Sprite @@ -31,7 +31,7 @@ parent: ClothingHeadHelmetHardsuitCybersun id: ClothingHeadHelmetHardsuitJuggernautReverseEngineered noSpawn: true - name: SA-127 combat hardsuit helmet + name: SA-126 combat hardsuit helmet description: An assault hardsuit helmet featuring a top-secret translucent polymer. components: - type: Sprite diff --git a/Resources/Prototypes/Objectives/stealTargetGroups.yml b/Resources/Prototypes/Objectives/stealTargetGroups.yml index e93c9c319da..59952784339 100644 --- a/Resources/Prototypes/Objectives/stealTargetGroups.yml +++ b/Resources/Prototypes/Objectives/stealTargetGroups.yml @@ -190,7 +190,7 @@ - type: stealTargetGroup id: ClothingOuterHardsuitVoidParamed - name: paramedic void suit + name: paramedic hardsuit sprite: sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi state: icon diff --git a/Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/equipped-HELMET.png b/Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/equipped-HELMET.png similarity index 100% rename from Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/equipped-HELMET.png rename to Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/equipped-HELMET.png diff --git a/Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/icon.png b/Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/icon.png similarity index 100% rename from Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/icon.png rename to Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/icon.png diff --git a/Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/inhand-left.png b/Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/inhand-left.png similarity index 100% rename from Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/inhand-left.png rename to Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/inhand-left.png diff --git a/Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/inhand-right.png b/Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/inhand-right.png similarity index 100% rename from Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/inhand-right.png rename to Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/inhand-right.png diff --git a/Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/meta.json b/Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/meta.json similarity index 95% rename from Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/meta.json rename to Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/meta.json index 4ec7339a888..a42fdeb8102 100644 --- a/Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/meta.json +++ b/Resources/Textures/Clothing/Head/Hardsuits/paramedhelm.rsi/meta.json @@ -1,26 +1,26 @@ -{ - "version": 1, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from paradise station at commit https://github.com/ParadiseSS13/Paradise/commit/e5e584804b4b0b373a6a69d23afb73fd3c094365, redrawn by Ubaser", - "size": { - "x": 32, - "y": 32 - }, - "states": [ - { - "name": "icon" - }, - { - "name": "equipped-HELMET", - "directions": 4 - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - } - ] -} +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from paradise station at commit https://github.com/ParadiseSS13/Paradise/commit/e5e584804b4b0b373a6a69d23afb73fd3c094365, redrawn by Ubaser", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-HELMET", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} From e23114ce58b7532800099b71947fba16ea29c7a8 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Mon, 12 Aug 2024 21:44:15 +0000 Subject: [PATCH 089/135] Automatic Changelog Update (#725) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 75cc34a090f..debbbbfe988 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5256,3 +5256,11 @@ Entries: message: Added showers id: 6256 time: '2024-08-12T16:46:05.0000000+00:00' +- author: gluesniffler + changes: + - type: Tweak + message: Changed hardsuit descriptions to be slightly less LRP. + - type: Tweak + message: Changed paramedic voidsuit from a softsuit to a hardsuit. + id: 6257 + time: '2024-08-12T21:43:52.0000000+00:00' From 2ae464e0693feb8aecf813070a13bb7b49d49006 Mon Sep 17 00:00:00 2001 From: stellar-novas Date: Mon, 12 Aug 2024 19:07:17 -0400 Subject: [PATCH 090/135] Nix Version Bump (#721) The bi-monthly nix version bump. Only impacts the nix users, which are me and @DEATHB4DEFEAT --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 7baaa468ea5..40a98aa9f96 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1717352157, - "narHash": "sha256-hbBzucWOhwxt3QzeAyUojtD6/aHH81JssDfhFfmqOy0=", + "lastModified": 1723382296, + "narHash": "sha256-55jPcSyBPG77QysozW12H0VA0E56PJYS+duYndDUNLg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "44f538ab12e2726af450877a5529f4fd88ddb0fb", + "rev": "a5d81094146e6b042c4e5f4c5e179c5c35c3ae28", "type": "github" }, "original": { From eb98bc86afa2148db0e15acf1edcab711df24dfc Mon Sep 17 00:00:00 2001 From: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:08:24 -0700 Subject: [PATCH 091/135] Fix Whitelist Requirements (#729) # Changelog :cl: - fix: Whitelist requirements work properly --- Resources/Prototypes/Roles/Antags/nukeops.yml | 2 +- Resources/Prototypes/Roles/Jobs/Command/captain.yml | 2 +- Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml | 2 +- Resources/Prototypes/Roles/Jobs/Security/warden.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Resources/Prototypes/Roles/Antags/nukeops.yml b/Resources/Prototypes/Roles/Antags/nukeops.yml index fe05393b9ca..26024b44b28 100644 --- a/Resources/Prototypes/Roles/Antags/nukeops.yml +++ b/Resources/Prototypes/Roles/Antags/nukeops.yml @@ -39,4 +39,4 @@ - !type:CharacterDepartmentTimeRequirement # DeltaV - Command dept time requirement department: Command min: 36000 # DeltaV - 10 hours - - !type:WhitelistRequirement # DeltaV - Whitelist requirement + - !type:CharacterWhitelistRequirement diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml index 12ad83e6e5c..d624b349d56 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml @@ -24,7 +24,7 @@ min: 108000 # DeltaV - 30 hours - !type:CharacterOverallTimeRequirement # DeltaV - Playtime requirement min: 108000 # 30 hours - - !type:WhitelistRequirement # DeltaV - Whitelist requirement + - !type:CharacterWhitelistRequirement weight: 20 startingGear: CaptainGear icon: "JobIconCaptain" diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index 675e7768fa7..46e018f35a8 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -15,7 +15,7 @@ min: 36000 # 10 hours - !type:CharacterOverallTimeRequirement min: 90000 # DeltaV - 25 hours - - !type:WhitelistRequirement # DeltaV - Whitelist requirement + - !type:CharacterWhitelistRequirement weight: 10 startingGear: HoSGear icon: "JobIconHeadOfSecurity" diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml index a4c5c5a8fab..82101373db2 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml @@ -10,7 +10,7 @@ - !type:CharacterPlaytimeRequirement # DeltaV - JobDetective time requirement. Give them an understanding of basic forensics. tracker: JobDetective min: 14400 # DeltaV - 4 hours - - !type:WhitelistRequirement # DeltaV - Whitelist requirement + - !type:CharacterWhitelistRequirement startingGear: WardenGear icon: "JobIconWarden" supervisors: job-supervisors-hos From 42a57938faf9a5e4f83cf8a4705b0c0268c3b7d4 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 13 Aug 2024 17:08:52 +0000 Subject: [PATCH 092/135] Automatic Changelog Update (#729) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index debbbbfe988..f8708b5992f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5264,3 +5264,9 @@ Entries: message: Changed paramedic voidsuit from a softsuit to a hardsuit. id: 6257 time: '2024-08-12T21:43:52.0000000+00:00' +- author: DEATHB4DEFEAT + changes: + - type: Fix + message: Whitelist requirements work properly + id: 6258 + time: '2024-08-13T17:08:24.0000000+00:00' From 90f56f412dfcb3651341540fee08e7e8e2405de0 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Wed, 14 Aug 2024 01:12:15 +0800 Subject: [PATCH 093/135] Oni Speech Update (#724) # Description This PR has updates surrounding Oni speech: a new speech bubble for Onis with horns, unique speech verbs, and a tweak to the Nekomimetic description to mention Onis. Notably, Onis will now have a **fully unique** speech (sound, speech bubble, verbs), improving how distinct they feel. #711 (Remove Or Rework Vulpkanin) triggered a discussion about how unique the species should be in EE. As an Oni main, I can't help but notice that Onis often feel like human reskins, practically being colorful humans with horns. This PR aims to be a step in the right direction to make Onis more aesthetically distinct from humans by changing the visuals of their speech. All that is left is to give them unique screams, preferably screams that sound rather *demonic*. Shoutout to @leonardo-dabepis who improved the chat bubble horns for me. I will impulsively put him in the changelog to give credit :trollface: ## Media **Speech Bubble** ![image](https://github.com/user-attachments/assets/71185797-40b9-437b-a360-7ffcac83705b)
See more **Speech Style** ![image](https://github.com/user-attachments/assets/67ef53f9-d713-40c4-a88f-903d7be4f55a) **Nekomimetic Description** ![image](https://github.com/user-attachments/assets/c3df58db-22d1-44a1-8f0c-84e879ad0c7f)
## Changelog :cl: Skubman and leonardo-dabepis - add: Onis now get a unique speech bubble, a black bubble with horns. - add: Onis have received a distinct speech style that reflects their strength. Hear them 'grunt', 'bellow', 'blare', and 'rumble' as they talk. - tweak: The Nekomimetic language description has been changed to mention Onis speaking it. --------- Signed-off-by: Angelo Fallaria Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- .../en-US/chat/managers/chat-manager.ftl | 6 ++++++ Resources/Locale/en-US/language/languages.ftl | 2 +- .../Nyanotrasen/Entities/Mobs/Species/Oni.yml | 3 +++ Resources/Prototypes/Voice/speech_verbs.yml | 11 +++++++++- Resources/Prototypes/typing_indicator.yml | 5 +++++ .../Textures/Effects/speech.rsi/meta.json | 19 +++++++++++++++++- .../Textures/Effects/speech.rsi/oni0.png | Bin 0 -> 715 bytes .../Textures/Effects/speech.rsi/oni1.png | Bin 0 -> 741 bytes .../Textures/Effects/speech.rsi/oni2.png | Bin 0 -> 742 bytes 9 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 Resources/Textures/Effects/speech.rsi/oni0.png create mode 100644 Resources/Textures/Effects/speech.rsi/oni1.png create mode 100644 Resources/Textures/Effects/speech.rsi/oni2.png diff --git a/Resources/Locale/en-US/chat/managers/chat-manager.ftl b/Resources/Locale/en-US/chat/managers/chat-manager.ftl index 6fbeb83ed41..589d79e6ea9 100644 --- a/Resources/Locale/en-US/chat/managers/chat-manager.ftl +++ b/Resources/Locale/en-US/chat/managers/chat-manager.ftl @@ -112,6 +112,12 @@ chat-speech-verb-vox-1 = screeches chat-speech-verb-vox-2 = shrieks chat-speech-verb-vox-3 = croaks +chat-speech-verb-name-oni = Oni +chat-speech-verb-oni-1 = grunts +chat-speech-verb-oni-2 = bellows +chat-speech-verb-oni-3 = blares +chat-speech-verb-oni-4 = rumbles + chat-speech-verb-name-canine = Canine chat-speech-verb-canine-1 = barks chat-speech-verb-canine-2 = woofs diff --git a/Resources/Locale/en-US/language/languages.ftl b/Resources/Locale/en-US/language/languages.ftl index 4b0c1248f28..68dc80f51da 100644 --- a/Resources/Locale/en-US/language/languages.ftl +++ b/Resources/Locale/en-US/language/languages.ftl @@ -11,7 +11,7 @@ language-RootSpeak-name = Rootspeak language-RootSpeak-description = The strange whistling-style language spoken by the Diona. language-Nekomimetic-name = Nekomimetic -language-Nekomimetic-description = To the casual observer, this language is an incomprehensible mess of broken Japanese. To the felinids, it's somehow comprehensible. +language-Nekomimetic-description = To the casual observer, this language is an incomprehensible mess of broken Japanese. To the Felinids and Oni, it's somehow comprehensible. language-Draconic-name = Draconic language-Draconic-description = The common language of lizard-people, composed of sibilant hisses and rattles. diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/Oni.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/Oni.yml index e93117b1aad..c1655287fdc 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/Oni.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Species/Oni.yml @@ -6,6 +6,7 @@ components: - type: Speech speechSounds: Baritone + speechVerb: Oni - type: HumanoidAppearance species: Oni - type: Sprite @@ -35,6 +36,8 @@ - MobLayer - type: Stamina critThreshold: 115 + - type: TypingIndicator + proto: oni - type: LanguageKnowledge speaks: - GalacticCommon diff --git a/Resources/Prototypes/Voice/speech_verbs.yml b/Resources/Prototypes/Voice/speech_verbs.yml index 9879cefb75d..3f0a4c10fce 100644 --- a/Resources/Prototypes/Voice/speech_verbs.yml +++ b/Resources/Prototypes/Voice/speech_verbs.yml @@ -1,4 +1,4 @@ -- type: speechVerb +- type: speechVerb id: Default name: chat-speech-verb-name-default speechVerbStrings: @@ -94,6 +94,15 @@ - chat-speech-verb-vox-2 - chat-speech-verb-vox-3 +- type: speechVerb + id: Oni + name: chat-speech-verb-name-oni + speechVerbStrings: + - chat-speech-verb-oni-1 + - chat-speech-verb-oni-2 + - chat-speech-verb-oni-3 + - chat-speech-verb-oni-4 + - type: speechVerb id: Plant name: chat-speech-verb-name-plant diff --git a/Resources/Prototypes/typing_indicator.yml b/Resources/Prototypes/typing_indicator.yml index 7271770ef50..7e8c92787fe 100644 --- a/Resources/Prototypes/typing_indicator.yml +++ b/Resources/Prototypes/typing_indicator.yml @@ -48,3 +48,8 @@ id: slime typingState: slime0 offset: 0, 0.125 + +- type: typingIndicator + id: oni + typingState: oni0 + offset: 0, 0.0625 diff --git a/Resources/Textures/Effects/speech.rsi/meta.json b/Resources/Textures/Effects/speech.rsi/meta.json index 98dd3b20607..1ec1219b0f8 100644 --- a/Resources/Textures/Effects/speech.rsi/meta.json +++ b/Resources/Textures/Effects/speech.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24 | Moth sprites made by PuroSlavKing (Github) | Spider sprites made by PixelTheKermit (Github) | Lizard sprites made by AmalgoMyte (Github)", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24 | Moth sprites made by PuroSlavKing (Github) | Spider sprites made by PixelTheKermit (Github) | Lizard sprites made by AmalgoMyte (Github) | Oni sprites made by angelofallars and leonardo-dabepis (Github)", "states": [ { "name": "alien0", @@ -422,6 +422,23 @@ 0.4 ] ] + }, + { + "name": "oni0", + "delays": [ + [ + 0.2, + 0.3, + 0.3, + 0.5 + ] + ] + }, + { + "name": "oni1" + }, + { + "name": "oni2" } ] } diff --git a/Resources/Textures/Effects/speech.rsi/oni0.png b/Resources/Textures/Effects/speech.rsi/oni0.png new file mode 100644 index 0000000000000000000000000000000000000000..cae529b35c2cf0ab1fa384fcfda2e626e327f52c GIT binary patch literal 715 zcmV;+0yO=JP)EX>4Tx04R}tkv&MmKpe$iQ%j3f9PA+CkfA!+MMWHI6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIZ5n$?#CG~G6{ z>6Dl+tcu}RL=c655W+IEj5$flz;}GzBf!_Y1kdt6_vaW;ixvX{B5{%#rcJy-JhN#V zocD=itRkz#=fo2xU6A;Z>x##3oXai?JTqqIvh&0-VzJ!AN)NM&sS!^T$5loiA^#v+y=L4<+^s;I$6f>xar3t8Gv`S?d%zeFyDTvae~ zET9ezvg-%`gWug+rKw3TDVhR8FOKsu284HkcGGdbj~%Cd0tBCdE4}Nlw}9DC(wki^ zegq6|0~gm_P1yr3cYxt1LpEhs3eprxCE)#xzNr8V-2(kX!oIU_K>MC;s92^4U zWy)Und3U6@w|~!c`uhR$&~kHCs7&wx009F@L_t(|+U?rW4TB&M#_`km*iE`X;~LK4 zG|u4~gaO)39H0-i4WVkOkvn4kzr;7mRX)mk%DjfBt@Sqb@#@R5-um5~$uBB*}UrS+z zVYq7M6*mBV-#;|-s`y)6*@PyglR!N`J_c{jxz91QwJGJ=3ykv@XXKvo53uxn5$o^* z@&Nz<00000oDlT^DX0(7Ta9Y@)CYv4PJO^{=dTZV-_L8`)34>{?nih%?h}?^&dtyy xpZb9K8>2qpdq$`aDBw38000000000E@dQjOu6&_V?cD$X002ovPDHLkV1nCON45X} literal 0 HcmV?d00001 diff --git a/Resources/Textures/Effects/speech.rsi/oni1.png b/Resources/Textures/Effects/speech.rsi/oni1.png new file mode 100644 index 0000000000000000000000000000000000000000..03da318f1d915f3b705706ef3cd097e7e4c623aa GIT binary patch literal 741 zcmVEX>4Tx04R}tkv&MmKpe$iQ%j3f9PA+CkfA!+MMWHI6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIZ5n$?#CG~G6{ z>6Dl+tcu}RL=c655W+IEj5$flz;}GzBf!_Y1kdt6_vaW;ixvX{B5{%#rcJy-JhN#V zocD=itRkz#=fo2xU6A;Z>x##3oXai?JTqqIvh&0-VzJ!AN)NM&sS!^T$5loiA^#v+y=L4<+^s;I$6f>xar3t8Gv`S?d%zeFyDTvae~ zET9ezvg-%`gWug+rKw3TDVhR8FOKsu284HkcGGdbj~%Cd0tBCdE4}Nlw}9DC(wki^ zegq6|0~gm_P1yr3cYxt1LpEhs3eprxCE)#xzNr8V-2(kX!oIU_K>MC;s92^4U zWy)Und3U6@w|~!c`uhR$&~kHCs7&wx00A9IL_t(|+U?ri34<^chT&uJvYWU-IcsDN zcM&p&Ye)uYH|YSqs6w=AEf|m0_W|z$F<*WZPDI{9`^;I==I>lYB-C}isBznF^$>pS ze^vR!Ob^}Upz=6f=Uh#$MNG$BR$dyvJm-VNS+Uxlv%)a-&=t5`%NV*lq1|Nrz>JS`NRaFtMfTOy|$z{VYz{DY#eEC~#fo$$G z*oCoG08=5P8vGJLRqs}RfT}vXDmDwjvhzIz0000000000$6{HZx9EX>4Tx04R}tkv&MmKpe$iQ%j3f9PA+CkfA!+MMWHI6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIZ5n$?#CG~G6{ z>6Dl+tcu}RL=c655W+IEj5$flz;}GzBf!_Y1kdt6_vaW;ixvX{B5{%#rcJy-JhN#V zocD=itRkz#=fo2xU6A;Z>x##3oXai?JTqqIvh&0-VzJ!AN)NM&sS!^T$5loiA^#v+y=L4<+^s;I$6f>xar3t8Gv`S?d%zeFyDTvae~ zET9ezvg-%`gWug+rKw3TDVhR8FOKsu284HkcGGdbj~%Cd0tBCdE4}Nlw}9DC(wki^ zegq6|0~gm_P1yr3cYxt1LpEhs3eprxCE)#xzNr8V-2(kX!oIU_K>MC;s92^4U zWy)Und3U6@w|~!c`uhR$&~kHCs7&wx00ACJL_t(|+U?ri4Z;Ph*_9` zNt+TY;GVg+i)@83sHMS&@3$U!db%707*qoM6N<$g5dE-uK)l5 literal 0 HcmV?d00001 From 079e9787de25151d1cd41cd806d97e7013d067e4 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 13 Aug 2024 17:12:42 +0000 Subject: [PATCH 094/135] Automatic Changelog Update (#724) --- Resources/Changelog/Changelog.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f8708b5992f..164bbbb316f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5270,3 +5270,17 @@ Entries: message: Whitelist requirements work properly id: 6258 time: '2024-08-13T17:08:24.0000000+00:00' +- author: Skubman and leonardo-dabepis + changes: + - type: Add + message: Onis now get a unique speech bubble, a black bubble with horns. + - type: Add + message: >- + Onis have received a distinct speech style that reflects their strength. + Hear them 'grunt', 'bellow', 'blare', and 'rumble' as they talk. + - type: Tweak + message: >- + The Nekomimetic language description has been changed to mention Onis + speaking it. + id: 6259 + time: '2024-08-13T17:12:15.0000000+00:00' From 666e820aedf209758f3773ecff4559a83242d035 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:16:51 +0200 Subject: [PATCH 095/135] Plushie Update! (#654) # Description By multiple requests i bring my PR from Frontier The [PLUSHIE UPDATE!](https://github.com/new-frontiers-14/frontier-station-14/pull/886) This PR add a prize vendor machine where you can trade prize ticket for a toy/plushie, to get ticket you win those in arcade machines. This PR will give a chance for everyone to get the toys they need in a special machine and will make plushies in general more random and fun, in term of random spawns. WARNING THIS PR DOES NOT MAP THE PRIZE VENDOR AND WILL MOSTLY NEED TO BE MAPPED. --- # TODO - [x] Prize Vendor - [x] Prize Tickets - [x] New Toys/Plushies - [x] Prizes ---

Media

![image](https://github.com/user-attachments/assets/643e6c65-bba0-4eef-8e8e-d3510922e51e)

--- # Changelog :cl: - add: A ton of new plushies has arrived - add: Prize counter are here, get your prizes by winning games and getting prize tickets! and find prize balls!! --- Resources/Audio/Effects/silence.ogg | Bin 0 -> 4181 bytes Resources/Migrations/eeMigration.yml | 3 + .../Prototypes/Catalog/Cargo/cargo_fun.yml | 20 - .../Prototypes/Catalog/Fills/Crates/fun.yml | 47 -- .../Entities/Markers/Spawners/Random/toy.yml | 32 + .../Entities/Objects/Fun/prizeticket.yml | 395 +++++++++ .../Entities/Objects/Fun/puppet.yml | 89 +++ .../Prototypes/Entities/Objects/Fun/toys.yml | 390 +++++++++ .../Structures/Machines/Computers/arcades.yml | 68 +- .../Entities/Structures/Machines/lathe.yml | 138 ++++ .../Entities/Objects/Specific/Mail/mail.yml | 145 +++- .../Reagents/Materials/prizeticket.yml | 6 + .../Recipes/Lathes/prizecounter.yml | 729 +++++++++++++++++ Resources/Prototypes/Stacks/prizeticket.yml | 7 + Resources/Prototypes/tags.yml | 3 + .../Objects/Fun/catplushie.rsi/black.png | Bin 0 -> 250 bytes .../Objects/Fun/catplushie.rsi/grey.png | Bin 0 -> 250 bytes .../Objects/Fun/catplushie.rsi/meta.json | 32 + .../Objects/Fun/catplushie.rsi/orange.png | Bin 0 -> 585 bytes .../Objects/Fun/catplushie.rsi/siames.png | Bin 0 -> 658 bytes .../Objects/Fun/catplushie.rsi/tabby.png | Bin 0 -> 539 bytes .../Objects/Fun/catplushie.rsi/tuxedo.png | Bin 0 -> 280 bytes .../Objects/Fun/catplushie.rsi/white.png | Bin 0 -> 250 bytes .../Objects/Fun/corgiplushie.rsi/corgi.png | Bin 0 -> 394 bytes .../Fun/corgiplushie.rsi/girlycorgi.png | Bin 0 -> 412 bytes .../Objects/Fun/corgiplushie.rsi/meta.json | 20 + .../Fun/corgiplushie.rsi/robotcorgi.png | Bin 0 -> 391 bytes .../Objects/Fun/foxplushie.rsi/black.png | Bin 0 -> 1201 bytes .../Objects/Fun/foxplushie.rsi/blue.png | Bin 0 -> 936 bytes .../Objects/Fun/foxplushie.rsi/coffee.png | Bin 0 -> 1046 bytes .../Objects/Fun/foxplushie.rsi/crimson.png | Bin 0 -> 927 bytes .../Objects/Fun/foxplushie.rsi/marble.png | Bin 0 -> 1089 bytes .../Objects/Fun/foxplushie.rsi/meta.json | 38 + .../Objects/Fun/foxplushie.rsi/orange.png | Bin 0 -> 939 bytes .../Objects/Fun/foxplushie.rsi/pink.png | Bin 0 -> 936 bytes .../Objects/Fun/foxplushie.rsi/purple.png | Bin 0 -> 942 bytes .../Objects/Fun/foxplushie.rsi/red.png | Bin 0 -> 1408 bytes .../Textures/Objects/Fun/petrock.rsi/fred.png | Bin 0 -> 204 bytes .../Objects/Fun/petrock.rsi/meta.json | 20 + .../Textures/Objects/Fun/petrock.rsi/rock.png | Bin 0 -> 195 bytes .../Objects/Fun/petrock.rsi/roxie.png | Bin 0 -> 231 bytes .../Objects/Fun/prizeticket.rsi/meta.json | 26 + .../Objects/Fun/prizeticket.rsi/prizeball.png | Bin 0 -> 732 bytes .../Objects/Fun/prizeticket.rsi/ticket.png | Bin 0 -> 201 bytes .../Objects/Fun/prizeticket.rsi/ticket_2.png | Bin 0 -> 296 bytes .../Objects/Fun/prizeticket.rsi/ticket_3.png | Bin 0 -> 361 bytes .../Objects/Fun/prizeticket.rsi/ticket_4.png | Bin 0 -> 188 bytes .../Objects/Fun/toys.rsi/abductor.png | Bin 0 -> 245 bytes .../Objects/Fun/toys.rsi/abductor_agent.png | Bin 0 -> 333 bytes .../Textures/Objects/Fun/toys.rsi/deer.png | Bin 0 -> 787 bytes .../Textures/Objects/Fun/toys.rsi/gnome.png | Bin 0 -> 330 bytes .../Textures/Objects/Fun/toys.rsi/grey.png | Bin 0 -> 389 bytes .../Textures/Objects/Fun/toys.rsi/ipc.png | Bin 0 -> 335 bytes .../Objects/Fun/toys.rsi/loveable.png | Bin 0 -> 373 bytes .../Textures/Objects/Fun/toys.rsi/meta.json | 747 +++++++++--------- .../Objects/Fun/toys.rsi/plushie_jester.png | Bin 0 -> 585 bytes .../Objects/Fun/toys.rsi/plushie_slips.png | Bin 0 -> 462 bytes .../Objects/Fun/toys.rsi/plushie_trystan.png | Bin 0 -> 1108 bytes .../Objects/Fun/toys.rsi/plushie_vulp.png | Bin 0 -> 1033 bytes .../rock_carrier.rsi/box-inhand-left.png | Bin 0 -> 563 bytes .../rock_carrier.rsi/box-inhand-right.png | Bin 0 -> 632 bytes .../Happyhonk/rock_carrier.rsi/box-open.png | Bin 0 -> 2925 bytes .../Happyhonk/rock_carrier.rsi/box.png | Bin 0 -> 3009 bytes .../Happyhonk/rock_carrier.rsi/meta.json | 25 + .../Machines/prizecounter.rsi/icon.png | Bin 0 -> 817 bytes .../Machines/prizecounter.rsi/meta.json | 20 + .../Machines/prizecounter.rsi/panel.png | Bin 0 -> 179 bytes .../Machines/prizecounter.rsi/unlit.png | Bin 0 -> 444 bytes 68 files changed, 2489 insertions(+), 511 deletions(-) create mode 100644 Resources/Audio/Effects/silence.ogg create mode 100644 Resources/Migrations/eeMigration.yml create mode 100644 Resources/Prototypes/Entities/Objects/Fun/prizeticket.yml create mode 100644 Resources/Prototypes/Reagents/Materials/prizeticket.yml create mode 100644 Resources/Prototypes/Recipes/Lathes/prizecounter.yml create mode 100644 Resources/Prototypes/Stacks/prizeticket.yml create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/black.png create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/grey.png create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/meta.json create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/orange.png create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/siames.png create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/tabby.png create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/tuxedo.png create mode 100644 Resources/Textures/Objects/Fun/catplushie.rsi/white.png create mode 100644 Resources/Textures/Objects/Fun/corgiplushie.rsi/corgi.png create mode 100644 Resources/Textures/Objects/Fun/corgiplushie.rsi/girlycorgi.png create mode 100644 Resources/Textures/Objects/Fun/corgiplushie.rsi/meta.json create mode 100644 Resources/Textures/Objects/Fun/corgiplushie.rsi/robotcorgi.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/black.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/blue.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/coffee.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/crimson.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/marble.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/meta.json create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/orange.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/pink.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/purple.png create mode 100644 Resources/Textures/Objects/Fun/foxplushie.rsi/red.png create mode 100644 Resources/Textures/Objects/Fun/petrock.rsi/fred.png create mode 100644 Resources/Textures/Objects/Fun/petrock.rsi/meta.json create mode 100644 Resources/Textures/Objects/Fun/petrock.rsi/rock.png create mode 100644 Resources/Textures/Objects/Fun/petrock.rsi/roxie.png create mode 100644 Resources/Textures/Objects/Fun/prizeticket.rsi/meta.json create mode 100644 Resources/Textures/Objects/Fun/prizeticket.rsi/prizeball.png create mode 100644 Resources/Textures/Objects/Fun/prizeticket.rsi/ticket.png create mode 100644 Resources/Textures/Objects/Fun/prizeticket.rsi/ticket_2.png create mode 100644 Resources/Textures/Objects/Fun/prizeticket.rsi/ticket_3.png create mode 100644 Resources/Textures/Objects/Fun/prizeticket.rsi/ticket_4.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/abductor.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/abductor_agent.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/deer.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/gnome.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/grey.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/ipc.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/loveable.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/plushie_jester.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/plushie_slips.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/plushie_trystan.png create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/plushie_vulp.png create mode 100644 Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/box-inhand-left.png create mode 100644 Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/box-inhand-right.png create mode 100644 Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/box-open.png create mode 100644 Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/box.png create mode 100644 Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/meta.json create mode 100644 Resources/Textures/Structures/Machines/prizecounter.rsi/icon.png create mode 100644 Resources/Textures/Structures/Machines/prizecounter.rsi/meta.json create mode 100644 Resources/Textures/Structures/Machines/prizecounter.rsi/panel.png create mode 100644 Resources/Textures/Structures/Machines/prizecounter.rsi/unlit.png diff --git a/Resources/Audio/Effects/silence.ogg b/Resources/Audio/Effects/silence.ogg new file mode 100644 index 0000000000000000000000000000000000000000..91738108486ed65c60563112099c3c036aab1eba GIT binary patch literal 4181 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 S@Na+rEraqO5^{C_x9Oi>d^^Yh literal 0 HcmV?d00001 diff --git a/Resources/Migrations/eeMigration.yml b/Resources/Migrations/eeMigration.yml new file mode 100644 index 00000000000..26713f6cbac --- /dev/null +++ b/Resources/Migrations/eeMigration.yml @@ -0,0 +1,3 @@ +# 2024-06-08 +CrateFunPlushie: CrateFunToyBox +CrateFunLizardPlushieBulk: CrateFunToyBox diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml b/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml index 61085f13b94..68bb4a6b849 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_fun.yml @@ -88,26 +88,6 @@ category: cargoproduct-category-name-fun group: market -- type: cargoProduct - id: FunPlushies - icon: - sprite: Objects/Fun/toys.rsi - state: plushie_h - product: CrateFunPlushie - cost: 1000 - category: cargoproduct-category-name-fun - group: market - -- type: cargoProduct - id: FunLizardPlushies - icon: - sprite: Objects/Fun/toys.rsi - state: plushie_lizard - product: CrateFunLizardPlushieBulk - cost: 500 - category: cargoproduct-category-name-fun - group: market - - type: cargoProduct id: FunBoardGames icon: diff --git a/Resources/Prototypes/Catalog/Fills/Crates/fun.yml b/Resources/Prototypes/Catalog/Fills/Crates/fun.yml index 28c5ea8dd47..b55bdd48322 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/fun.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/fun.yml @@ -1,50 +1,3 @@ -- type: entity - id: CrateFunPlushie - parent: CrateGenericSteel - name: plushie crate - description: A buncha soft plushies. Throw them around and then wonder how you're gonna explain this purchase to NT. - components: - - type: StorageFill - contents: - - id: PlushieBee - - id: PlushieNar - - id: PlushieCarp - - id: PlushieNuke - - id: PlushieSlime - - id: PlushieSnake - - id: PlushieLizard - - id: PlushieSpaceLizard - - id: PlushieVox - - id: PlushieRouny - - id: PlushieRatvar - - id: PlushieSharkBlue - orGroup: PlushieShark - - id: PlushieSharkGrey - orGroup: PlushieShark - - id: PlushieAtmosian - - id: PlushieDiona - - id: PlushieXeno - - id: PlushieHampter - - id: PlushieMoth - - id: PlushieMothRandom # Nyanotrasen - Random Moth Plushies - amount: 2 - - id: PlushieArachind - - id: PlushiePenguin - - id: PlushieArachne - -- type: entity - id: CrateFunLizardPlushieBulk - parent: CrateGenericSteel - name: bulk lizard plushie crate - description: A buncha soft lizard plushies. Throw them around and then wonder how you're gonna explain this purchase to NT. - components: - - type: StorageFill - contents: - - id: PlushieLizard - amount: 3 - - id: PlushieSpaceLizard - amount: 2 - - type: entity id: CrateFunInstrumentsVariety parent: CrateGenericSteel diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/toy.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/toy.yml index d12b85cde41..96b5f7aa8c5 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/toy.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/toy.yml @@ -12,6 +12,7 @@ rarePrototypes: - FoamBlade - PlushieGhost + - PlushieAbductorAgent rareChance: 0.03 prototypes: - PlushieBee @@ -37,6 +38,37 @@ - PlushieMothRandom # Nyanotrasen Random Moth Plushies - PlushieArachind - PlushieArachne + - PlushieAbductor + - PlushieGnome + - PlushieLoveable + - PlushieDeer + - PlushieIpc + - PlushieGrey + - PlushieRedFox + - PlushiePurpleFox + - PlushiePinkFox + - PlushieOrangeFox + - PlushieMarbleFox + - PlushieCrimsonFox + - PlushieCoffeeFox + - PlushieBlueFox + - PlushieBlackFox + - PlushieVulp + - PlushieCorgi + - PlushieGirlyCorgi + - PlushieRobotCorgi + - PlushieCatBlack + - PlushieCatGrey + - PlushieCatOrange + - PlushieCatSiames + - PlushieCatTabby + - PlushieCatTuxedo + - PlushieCatWhite + - PlushieRatvar + - PlushieNar + - PlushieTrystan + - PlushieSlips + - PlushieJester chance: 0.5 offset: 0.2 diff --git a/Resources/Prototypes/Entities/Objects/Fun/prizeticket.yml b/Resources/Prototypes/Entities/Objects/Fun/prizeticket.yml new file mode 100644 index 00000000000..695e45a2e64 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Fun/prizeticket.yml @@ -0,0 +1,395 @@ +- type: entity + abstract: true + parent: BaseItem + id: PrizeTicketBase + description: A prize ticket, ready to be redeemed at a prize counter. + components: + - type: Sprite + sprite: Objects/Fun/prizeticket.rsi + - type: Item + sprite: Objects/Fun/prizeticket.rsi + size: Tiny + - type: StaticPrice + price: 0 + - type: Tag + tags: + - Sheet + - PrizeTicket + +- type: entity + parent: PrizeTicketBase + id: PrizeTicket + name: prize ticket + suffix: Full + components: + - type: Material + - type: PhysicalComposition + materialComposition: + PrizeTicket: 1 + - type: Stack + count: 100 + stackType: PrizeTicket + baseLayer: base + layerStates: + - ticket + - ticket_2 + - ticket_3 + - ticket_4 + - type: Sprite + state: ticket_4 + layers: + - state: ticket_4 + map: ["base"] + - type: Item + heldPrefix: prize ticket + - type: Appearance + +- type: entity + parent: PrizeTicket + id: PrizeTicket10 + name: prize ticket + suffix: 10 + components: + - type: Sprite + state: ticket + - type: Stack + stackType: PrizeTicket + count: 10 + +- type: entity + parent: PrizeTicket + id: PrizeTicket30 + name: prize ticket + suffix: 30 + components: + - type: Sprite + state: ticket + - type: Stack + stackType: PrizeTicket + count: 30 + +- type: entity + parent: PrizeTicket + id: PrizeTicket60 + name: prize ticket + suffix: 60 + components: + - type: Sprite + state: ticket + - type: Stack + stackType: PrizeTicket + count: 60 + +- type: entity + parent: PrizeTicket + id: PrizeTicket1 + name: prize ticket + suffix: Single + components: + - type: Sprite + state: ticket + - type: Stack + stackType: PrizeTicket + count: 1 + +- type: entity + parent: PresentRandom + id: PrizeBall + name: prize ball + description: I wounder whats inside! + components: + - type: Sprite + sprite: Objects/Fun/prizeticket.rsi + layers: + - state: prizeball + - type: SpawnItemsOnUse + items: + - id: PresentTrash + - id: PrizeTicket10 + orGroup: Prize + # Common + - id: PrizeTicket30 + prob: 0.80 + orGroup: Prize + - id: PlushieMothRandom + prob: 0.80 + orGroup: Prize + - id: PlushieMothMusician + prob: 0.80 + orGroup: Prize + - id: PlushieMothBartender + prob: 0.80 + orGroup: Prize + - id: PlushieBee + prob: 0.80 + orGroup: Prize + - id: PlushieHampter + prob: 0.80 + orGroup: Prize + - id: PlushieRouny + prob: 0.80 + orGroup: Prize + - id: PlushieLamp + prob: 0.80 + orGroup: Prize + - id: PlushieArachind + prob: 0.80 + orGroup: Prize + - id: PlushieLizard + prob: 0.80 + orGroup: Prize + - id: PlushieLizardMirrored + prob: 0.80 + orGroup: Prize + - id: PlushieSpaceLizard + prob: 0.80 + orGroup: Prize + - id: PlushieDiona + prob: 0.80 + orGroup: Prize + - id: PlushieSharkBlue + prob: 0.80 + orGroup: Prize + - id: PlushieSharkPink + prob: 0.80 + orGroup: Prize + - id: PlushieSharkGrey + prob: 0.80 + orGroup: Prize + - id: PlushieCarp + prob: 0.80 + orGroup: Prize + - id: PlushieMagicarp + prob: 0.80 + orGroup: Prize + - id: PlushieHolocarp + prob: 0.80 + orGroup: Prize + - id: PlushieSlime + prob: 0.80 + orGroup: Prize + - id: PlushieSnake + prob: 0.80 + orGroup: Prize + - id: ToyMouse + prob: 0.80 + orGroup: Prize + - id: ToyRubberDuck + prob: 0.80 + orGroup: Prize + - id: PlushieVox + prob: 0.80 + orGroup: Prize + - id: PlushieAtmosian + prob: 0.80 + orGroup: Prize + - id: PlushiePenguin + prob: 0.80 + orGroup: Prize + - id: PlushieHuman + prob: 0.80 + orGroup: Prize + - id: PlushieArachne + prob: 0.80 + orGroup: Prize + - id: PlushieGnome + prob: 0.80 + orGroup: Prize + - id: PlushieLoveable + prob: 0.80 + orGroup: Prize + - id: PlushieDeer + prob: 0.80 + orGroup: Prize + - id: PlushieIpc + prob: 0.80 + orGroup: Prize + - id: PlushieGrey + prob: 0.80 + orGroup: Prize + - id: PlushieRedFox + prob: 0.80 + orGroup: Prize + - id: PlushiePurpleFox + prob: 0.80 + orGroup: Prize + - id: PlushiePinkFox + prob: 0.80 + orGroup: Prize + - id: PlushieOrangeFox + prob: 0.80 + orGroup: Prize + - id: PlushieMarbleFox + prob: 0.80 + orGroup: Prize + - id: PlushieCrimsonFox + prob: 0.80 + orGroup: Prize + - id: PlushieCoffeeFox + prob: 0.80 + orGroup: Prize + - id: PlushieBlueFox + prob: 0.80 + orGroup: Prize + - id: PlushieBlackFox + prob: 0.80 + orGroup: Prize + - id: PlushieVulp + prob: 0.80 + orGroup: Prize + - id: PlushieCorgi + prob: 0.80 + orGroup: Prize + - id: PlushieGirlyCorgi + prob: 0.80 + orGroup: Prize + - id: PlushieRobotCorgi + prob: 0.80 + orGroup: Prize + - id: PlushieCatBlack + prob: 0.80 + orGroup: Prize + - id: PlushieCatGrey + prob: 0.80 + orGroup: Prize + - id: PlushieCatOrange + prob: 0.80 + orGroup: Prize + - id: PlushieCatSiames + prob: 0.80 + orGroup: Prize + - id: PlushieCatTabby + prob: 0.80 + orGroup: Prize + - id: PlushieCatTuxedo + prob: 0.80 + orGroup: Prize + - id: PlushieCatWhite + prob: 0.80 + orGroup: Prize + - id: ToyAi + prob: 0.80 + orGroup: Prize + - id: ToyIan + prob: 0.80 + orGroup: Prize + - id: BalloonNT + prob: 0.80 + orGroup: Prize + - id: BalloonCorgi + prob: 0.80 + orGroup: Prize + - id: CrayonBox + prob: 0.80 + orGroup: Prize + - id: BasePetRock + prob: 0.80 + orGroup: Prize + # Uncommon + - id: PrizeTicket60 + prob: 0.50 + orGroup: Prize + - id: PlushieGhost + prob: 0.50 + orGroup: Prize + - id: PlushieRGBee + prob: 0.50 + orGroup: Prize + - id: PlushieRatvar + prob: 0.50 + orGroup: Prize + - id: PlushieNar + prob: 0.50 + orGroup: Prize + - id: PlushieRainbowCarp + prob: 0.50 + orGroup: Prize + - id: PlushieXeno + prob: 0.50 + orGroup: Prize + - id: PlushieJester + prob: 0.50 + orGroup: Prize + - id: PlushieSlips + prob: 0.50 + orGroup: Prize + - id: PlushieAbductor + prob: 0.50 + orGroup: Prize + - id: PlushieTrystan + prob: 0.50 + orGroup: Prize + - id: FoamCrossbow + prob: 0.50 + orGroup: Prize + - id: RevolverCapGun + prob: 0.50 + orGroup: Prize + - id: PonderingOrb + prob: 0.50 + orGroup: Prize + - id: ToyAmongPequeno + prob: 0.50 + orGroup: Prize + - id: FoamCutlass + prob: 0.50 + orGroup: Prize + - id: ToyHammer + prob: 0.50 + orGroup: Prize + - id: WhoopieCushion + prob: 0.50 + orGroup: Prize + - id: PlasticBanana + prob: 0.50 + orGroup: Prize + - id: WeaponWaterPistol + prob: 0.50 + orGroup: Prize + - id: WeaponWaterBlaster + prob: 0.50 + orGroup: Prize + - id: NewtonCradle + prob: 0.50 + orGroup: Prize + - id: SnapPopBox + prob: 0.50 + orGroup: Prize + - id: CrazyGlue + prob: 0.50 + orGroup: Prize + - id: MrChips + prob: 0.50 + orGroup: Prize + - id: MrDips + prob: 0.50 + orGroup: Prize + # Rare + - id: PlushieAbductorAgent + prob: 0.30 + orGroup: Prize + - id: PlushieNuke + prob: 0.30 + orGroup: Prize + - id: ToyNuke + prob: 0.30 + orGroup: Prize + - id: FoamBlade + prob: 0.30 + orGroup: Prize + - id: BalloonSyn + prob: 0.30 + orGroup: Prize + - id: SingularityToy + prob: 0.30 + orGroup: Prize + - id: TeslaToy + prob: 0.30 + orGroup: Prize + - id: ToySword + prob: 0.30 + orGroup: Prize + - id: ThronglerToy + prob: 0.30 + orGroup: Prize + \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Fun/puppet.yml b/Resources/Prototypes/Entities/Objects/Fun/puppet.yml index 01a15d2e5bd..068039e0c56 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/puppet.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/puppet.yml @@ -40,3 +40,92 @@ sprite: Objects/Fun/mrdips.rsi layers: - state: icon + +## PET ROCK! + +- type: entity + id: PetRockCarrier + parent: HappyHonk + name: pet rock carrier + description: Your new and only best friend home! + components: + - type: Sprite + sprite: Objects/Storage/Happyhonk/rock_carrier.rsi + state: box + - type: Item + sprite: Objects/Storage/Happyhonk/rock_carrier.rsi + heldPrefix: box + - type: StorageFill + contents: + - id: PetRock + prob: 0.8 + orGroup: Rock + - id: PetRockFred + prob: 0.1 + orGroup: Rock + - id: PetRockRoxie + prob: 0.1 + orGroup: Rock + +- type: entity + parent: [BaseItem, MrChips] + id: BasePetRock + name: pet rock + description: Your new and only best friend! + abstract: true + components: + - type: DamageOnLand + damage: + types: + Blunt: 1 + - type: DamageOtherOnHit + damage: + types: + Blunt: 1 + - type: Damageable + damageContainer: Inorganic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 10 + behaviors: + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/break_stone.ogg + - !type:SpawnEntitiesBehavior + spawn: + Ash: + min: 1 + max: 1 + - !type:DoActsBehavior + acts: [ "Destruction" ] + +- type: entity + parent: BasePetRock + id: PetRock + components: + - type: Sprite + sprite: Objects/Fun/petrock.rsi + layers: + - state: rock + +- type: entity + parent: BasePetRock + id: PetRockFred + name: fred + components: + - type: Sprite + sprite: Objects/Fun/petrock.rsi + layers: + - state: fred + +- type: entity + parent: BasePetRock + id: PetRockRoxie + name: roxie + components: + - type: Sprite + sprite: Objects/Fun/petrock.rsi + layers: + - state: roxie \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index 66d6713fb22..1fea59a926c 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -819,6 +819,368 @@ useSound: path: /Audio/Voice/Moth/moth_chitter.ogg +- type: entity + parent: BasePlushie + id: PlushieJester #Weh! + name: jester plushie + description: A dubious little creature getting up to mischief. + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: plushie_jester + +- type: entity + parent: BasePlushie + id: PlushieSlips + name: janitor plushie + description: The silent cleaner, the one that you dont hear say "Weh"! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: plushie_slips + - type: EmitSoundOnUse + sound: + path: /Audio/Effects/silence.ogg + - type: EmitSoundOnLand + sound: + path: /Audio/Effects/silence.ogg + - type: EmitSoundOnActivate + sound: + path: /Audio/Effects/silence.ogg + - type: MeleeWeapon + soundHit: + path: /Audio/Effects/silence.ogg + - type: Tag + tags: + - Soap + - type: Slippery + paralyzeTime: 0.7 + launchForwardsMultiplier: 0.5 + - type: StepTrigger + intersectRatio: 0.2 + - type: CollisionWake + enabled: false + - type: Physics + bodyType: Dynamic + - type: Fixtures + fixtures: + slips: + shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" + layer: + - SlipLayer + hard: false + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" + density: 10 + mask: + - ItemMask + +- type: entity + parent: BasePlushie + id: PlushieGnome + name: gnome plushie + description: A stuffed toy that resembles a gnome! or a drawf... + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: gnome + +- type: entity + parent: BasePlushie + id: PlushieLoveable + name: loveable plushie + description: A stuffed toy that resembles... a creature. + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: loveable + +- type: entity + parent: BasePlushie + id: PlushieDeer + name: deer plushie + description: A stuffed toy that resembles a deer! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: deer + +- type: entity + parent: BasePlushie + id: PlushieIpc + name: ipc plushie + description: A stuffed toy that resembles a ipc! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: ipc + +- type: entity + parent: BasePlushie + id: PlushieGrey + name: grey plushie + description: A stuffed toy that resembles a grey! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: grey + +- type: entity + parent: BasePlushie + id: PlushieAbductor + name: abductor plushie + description: A stuffed toy that resembles an abductor! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: abductor + +- type: entity + parent: BasePlushie + id: PlushieAbductorAgent + name: abductor agent plushie + description: A stuffed toy that resembles an abductor agent! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: abductor_agent + +- type: entity + parent: BasePlushie + id: PlushieRedFox + name: red fox plushie + description: A cute plushie that look like a red foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: red + +- type: entity + parent: BasePlushie + id: PlushiePurpleFox + name: purple fox plushie + description: A cute plushie that look like a purple foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: purple + +- type: entity + parent: BasePlushie + id: PlushiePinkFox + name: pink fox plushie + description: A cute plushie that look like a pink foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: pink + +- type: entity + parent: BasePlushie + id: PlushieOrangeFox + name: orange fox plushie + description: A cute plushie that look like a orange foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: orange + +- type: entity + parent: BasePlushie + id: PlushieMarbleFox + name: marble fox plushie + description: A cute plushie that look like a marble foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: marble + +- type: entity + parent: BasePlushie + id: PlushieCrimsonFox + name: crimson fox plushie + description: A cute plushie that look like a crimson foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: crimson + +- type: entity + parent: BasePlushie + id: PlushieCoffeeFox + name: coffee fox plushie + description: A cute plushie that look like a coffee foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: coffee + +- type: entity + parent: BasePlushie + id: PlushieBlueFox + name: blue fox plushie + description: A cute plushie that look like a blue foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: blue + +- type: entity + parent: BasePlushie + id: PlushieBlackFox + name: black fox plushie + description: A cute plushie that look like a black foxxo! + components: + - type: Sprite + sprite: Objects/Fun/foxplushie.rsi + state: black + +- type: entity + parent: BasePlushie + id: PlushieVulp + name: vulpkanin plushie + description: A vulpkanin plushie, at least you can hug this one without the risk to get bitten. + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: plushie_vulp + - type: EmitSoundOnUse + sound: + path: /Audio/DeltaV/Voice/Vulpkanin/dog_bark1.ogg + - type: EmitSoundOnLand + sound: + path: /Audio/DeltaV/Voice/Vulpkanin/dog_bark1.ogg + - type: EmitSoundOnActivate + sound: + path: /Audio/DeltaV/Voice/Vulpkanin/dog_bark1.ogg + - type: MeleeWeapon + soundHit: + path: /Audio/DeltaV/Voice/Vulpkanin/dog_bark1.ogg + +- type: entity + parent: PlushieVulp + id: PlushieTrystan + name: office vulp plushie + description: The ones who yeeps! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: plushie_trystan + +- type: entity + parent: PlushieVulp + id: PlushieCorgi + name: corgi plushie + description: The ian plushie edition! + components: + - type: Sprite + sprite: Objects/Fun/corgiplushie.rsi + state: corgi + +- type: entity + parent: PlushieVulp + id: PlushieGirlyCorgi + name: girly corgi plushie + components: + - type: Sprite + sprite: Objects/Fun/corgiplushie.rsi + state: girlycorgi + +- type: entity + parent: PlushieVulp + id: PlushieRobotCorgi + name: robot corgi plushie + components: + - type: Sprite + sprite: Objects/Fun/corgiplushie.rsi + state: robotcorgi + +- type: entity + parent: BasePlushie + id: BasePlushieCat + description: A stuffed toy that resembles a cute kitty! + abstract: true + components: + - type: EmitSoundOnUse + sound: + path: /Audio/Nyanotrasen/Voice/Felinid/cat_meow1.ogg + - type: EmitSoundOnLand + sound: + path: /Audio/Nyanotrasen/Voice/Felinid/cat_meow1.ogg + - type: EmitSoundOnActivate + sound: + path: /Audio/Nyanotrasen/Voice/Felinid/cat_meow1.ogg + - type: MeleeWeapon + soundHit: + path: /Audio/Nyanotrasen/Voice/Felinid/cat_meow1.ogg + +- type: entity + parent: BasePlushieCat + id: PlushieCatBlack + name: black cat plushie + components: + - type: Sprite + sprite: Objects/Fun/catplushie.rsi + state: black + +- type: entity + parent: BasePlushieCat + id: PlushieCatGrey + name: grey cat plushie + components: + - type: Sprite + sprite: Objects/Fun/catplushie.rsi + state: grey + +- type: entity + parent: BasePlushieCat + id: PlushieCatOrange + name: orange cat plushie + components: + - type: Sprite + sprite: Objects/Fun/catplushie.rsi + state: orange + +- type: entity + parent: BasePlushieCat + id: PlushieCatSiames + name: siames cat plushie + components: + - type: Sprite + sprite: Objects/Fun/catplushie.rsi + state: siames + +- type: entity + parent: BasePlushieCat + id: PlushieCatTabby + name: tabby cat plushie + components: + - type: Sprite + sprite: Objects/Fun/catplushie.rsi + state: tabby + +- type: entity + parent: BasePlushieCat + id: PlushieCatTuxedo + name: tuxedo cat plushie + components: + - type: Sprite + sprite: Objects/Fun/catplushie.rsi + state: tuxedo + +- type: entity + parent: BasePlushieCat + id: PlushieCatWhite + name: white cat plushie + components: + - type: Sprite + sprite: Objects/Fun/catplushie.rsi + state: white + ## Cheapo Figurines - type: entity @@ -1538,3 +1900,31 @@ # params: # volume: -9 # maxDistance: 3 + +- type: entity + name: The Throngler + parent: ToyHammer + id: ThronglerToy + suffix: Toy + description: Why would you make this? + components: + - type: Sprite + sprite: Objects/Weapons/Melee/Throngler2.rsi + state: icon + - type: StaminaDamageOnHit + damage: 0.8 + - type: MeleeWeapon + wideAnimationRotation: -135 + attackRate: 10 + damage: + types: + Blunt: 0 + soundHit: + path: /Audio/Effects/explosion_small1.ogg + soundNoDamage: + path: /Audio/Effects/explosion_small1.ogg + - type: Item + size: Ginormous + sprite: Objects/Weapons/Melee/Throngler-in-hand.rsi + - type: DisarmMalus + malus: 0 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/arcades.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/arcades.yml index 98f4a9afb0c..59690e56ebd 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/arcades.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/arcades.yml @@ -72,65 +72,15 @@ rewardMinAmount: 0 rewardMaxAmount: 0 possibleRewards: - - ToyMouse - - ToyAi - - ToyNuke - - ToyGriffin - - ToyHonk - - ToyIan - - ToyMarauder - - ToyMauler - - ToyGygax - - ToyOdysseus - - ToyOwlman - - ToyDeathRipley - - ToyPhazon - - ToyFireRipley - - ToyReticence - - ToyRipley - - ToySeraph - - ToyDurand - - ToySkeleton - - FoamCrossbow - - RevolverCapGun - - PlushieHampter - - PlushieLizard - - PlushieAtmosian - - PlushieSpaceLizard - - PlushieNuke - - PlushieCarp - - PlushieMagicarp - - PlushieHolocarp - - PlushieRainbowCarp - - PlushieRatvar - - PlushieNar - - PlushieSnake - - PlushieArachind - - Basketball - - Football - - PlushieRouny - - PlushieBee - - PlushieSlime - - BalloonNT - - BalloonCorgi - - ToySword - - CrayonBox - - BoxDonkSoftBox - - BoxCartridgeCap - - HarmonicaInstrument - - OcarinaInstrument - - RecorderInstrument - - GunpetInstrument - - BirdToyInstrument - - PlushieXeno - - BeachBall - - PlushieMoth - - PlushieHampter - - ToyRenault # DeltaV Toy, see Resources/Prototypes/DeltaV/Entities/Objects/Fun/toys.yml - - ToySiobhan # DeltaV Toy, see Resources/Prototypes/DeltaV/Entities/Objects/Fun/toys.yml - - PlushiePenguin - - PlushieHuman - - ClothingHeadHatCowboyRed + - PrizeBall + - PrizeTicket10 + - PrizeTicket10 + - PrizeTicket10 + - PrizeTicket10 + - PrizeTicket10 + - PrizeTicket30 + - PrizeTicket30 + - PrizeTicket60 - type: WiresPanel - type: Wires layoutId: Arcade diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 7e861db0d5a..de72dfcd5e4 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -1275,3 +1275,141 @@ staticRecipes: - MaterialSheetMeat - SheetPaper + +- type: entity + parent: BaseLathe + id: PrizeCounter + name: prize counter + description: Claim your prize and win some toys and cute plushies! + components: + - type: AmbientOnPowered + - type: AmbientSound + volume: -9 + range: 3 + enabled: false + sound: + path: /Audio/Ambience/Objects/vending_machine_hum.ogg + - type: LitOnPowered + - type: ApcPowerReceiver + powerLoad: 200 + priority: Low + # - type: Advertise + # pack: CuddlyCritterAds # TODO Change this + - type: PointLight + radius: 1.5 + energy: 1.6 + color: "#4b93ad" + - type: Transform + noRot: false + - type: Sprite + sprite: Structures/Machines/prizecounter.rsi + snapCardinals: true + layers: + - state: icon + map: ["enum.LatheVisualLayers.IsRunning"] + - state: unlit + shader: unshaded + map: ["enum.PowerDeviceVisualLayers.Powered"] + - state: panel + map: ["enum.WiresVisualLayers.MaintenancePanel"] + - type: Lathe + idleState: icon + runningState: icon + staticRecipes: + - PrizeBall + - PlushieMothRandom + - PlushieMothMusician + - PlushieMothBartender + - PlushieBee + - PlushieHampter + - PlushieRouny + - PlushieLamp + - PlushieArachind + - PlushieLizard + - PlushieSpaceLizard + - PlushieSharkBlue + - PlushieSharkPink + - PlushieSharkGrey + - PlushieCarp + - PlushieMagicarp + - PlushieHolocarp + - PlushieSlime + - PlushieSnake + - ToyMouse + - ToyRubberDuck + - PlushieVox + - PlushieAtmosian + - PlushiePenguin + - PlushieHuman + - PlushieArachne + - PlushieGnome + - PlushieLoveable + - PlushieDeer + - PlushieIpc + - PlushieGrey + - PlushieRedFox + - PlushiePurpleFox + - PlushiePinkFox + - PlushieOrangeFox + - PlushieMarbleFox + - PlushieCrimsonFox + - PlushieCoffeeFox + - PlushieBlueFox + - PlushieBlackFox + - PlushieVulp + - PlushieCorgi + - PlushieGirlyCorgi + - PlushieRobotCorgi + - PlushieCatBlack + - PlushieCatGrey + - PlushieCatOrange + - PlushieCatSiames + - PlushieCatTabby + - PlushieCatTuxedo + - PlushieCatWhite + - ToyAi + - ToyIan + - BalloonNT + - BalloonCorgi + - CrayonBox + - PetRockCarrier + - PlushieXeno + - FoamCrossbow + - RevolverCapGun + - PonderingOrb + - ToyAmongPequeno + - FoamCutlass + - WhoopieCushion + - ToyHammer + - PlasticBanana + - WeaponWaterPistol + - WeaponWaterBlaster + - NewtonCradle + - SnapPopBox + - MrDips + - MrChips + - CrazyGlue + - PlushieRatvar + - PlushieNar + - type: EmagLatheRecipes + emagStaticRecipes: + - PlushieGhost + - PlushieRGBee + - PlushieRainbowCarp + - PlushieJester + - PlushieSlips + - PlushieTrystan + - PlushieAbductor + - PlushieAbductorAgent + - PlushieNuke + - ToyNuke + - FoamBlade + - BalloonSyn + - SingularityToy + - TeslaToy + - ToySword + - ThronglerToy + - type: MaterialStorage + whitelist: + tags: + - PrizeTicket \ No newline at end of file diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Specific/Mail/mail.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Specific/Mail/mail.yml index 72f0cb741c7..7f1b26d9cbf 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Specific/Mail/mail.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Specific/Mail/mail.yml @@ -569,41 +569,130 @@ components: - type: Mail contents: - # These are all grouped up now to guarantee at least one item received. - # The downside is you're not going to get half a dozen plushies anymore. + - id: PlushieMothRandom + orGroup: Prize + - id: PlushieMothMusician + orGroup: Prize + - id: PlushieMothBartender + orGroup: Prize - id: PlushieBee - orGroup: Plushie - - id: PlushieRGBee - prob: 0.5 - orGroup: Plushie - - id: PlushieNuke - orGroup: Plushie + orGroup: Prize + - id: PlushieHampter + orGroup: Prize - id: PlushieRouny - orGroup: Plushie + orGroup: Prize + - id: PlushieLamp + orGroup: Prize + - id: PlushieArachind + orGroup: Prize - id: PlushieLizard - orGroup: Plushie + orGroup: Prize + - id: PlushieLizardMirrored + orGroup: Prize - id: PlushieSpaceLizard - orGroup: Plushie - - id: PlushieRatvar - orGroup: Plushie - - id: PlushieNar - orGroup: Plushie + orGroup: Prize + - id: PlushieDiona + orGroup: Prize + - id: PlushieSharkBlue + orGroup: Prize + - id: PlushieSharkPink + orGroup: Prize + - id: PlushieSharkGrey + orGroup: Prize - id: PlushieCarp - orGroup: Plushie + orGroup: Prize + - id: PlushieMagicarp + orGroup: Prize + - id: PlushieHolocarp + orGroup: Prize - id: PlushieSlime - orGroup: Plushie + orGroup: Prize - id: PlushieSnake - orGroup: Plushie - - id: PlushieMothRandom - orGroup: Plushie - - id: PlushieMoth - orGroup: Plushie - - id: PlushieMothMusician - prob: 0.5 - orGroup: Plushie - - id: PlushieMothBartender - prob: 0.5 - orGroup: Plushie + orGroup: Prize + - id: PlushieVox + orGroup: Prize + - id: PlushieAtmosian + orGroup: Prize + - id: PlushiePenguin + orGroup: Prize + - id: PlushieHuman + orGroup: Prize + - id: PlushieArachne + orGroup: Prize + - id: PlushieGnome + orGroup: Prize + - id: PlushieLoveable + orGroup: Prize + - id: PlushieDeer + orGroup: Prize + - id: PlushieIpc + orGroup: Prize + - id: PlushieGrey + orGroup: Prize + - id: PlushieRedFox + orGroup: Prize + - id: PlushiePurpleFox + orGroup: Prize + - id: PlushiePinkFox + orGroup: Prize + - id: PlushieOrangeFox + orGroup: Prize + - id: PlushieMarbleFox + orGroup: Prize + - id: PlushieCrimsonFox + orGroup: Prize + - id: PlushieCoffeeFox + orGroup: Prize + - id: PlushieBlueFox + orGroup: Prize + - id: PlushieBlackFox + orGroup: Prize + - id: PlushieVulp + orGroup: Prize + - id: PlushieCorgi + orGroup: Prize + - id: PlushieGirlyCorgi + orGroup: Prize + - id: PlushieRobotCorgi + orGroup: Prize + - id: PlushieCatBlack + orGroup: Prize + - id: PlushieCatGrey + orGroup: Prize + - id: PlushieCatOrange + orGroup: Prize + - id: PlushieCatSiames + orGroup: Prize + - id: PlushieCatTabby + orGroup: Prize + - id: PlushieCatTuxedo + orGroup: Prize + - id: PlushieCatWhite + orGroup: Prize + - id: PlushieGhost + orGroup: Prize + - id: PlushieRGBee + orGroup: Prize + - id: PlushieRatvar + orGroup: Prize + - id: PlushieNar + orGroup: Prize + - id: PlushieRainbowCarp + orGroup: Prize + - id: PlushieXeno + orGroup: Prize + - id: PlushieJester + orGroup: Prize + - id: PlushieSlips + orGroup: Prize + - id: PlushieAbductor + orGroup: Prize + - id: PlushieTrystan + orGroup: Prize + - id: PlushieAbductorAgent + orGroup: Prize + - id: PlushieNuke + orGroup: Prize - type: entity noSpawn: true diff --git a/Resources/Prototypes/Reagents/Materials/prizeticket.yml b/Resources/Prototypes/Reagents/Materials/prizeticket.yml new file mode 100644 index 00000000000..cde81626c84 --- /dev/null +++ b/Resources/Prototypes/Reagents/Materials/prizeticket.yml @@ -0,0 +1,6 @@ +- type: material + id: PrizeTicket + stackEntity: PrizeTicket1 + name: prize ticket + icon: { sprite: Objects/Fun/prizeticket.rsi, state: ticket } + price: 0 diff --git a/Resources/Prototypes/Recipes/Lathes/prizecounter.yml b/Resources/Prototypes/Recipes/Lathes/prizecounter.yml new file mode 100644 index 00000000000..e893c178358 --- /dev/null +++ b/Resources/Prototypes/Recipes/Lathes/prizecounter.yml @@ -0,0 +1,729 @@ +- type: latheRecipe + id: PrizeBall + result: PrizeBall + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 30 + +- type: latheRecipe + id: PlushieMothRandom + result: PlushieMothRandom + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieMothMusician + result: PlushieMothMusician + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieMothBartender + result: PlushieMothBartender + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieBee + result: PlushieBee + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieHampter + result: PlushieHampter + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieRouny + result: PlushieRouny + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieLamp + result: PlushieLamp + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieArachind + result: PlushieArachind + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieLizard + result: PlushieLizard + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieSpaceLizard + result: PlushieSpaceLizard + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieSharkBlue + result: PlushieSharkBlue + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieSharkPink + result: PlushieSharkPink + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieSharkGrey + result: PlushieSharkGrey + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCarp + result: PlushieCarp + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieMagicarp + result: PlushieMagicarp + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieHolocarp + result: PlushieHolocarp + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieSlime + result: PlushieSlime + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieSnake + result: PlushieSnake + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: ToyMouse + result: ToyMouse + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: ToyRubberDuck + result: ToyRubberDuck + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieVox + result: PlushieVox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieAtmosian + result: PlushieAtmosian + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushiePenguin + result: PlushiePenguin + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieHuman + result: PlushieHuman + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieArachne + result: PlushieArachne + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieGnome + result: PlushieGnome + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieLoveable + result: PlushieLoveable + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieDeer + result: PlushieDeer + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieIpc + result: PlushieIpc + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieGrey + result: PlushieGrey + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieRedFox + result: PlushieRedFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushiePurpleFox + result: PlushiePurpleFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushiePinkFox + result: PlushiePinkFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieOrangeFox + result: PlushieOrangeFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieMarbleFox + result: PlushieMarbleFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCrimsonFox + result: PlushieCrimsonFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCoffeeFox + result: PlushieCoffeeFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieBlueFox + result: PlushieBlueFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieBlackFox + result: PlushieBlackFox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieVulp + result: PlushieVulp + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCorgi + result: PlushieCorgi + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieGirlyCorgi + result: PlushieGirlyCorgi + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieRobotCorgi + result: PlushieRobotCorgi + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCatBlack + result: PlushieCatBlack + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCatGrey + result: PlushieCatGrey + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCatOrange + result: PlushieCatOrange + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCatSiames + result: PlushieCatSiames + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCatTabby + result: PlushieCatTabby + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCatTuxedo + result: PlushieCatTuxedo + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieCatWhite + result: PlushieCatWhite + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: ToyAi + result: ToyAi + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 30 + +- type: latheRecipe + id: ToyIan + result: ToyIan + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 30 + +- type: latheRecipe + id: BalloonNT + result: BalloonNT + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 30 + +- type: latheRecipe + id: BalloonCorgi + result: BalloonCorgi + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 30 + +- type: latheRecipe + id: CrayonBox + result: CrayonBox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 20 + +- type: latheRecipe + id: PetRockCarrier + result: PetRockCarrier + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 50 + +- type: latheRecipe + id: PlushieXeno + result: PlushieXeno + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: FoamCrossbow + result: FoamCrossbow + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: RevolverCapGun + result: RevolverCapGun + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PonderingOrb + result: PonderingOrb + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: ToyAmongPequeno + result: ToyAmongPequeno + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: FoamCutlass + result: FoamCutlass + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: ToyHammer + result: ToyHammer + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: WhoopieCushion + result: WhoopieCushion + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlasticBanana + result: PlasticBanana + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: WeaponWaterPistol + result: WeaponWaterPistol + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: WeaponWaterBlaster + result: WeaponWaterBlaster + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: NewtonCradle + result: NewtonCradle + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: SnapPopBox + result: SnapPopBox + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: MrDips + result: MrDips + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: MrChips + result: MrChips + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: CrazyGlue + result: CrazyGlue + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieRatvar + result: PlushieRatvar + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +- type: latheRecipe + id: PlushieNar + result: PlushieNar + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 80 + +# EMAG + +- type: latheRecipe + id: PlushieGhost + result: PlushieGhost + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieRGBee + result: PlushieRGBee + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieRainbowCarp + result: PlushieRainbowCarp + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieJester + result: PlushieJester + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieSlips + result: PlushieSlips + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieTrystan + result: PlushieTrystan + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieAbductor + result: PlushieAbductor + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieAbductorAgent + result: PlushieAbductorAgent + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: PlushieNuke + result: PlushieNuke + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: ToyNuke + result: ToyNuke + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: FoamBlade + result: FoamBlade + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 150 + +- type: latheRecipe + id: BalloonSyn + result: BalloonSyn + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 100 + +- type: latheRecipe + id: SingularityToy + result: SingularityToy + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 150 + +- type: latheRecipe + id: TeslaToy + result: TeslaToy + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 150 + +- type: latheRecipe + id: ToySword + result: ToySword + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 200 + +- type: latheRecipe + id: ThronglerToy + result: ThronglerToy + applyMaterialDiscount: false + completetime: 0.1 + materials: + PrizeTicket: 500 \ No newline at end of file diff --git a/Resources/Prototypes/Stacks/prizeticket.yml b/Resources/Prototypes/Stacks/prizeticket.yml new file mode 100644 index 00000000000..1b84c81632c --- /dev/null +++ b/Resources/Prototypes/Stacks/prizeticket.yml @@ -0,0 +1,7 @@ +- type: stack + id: PrizeTicket + name: prize ticket + icon: { sprite: Objects/Fun/prizeticket.rsi, state: ticket } + spawn: PrizeTicket1 + maxCount: 100 + itemSize: 1 \ No newline at end of file diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 928da630f6f..cc81a2ed64b 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -1033,6 +1033,9 @@ - type: Tag id: PrisonUniform +- type: Tag + id: PrizeTicket + - type: Tag id: ProximitySensor diff --git a/Resources/Textures/Objects/Fun/catplushie.rsi/black.png b/Resources/Textures/Objects/Fun/catplushie.rsi/black.png new file mode 100644 index 0000000000000000000000000000000000000000..e62cb62916e36ce5d03c8aa066038b751483d852 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)*8>L*@bmM_$;k-|3u|a- z{Qv)-m6esBgYj$gyBXJa+yp9PED7=pW^j0RBMr#u^>lFz(U^F){~+%n10L76ypL44 zkDO%6Q(uvNgpG&6+JLb+m@{K;%mj;%|KGl>J<0ZCe#=_Bhz%tQqO0akieN9WyldmI zZ~pp6y*d1E)oz4z*m#-vZnF@WDITW&^y(zd?fouMrnAl!S8Ha7geHle%5UA|8TXuF vN4|!FpiF{&21_K{!ukZ^eYy;sb*F_BeFb$6Y}dU3bQpuDtDnm{r-UW|2DMi% literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/catplushie.rsi/grey.png b/Resources/Textures/Objects/Fun/catplushie.rsi/grey.png new file mode 100644 index 0000000000000000000000000000000000000000..b941adbf78194b15c17b17ffc4eaea39ec4e20bb GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)*8>L*7#bL)rlvYLI5amm z|NsA=m6esBgYj$gyMyVUG=Rz&OM?7@862M7NCR?uJzX3_G$x+yKgfH?fXDSM?;{oN zBPW^i)K_F5VdG)2HehTH=FFHIGr{8H|F8x|b)tVV1p-G~r@>@4~#yw}) vk*}d3D3f5H!4k=~us%U}pDqJu-D%-OUqPJ%+jVaM9me44>gTe~DWM4fv)frg literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/catplushie.rsi/meta.json b/Resources/Textures/Objects/Fun/catplushie.rsi/meta.json new file mode 100644 index 00000000000..878f438f4ec --- /dev/null +++ b/Resources/Textures/Objects/Fun/catplushie.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise Station", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "black" + }, + { + "name": "grey" + }, + { + "name": "orange" + }, + { + "name": "siames" + }, + { + "name": "tabby" + }, + { + "name": "tuxedo" + }, + { + "name": "white" + } + ] +} diff --git a/Resources/Textures/Objects/Fun/catplushie.rsi/orange.png b/Resources/Textures/Objects/Fun/catplushie.rsi/orange.png new file mode 100644 index 0000000000000000000000000000000000000000..0f4cad131f780ecb2d1897d0e7e14e5d227df3cd GIT binary patch literal 585 zcmV-P0=E5$P)#HWjg&GK+@O2dtBy+^2A(<~;lHb&LL1eCR>O2WykR1~QxL&$ zHO!4&ojw--|NjLA1>VQBlRpd(2m$x*=-{Gv(RNJi$D8iXxAyGi^@HyB?B(I9gYx3n z^W@s$u8+)VJgH7An>QPkGZkPc2-klsr9dd};MMZv+tZ+Y#)e(^@a*&F;Ak%p+@xOW z)5Y%G(aw`_^X1&$uWY74D!*$lp*$kfqlDqVs`u~d_wDE1r(oTxWZRrnog3e5i1_g9?c31Cgk9;n9Ax})fkUtyj6hs3szg- z*wh{~t(`SwweL&-Y;EtbHbB}t!<+?HJ85@s9|{MDo*00r%z=QeqsGzk$?4g7urDsJ zxV0|$0jW2xA^hCjR-k2o7Uuolj1v#@<%@^;)ZM*}7HB>^#sSTz=a*<8d3}422mVwa XRp=GyD$AXr00000NkvXXu0mjf#}p}# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/catplushie.rsi/siames.png b/Resources/Textures/Objects/Fun/catplushie.rsi/siames.png new file mode 100644 index 0000000000000000000000000000000000000000..6f27a86343a2d2450faccef3345bc9eaa4c8c805 GIT binary patch literal 658 zcmV;D0&V??P)eEgK{f2W&|yG9eNl396&H0Xhbc2UN}G-2M-7V zT`moJTRfq9KVUHs^@HwLCJJUa7^IF~oN`2TMDbb ziCJ1H4Rl8%Cl(4dBo!bI1WYIpf?_;IFdKbQD^4pCL^B|ARyZ>p3`8IbA`k^G9S>9^ z2_X*!KN|)`APPh-8gNf7eqK6XN-$SKDP=<}N;o7xFda807da>wR3!;kB?>DO1}7B> zC=moH5d=s$BRwn|DHjSiCKfs>8BseXFdq>i5CuasATt{bLNXsi9SAEK3?mT+a87mq z00001bW%=J06^y0W&i*I2uVaiR5*=eU>F5RfDwq9@W?Z>urjc*bKsQcMC+ z#A$$#u!yLbxC9$61(H(IGP2S#a`HIj6%>_}WmJ@9L{t@UsZdjw)zH+^#w8C_p{=8< zr>_78I8>-AD5z?yY8x0BU{|4_4FU#0%0L@rj3K%LBV!X)pk^R804g*!Gq*sIwzQJ9 zwz0LdcK}(Tt*YwiFVv{>*uc!VC5znh@>JY*eWE{Ei9bP zO*SGT(j6pZ6%vJFNpwtXTs#9q0yDE!I9Px))B$IpfI(tt5?*=E(Bu?+^31ZSY53%U sPUggGfs0#MI$i|~>FGxJ6;Krb0Nb!9XXk;&$p8QV07*qoM6N<$g2P|dnE(I) literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/catplushie.rsi/tabby.png b/Resources/Textures/Objects/Fun/catplushie.rsi/tabby.png new file mode 100644 index 0000000000000000000000000000000000000000..38575cc0de2a47fc8856e110be3b9fc6ccb34969 GIT binary patch literal 539 zcmV+$0_6RPP)CdG!^6zX z%=LrrzP-M!t*taOGo_`aa&mGN6%{r$HC9$uPfkuoMMXL~I&^e&IygEsGBZ3oJa2Dr z#l^)=O-^oYZE|sOsi~=2T3UK~dXA2ce0+RpXJbi$iw5)vwQNAy^h|d7sj*A9FVYJtPTppao}?}-apdMU_h2g78IiX d1X1002ovPDHLkV1lM|L*NJvN+85t=kC^$Mg z{{R1_!@pGvCw2F+^ix za)N}70|UoI#>GmDmAV=>ELvdHC6uVDZqjIQJtc+FZK=_B73UODB{}0c0b2}KnMiVR zDRFahOG)muP~!Ah8&nihMh~(UUhKSQoWibPYIhGQi_z zKmf}smw+Qj1CHE`XlN8%=N`}y7%+iRk)d2**8wr-5W8~mEDOUoFWfF~d~7m{;d>t2 bCk6(OOJbW|374M*I+elG)z4*}Q$iB}NN!}# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/catplushie.rsi/white.png b/Resources/Textures/Objects/Fun/catplushie.rsi/white.png new file mode 100644 index 0000000000000000000000000000000000000000..e16a9ed29dbc2334887cf408db029caa7cd126ab GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)*8>L*oH%jf-o1P0&YgSx z`t|?+|5;gC`8gQBHow!jKC=p_jIkuhFPOpM*^M+Hr`OZPF+^kH+5UsPhYWaJ-|{|E z;XZPbDNlVx_7OH725SSx=3vf@xiJ$gKK_6Evi2m~kNGWY?IJdmD2T3_J1K&_!1At* z!@l|JANA(&zg4>t(qZFe;=9d4V5WGO`qQhEG`IJ=M48SyS6r=`ArhJ-dMdwllV{v> wh8_7D3W72T_8BaZYzylXg!kz(aMqm`PV^PjIj~*#2GC&)p00i_>zopr09GJhB>(^b literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/corgiplushie.rsi/corgi.png b/Resources/Textures/Objects/Fun/corgiplushie.rsi/corgi.png new file mode 100644 index 0000000000000000000000000000000000000000..83eaa3bb860151b94f96b2cbe7634fed80ef1f08 GIT binary patch literal 394 zcmV;50d@X~P)FMbQ5`KUN@GzoM@7Wt$!aA#+6XJ>P1X>>;z z;BpfP00001bW%=J06^y0W&i*H%t=H+R5*?0k6m)YFbssFm6bR(3TYh>#HEz>{&%d+ z&x_M=0d~fE(0P2H1WB6#;Z=g9V}f8EU;yqJfCBI;Kmzf?{OCXx zC<4yU^>o);6(te^u<<%`Jyra008px^7*Mb`Kvwor#AVeHTkJJw?wY?_V)Ru zH1qTGbVnE9aM$VS>GARLlarHlNEmHoWR;bb`KUPgt33316#1hw`J^;-Mi%*|HF7iw zb7^UDXJ>Rp6>w)~bVnFp#*69z0004WQchC@kpt+?WIEIRvfWN5e=4H`FygBT+4L)6Ae#YX*$9v;G0n#k za>xP9R{#M}H2}=}##n2~5t2z4=jN@VL?Wy62`s8ESl4TIOGJ?rSoMHvT{q&q_nWlC zwzrFp*r~#xWVJ_R!N|O>>vs4{gH^#S4x_M>whT!`u!rMm)i@vVe7Lk4#-BtuYk}*n z@i&ZEUhWU#G{TW52_ZbAt~a~%2_-u9rx4S?PSG*{C-nlxkqp668Tr8g0000%q1F literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/corgiplushie.rsi/meta.json b/Resources/Textures/Objects/Fun/corgiplushie.rsi/meta.json new file mode 100644 index 00000000000..06c0cf9ed4a --- /dev/null +++ b/Resources/Textures/Objects/Fun/corgiplushie.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise Station", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "corgi" + }, + { + "name": "girlycorgi" + }, + { + "name": "robotcorgi" + } + ] +} diff --git a/Resources/Textures/Objects/Fun/corgiplushie.rsi/robotcorgi.png b/Resources/Textures/Objects/Fun/corgiplushie.rsi/robotcorgi.png new file mode 100644 index 0000000000000000000000000000000000000000..a8dfdfb3f32d8744a16138695f681eba8785d658 GIT binary patch literal 391 zcmV;20eJq2P)$!BM0V`F0%6%{QhDJv%@US3{OOG{KuO;b!v zURG8vDk@YRqKp6l00DGTPE!Ct=GbNc006^DL_t(IjpdI^8iFtkgh@icN6}IYNGsy= z{#UdG-4x*h%p!}-pZO+9vMvFHvEU;?0_i*f9Dp!pfs6nd=K(^*bP3=9&@2F)^Pn#P z5g4p|v)y@M)IN%0R$~AXg)&$iqKKo`x-=F3RGi{6QhNof8G!S&EVSOU)}gY9mtqni zX{(G?4ohQgQ^fCz^=EBI89HsMYkwn>2;h6)rReaXtLMv?$Rvu8y7D3JEh36FmysV3 lwyZ=3SY+yt`#N literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/black.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/black.png new file mode 100644 index 0000000000000000000000000000000000000000..b314043924a700369a0e59064891c767464cf785 GIT binary patch literal 1201 zcmV;i1Wx;jP) zH8wgQ9v~|!E)WnBK|x9?C@vTm8W$EAN={TKCn_y1FhWI2NkT^%85|xWB@z-97#SN7 z4-ps?7(zis9v>ntFElJIFf%hZTwrBxZgy^IZ)ag=7!wvB9UwV7KQ%QvWM^(hK0`V) zH#sslBqAg%C@V)lMKmrl9~m7Y93LGUA1^R9OiWQ%Qdu-DGDJKC$oCqh3(Jw8G(GBqF|BRn}mBqAp{H$8@smO@5J z2nY%&CM`NVK{PcwH#t2dA|*~zRvsK592_1X9U>bT9VaC!C?_l+AS53jA|)j#USw$? zA0reWC00DGTPE!Ct=GbNc00FH@L_t(IjbmUKI)IT0pDZ&A11lRl z9t9knEL_|?ytoyx^YIG^3JHtgQ6VZOE+L6Wft0k2tem`pA`WR886{;I85LDEbzBNG zG_|yKboKNN42_JrOw>&=R4}uciI`hhT3OrJa@yH*af7#sO;qIBJb+v?&0a` zx=4d7C(Q-fWV+&zmU+da89p?NKVeEXk-O3v5t;$@zM#7iAl*Rsa|R6oEe!} z**S3e+`RmP!lL4m(v-Zi@`}pXs_L4M+PeA%h-_n1UbABgV@qomds};lX=hh=4?{<9 zVqgD+iOgUHlO|6AlCe{#O$YI2%$x;^+MbNrbLP&Q53^#y!bOXhbTBY1UAAmFdk;ut z#mZHy*Q{N)9;#r&#!Z_+^u`UFAf_(cvUS_`9Xog7N(IYyPurusH*4SiHf*xIj0X-* zJ9PNS(PPI?^q|Rc@J^ZDcJfs0=`&}yojZRaj{{xvl8cuv7jL~1d-dA&8#iyo-o`Y3 z$(_5V+S+~>?%jXjtc5idK76Ph8=L>=vEQl=Tt0YG^;D{(gQ*IKH1z=hXu|A* P00000NkvXXu0mjfJehD= literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/blue.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/blue.png new file mode 100644 index 0000000000000000000000000000000000000000..ccc9b2d7e4adcb3b39780d25ff23411da83d90dd GIT binary patch literal 936 zcmV;Z16TZsP)r;v9{~sz0S6NS2ND4Y7Mz@%y}iBH*VpCd=%};2-QwmGZo3OBQ4A_k4?1iO zI&Kd{fDl}u6K}m0d(Q$NQ@6Oh=I7|$;pGohkPkw65?Y-TZ@&|7vjk7G12~20>FMa` z=|rX1)z#JH=IG+&=hxojVYu14#?Tmu)C3hN+1c6E*V$N}zbcm1*VowKTgF{?gMi!R> zIeB>nMI~hwRW)@DO-*$z3>DhiI=XuL28Kq)CZ=ZQ7M51r+?d8#+t}LKJ2*Oti;4@2 ziwipgfeWfBu5Rw4U?40mDk?4xVxg$;@bvN)74`A;6BPzZi3>wiAguD24+snr4OR?M z1j&hubA!zghnf)@79J596&({Br=z384KzWVn}Hi_gfK)!d_p3SOcG2^0r67P#6c#z zh@vvE1Q8KCpRy@pb#YDEQ(|V14B`9Nj8WsE-5Ji3pj(_0CxojC@m93H30>b zS5#J2SJ!}oLl`|wwaayNYrPcf>KhuHz}`jItRpWU(A?76*51+C)!ozEhiSZa|AdK? z6edrZI&J!lnL5}Upgn7ntE>F%IdkXD*T&(4S=vCbU?DDP>H`3mph^Oj#Q#_T0000< KMNUMnLSTZQJ##Jq literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/coffee.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/coffee.png new file mode 100644 index 0000000000000000000000000000000000000000..81650c1b6f6981f04c4c387cd8ebaf3abef7d3e9 GIT binary patch literal 1046 zcmV+x1nK*UP)F0wfs?Sv(bCL>(6n1riDaG$RWt9S=As z4`)gw8xaT{5(rmCEn!bLTS+lkMlOC~Iu8f}D;*G?fm#3n0RR90gltTPX+o-wY1-G) z($2}Bi*VJ^!|CYg>+9?0<>c}3@bK{O&9|A5d0du}hl_)G)6vl5F3SK!&XEr91H7*snOJ1P?>91y|5z2V^A z)6mS`+}XsxyzA=db6GXx;osca*4Wk1V?`fKGZRcR6ntn-6%7Tap_u6C=koIM?d|K= z)6e4I-s|b;X-+3zNh@DOAFi2xQ92w~MKQy}!Q9*0zPYl_%*g8M>fztp=jG$k&&%lN z<>21i-rU+M8Vrtwe7CZ%;N98S)X&-1)ARH5^Yil4(b1fij*y6ci-UM?WLIfkP@$WY zvahVk$;qO0Dp~*l00DGTPE!Ct=GbNc00DkUL_t(IjbmUKI)IT0pDZ&A11lRl9t9kn zT--doe7F_x3-AgG33H0zRv{`TE+Hu;jaz|?tem`ptRgcGX*oG1WjQ$&RRtMb3e?m! zG_|yKbQNSE07HeIzJZ~Uv5|?Xf-D$dQ^R1Ut!-{0E32R&t01nRAZ`f+RwxRrO>Ar- z`o$H%>VN=6g`K^FqpXv&i>sSBP)b1@q5@%+ySay_mp7-6hOZw`PC-EiY=#2V4F7<@ zpx}_uu<(e;sOT7R+1R*v1{tss;t&-Hi6EoGlZ2B&yp+_iG$3Uqi{gy*jHJx0YzBs$ z+`RmPY>-G{ERqon4ANXh#UQ#wnx7RcP#RVSbOYQK7@)kOvWll#Shl7Xn`~WuLt|5O zOKU}2dq*dlTvvBbZ(sj}iIXNxo-#FK+VmOdnrE8N(wIGG?z~y^7c5+~c*#;soyII?K^hv!r_D6d-m?zf8gM59MaSW067X@vYYkh QnE(I)07*qoM6N<$f~1|=y#N3J literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/crimson.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/crimson.png new file mode 100644 index 0000000000000000000000000000000000000000..025750617687fc66565a7a6d050e5578821c5f23 GIT binary patch literal 927 zcmV;Q17Q4#P)q%0001HC?^;M1XKb9UMeUZ1O$E%7JMWm!W$(_Eh-!Y z1dR?Ai6SJ_7b3>S#boD3%~3q7W7o0s-dX;o92T+1JFMd{ z=+{I})z#JL9QV+9Ch1O=rRA3`7?QY0u& zEGQHN1RV+q9SaH^3kokA84m;mFarb)1qBQR1!xfyxEmtZ)zxZHOhp_VS|=xaB`AX= zC%wG9)zHt0UR+NtDtJ6R+q%8z=jYhe)y%!UT_z;8adGD3k0d!JMQvg8b*k%9#0dPq~K~y-6V_+CMfRPEGEHeuOD;ql=1st4Q z+#Ec-cogvQb8`p?3gJ;93Otn!x+2n-SpR#XT9$%%_|gUt|! znh_cn9uXN89TOX;qoczOG(nu3fg5auFhoUsLL!h%5=>43@lw;oK_Lw;dV7Kkn^Dk=gCID_2)cLfG0E)hjF0R@znl~+_&R)K;; z7(Gn2OLcXty%cL|>*^c8-bL4}BQGD&Xw%f((%RPE(b?6FX}oq%Z(qN{go%?TPnkMR z2b%-5r}w+M%FmcNYxW#%96p$?4Fq%N;gY64006r6Ne_AxUEBZw002ovPDHLkV1nsA BUAq7P literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/marble.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/marble.png new file mode 100644 index 0000000000000000000000000000000000000000..b6f1cb9032df73a30248205732b42897dc1e58dd GIT binary patch literal 1089 zcmV-H1it%;P)RMrAPgGX7yuP2Rtso~U5fl~%2L}ZO1soqC z=jrLX!^b~EML|PFUu0%>dwz3ydwhe2fQXHYla(VUC>k6c3k?m`+u4+um_!Yo(go}^V*Vu-RkwQgBM@&x6(b3=G;nmsN@$&N7+uL(`e6_l~!p+YoC@3f_EGjH4 z4iFFo1O%0!rNhR?=;`V0?(Vm{ziDrCFETPHEG;K0DtCT?TxV;4hKPWNieqSM$j!_? zL`SEruFuiZ=I7_p)YYf1u))R1*xTM-V`eQdFf1)CK1NDDMMzCmS1Bzox4**R;^Ld1 zpN^B3i<6c+Ktqj_mfGIogo}|VDk?ujL}hV#mY$;0)YReQ#Jw6|$-a_;c(u(h>_j*b^!y9NLN00DGTPE!Ct=GbNc00EIn zL_t(IjbmUKI)IUpfGiU;J{62Cj7+R7YFetuCgaa>05OGrvdu}aIx%E>DzDk&-{VLFmgS%sCISyfG4LsLszM^{hZ0Mi&l zR#qcp6H_yD3rj0&adsP9J9`Hd1x&0ej!w=lu5Rwy9-b`X;$AY|KDNjTd|6fe{8?DV z0|J9wSy;r`gF`~Y!XqN#@=?)JQsObOtWvB}?BYNJn55$36B3h@A+pISscGpMnOWI6 zhK7br94xtcYz$2K1%*Y$f+b)DrDf$nvZ9jJ5X7shuBio5b@dI6O-;=(E7Dq8+uDHv z)zR72-O~#a>Fb{`anj@|P)iu5vax}~aoY45GrBZ~lUXFa_v9Wzpg#OC^>q zU$GLatcs!3s?}@OhOb+{VI!IxlL}Cl6$mzM-m-Pu_8mJhLR<&IK*X})g_w7G` zX*?4L2M0*a!9$0S96g530ZdE~BaXA4IEljtOi+MBn)(0$kD^{00000NkvXX Hu0mjfr27Q% literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/meta.json b/Resources/Textures/Objects/Fun/foxplushie.rsi/meta.json new file mode 100644 index 00000000000..5842b1ad07a --- /dev/null +++ b/Resources/Textures/Objects/Fun/foxplushie.rsi/meta.json @@ -0,0 +1,38 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise Station", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "black" + }, + { + "name": "blue" + }, + { + "name": "coffee" + }, + { + "name": "crimson" + }, + { + "name": "marble" + }, + { + "name": "orange" + }, + { + "name": "pink" + }, + { + "name": "purple" + }, + { + "name": "red" + } + ] +} diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/orange.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/orange.png new file mode 100644 index 0000000000000000000000000000000000000000..5bd3098c0d25efb396fa78c12fec86fc903c8f08 GIT binary patch literal 939 zcmV;c162HpP)z)0001HJSP|l1XK(HUOFfp2?TyD5PUx*!bclSIVv0p z1dT2Zi9sUNOc%z+#FMd{ z=+|*X)z#JL<>cq%;^W%a*@16&DQ$ zLMIL{6bJ+z5D6U+3LFs%FCrNa2Lvz*0}llR4G0Ac2n7@e1ZX1>xJMh;)zxZP zOhqUhS~n+qJtc!bB)z=6)zQz1Y+O${DtJ#k+s?Y^=jYhf)Xc)YT{k4PhH>WPOtn!x+2n-Sp z4hdBR$%%_|gUt|!nh_Qr5g8R76B`$=qoczOG(nu3fg5auFhoT{ViJ%{7EDP6@zT=8 zK_LvcxI8Hg?^EiDBLID_2)cLfG0uMkBw z0R>c6RoB$k)`5aU7(Gn2D|L12y+Rrqo0?m|-bL4}BQGD&YSY%<(b?7A)7#gNX}tD? ziIXNPOqn`u`iz;gbg(%SGN2Gdy%SW=6yxg##h!>FMd{ z=+{Ju)z#JL zLLx0gA1zcHIK{=q7zz(k9x`DhJk@8J6bK3!1q}`a2u>$7PbV~E1sr7r8l@LbLLe(r zBsoqfG86;}9SIK|3J)9#4lfxW4+ID>0}c%Z2Mh%VXb~y68&=oV)oM&qMI0zvCpmj1 zMS~ z(9@7_d5V64o12@QoSXNqr2qf`00DGTPE!Ct=GbNc00D4GL_t(IjbmUKI)IT0pDZ&A z11lRl9t9knT-+Qyym%Dw@pE$s2nyj*Aq)f}cr4)-KTgF{?gMi!R> zIeB>nMI~hwRW)@DO-*$z3>DhiI=XuL28Kq)CZ=ZQ7M51r+?d8#+t}LKJ2*Oti;4@2 ziwipgfeWfBu5Rw4U?40mDk?4xVxg$;@bvN)74`A;6BPzZi3>wiAguD24+snr4Gswn z0m+GrbA!zghnf)<9uXN89TOWDucM>G4KzWVn}Hi_gfK)!LShn-OcqQ@1@Y3-#X%;! zh@vb zl~+_&RaJw6Ll`|wwaavMYidL4>KhuHz}`jItRpWU(A?76*51+C)!ozEhiSZa|AdK? z6edrZI&J!lnL5}Upgn7ntE>F%IdkXD*T&(4S=vCbU?DDP>H`3&&Pu+BmUaXH0000< KMNUMnLSTZR1#;d1 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/purple.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/purple.png new file mode 100644 index 0000000000000000000000000000000000000000..18aa47315d69685354a9eb295de9468b8a70e82c GIT binary patch literal 942 zcmV;f15x~mP)FMa` z>6=8?)z#JJ-`4+ALJtt2j1!E@!WnCAgGay1Y zBvL;pP7enc3Ir4s2^|y)9To~4CmAmZ1P>DfFbD(>2?Y%a1q?M2Xlxs})z#NwOlmP4 zMMEcAPbGU)B!k!0*S);G<>Kel&((HZi9sq)UOafxy4&dI=+)HN#l6f$BwdzqwdCXG zlxetEB8FohqIg)AGZ$0Az{A49#KXeG+1T0N-QSRDwbIJiX;pktENoFHZ&W*EoSU55 z+1k+0($vt`gKv<9eu|r$o1B}QDY|IG00001bW%=J06^y0W&i*Ia7jc#R5*=eU>G`p zkqMtHGYbPN8#^8a9GqO-96Y>u6!7tLa|j3u;ZY$B1R{7W;TGi(6Bm_`#HF7@N}7X1 zTwF#LmjXF?c?Cr!WffI5bq!5TbuA1P+S)q0din;2M#d(lX66=_R@~f}##r0f+Sxle zI*E&l3yX^jI|G3Wswu8+?xJ8IEG{Z4E)HU$sPORg@)i~K@%0lG21iWgWUjk1qLW9 z7ezGz1yod4RoB$if`UUBJxsOhbam?+LK>TzTUx>1Mc1q&FCWlm)85h9)!ozE*FOQ% zcoGGrZ@^k0SU$9UchY#jx1Hq!jxTL8M0H~%)-o-EO QUjP6A07*qoM6N<$f@$)3EdT%j literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/foxplushie.rsi/red.png b/Resources/Textures/Objects/Fun/foxplushie.rsi/red.png new file mode 100644 index 0000000000000000000000000000000000000000..966108f7abe96ce5d2ed2ce4a60fcada6afe5c01 GIT binary patch literal 1408 zcmV-`1%LX9P)1w!oSAlpuG3PWOqoK}E`nH*C;^mGfv`=B#$8bpHHcoI5H;R-VKfp=OkFWi zqo9$X2E+nm0R`g{gNRy$Zg!>1jMEMs+L<{sXU_S(0187D5ka`{y*XR*e^1`L-lA*Ec<>i+{=)BwxfH^|4A+#vr`fPP<-{P8ij1emqN%{yQ1Wo1SAd4)&-7?GrM zx2K+W9&pRgHf~|mm|Wg}{&toxntk3N5&)jKe;I3DTFvZftb@4h-rQI$uWYk*-P9E`-Uj~Ha>rY`RK zr~^IRi?FI(zaW?O_sluxE?AD=l$Di90MD{g+Ji^m2_b0P zVL}E{eLu*~^vgJMI7r1}Hx?-gbTyLgx*YG?#eDzyPvjT5NEzrOY4R-8>@g^c0Vaf6 zI=N%@R#Ghj&5*pddFL6y3=84On&3>AqwEnRc;7@?#fjv4HuwyuZbLMKyal~S0ONuZ~l2Og}TwA9J96I1C;iZOMp4fX9? zhlTjG00*8~hPPoeMl{6er5|I>9*t@rLB{+wC=;J1YwqjVuAWI>TOH!JJ=E6h!kOb> zY<4;=t=(w7UV@=8IVmbub&$e}N%TIqSngX@DgPGWg`3M|?(|}UzBq=W(o?^eZ}zp* z>5X8uSg_|6Ayf+^OYS7uW@r2ULo~NF)9wv&?aXUfw`DJv7i1%Z%8y-P+Pen{9*U8i zn@L>gLv<1|@YYlJ%TIslCg0^E*(!(+9;SNDv#kBpgQ)w0!El)CCS+2uXgT(xshE)v zM*d`8T{@Q>5#Yx1E2-MFkHDafN8ha$Z`?6QPM>6@ILE=4O@2(pN=BNUh%QJ8hL}<1 z5eaR$@#k(V3LI*0quNs=0NQ}2+UI1q?j%zQ^WnBmK6toXpaCKsI{bX{YrmXa=)(K8 zpPg-zb=B1Z;NkT<#pCWWx%QD7z%sAD7ll8=khh$t$#x##U zH#9V2nsI7sb_jqwZ*t2}9HazCRwmvaF9?RdAJ>vfx14gtCCp3nQ|QWLzhC3NdFfQW zTg$G4!NfsyvTEyFFr`FrbRvFUvpwP9Kqv}G6d~~YeAH~;F|5UwRJ!HZJSY8O$=2vd zJb@_a8hu-=%yy||9@s0xm32e;jF zBPu6~A6I>I`%qZV8lb7JRe1ZnM0K607GWS1B&NpziHd@df*CW)D4IBNsJNzSw6=Dz zZQF^(=3j?!bdFud2LrfDreU#Ikw8?Bfs{xI(llvotY>cdJX8#-J&E1)mu+~a^7$hI z>?HMeOB0A0ag3NjEE=P=t)0j~Kd-*BhHaidU+2zS8=k2y-an)NN`C-Zic6bDFMn|W O0000VS)*8>L*$jHbT8yoxj`j(fM zYieqqSy8;M&hx;uScQW>1cAyJOM?7@862M7NCR@>JzX3_G$tk|Nc?i(=v|+p)N!c1 zsLYJZ;n8LZ>Del*N}L+2XK1ce;xy>8u-4R`%5{KsMo&+uvo4b$Q_rbYS&lCkdN8e8 xc<}AQ6K!2>ZEaj!3P7b?i*|K0x>gl1F?`P8kvnX${1(tE22WQ%mvv4FO#qYBL6HCe literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/petrock.rsi/meta.json b/Resources/Textures/Objects/Fun/petrock.rsi/meta.json new file mode 100644 index 00000000000..d39a58e623d --- /dev/null +++ b/Resources/Textures/Objects/Fun/petrock.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise Station", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "rock" + }, + { + "name": "fred" + }, + { + "name": "roxie" + } + ] +} diff --git a/Resources/Textures/Objects/Fun/petrock.rsi/rock.png b/Resources/Textures/Objects/Fun/petrock.rsi/rock.png new file mode 100644 index 0000000000000000000000000000000000000000..4f97dfeba6f1b58eb6ddb51661beb0f3f3915da8 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*$jHbT8yoxj`j(fM zYiep1-s}1Xlw~Xl@(X5gcy=QV$cguKaSYLzn4BQ-%YmbJeTq`Yq4J_KGcJcmn1prCPAj2Q>(ljS1t5lTD9na**8>L*>@u75Y4WQ(8AoJf zWXj9SeSLj3H8qWmjnAwoURURNU|OvA%-jl~dd893!RFCB!i$`HuDBOP3~W-4R~m(|y9>L*yze zqo`nK83Cquw@+zbx+NvR^i=zHdPs^wh{2BO>;3fCI|wBdYU=CjI~K0&_U>fvVh9jC c{D6(2bf(10u&`bIK+73CUHx3vIVCg!07gYq&j0`b literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/prizeticket.rsi/meta.json b/Resources/Textures/Objects/Fun/prizeticket.rsi/meta.json new file mode 100644 index 00000000000..bf0f0d3224d --- /dev/null +++ b/Resources/Textures/Objects/Fun/prizeticket.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise Station", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "ticket" + }, + { + "name": "ticket_2" + }, + { + "name": "ticket_3" + }, + { + "name": "ticket_4" + }, + { + "name": "prizeball" + } + ] +} diff --git a/Resources/Textures/Objects/Fun/prizeticket.rsi/prizeball.png b/Resources/Textures/Objects/Fun/prizeticket.rsi/prizeball.png new file mode 100644 index 0000000000000000000000000000000000000000..fd8290de14789c7629b796b6824221cb397878ae GIT binary patch literal 732 zcmV<20wev2P)@yq4(%H{LS<@Czr^TFWpip1uCz~a8%@y_P-+wJ$^@c88M z`Q`HY+3fez>GjO!^t9UVg23dq+waZh^vi5=?~0Q4keHsVwEO-3@Av!X^ZM88_Qc`x zvDof?zT&#w@T5#o=Y)&-_}Kpb;s5{t{+FNikeBI(jpXwAf4<_h+3vmG@T*c*?d-?- z`Pu*f;`jE}?(N9l@A$Ra@2}VGc)a1W+3vjE@RdJ9+}W-4^U?d1ocxxZ`uf|JqpEa% zguuLmpGZrs*6nw@;Q%EEvf1vq-0zDwIz~)SW^Z)pg^cr#mGkn?Z+U*iz=^lAbu>9U ztkvxRAq4;<20TGTMN3bbL`b(>VXaeGxwLtyqhX_*S9d2Vu-EPYAO!#-1pxm`g~Q~L ziaeH&M1(Oki8VMtMoFTaRy{&Rnv+U$BP0M+4o^ZDl8QZiD=jWEG?R=#lZ-!y!{h)} z4oN%~Ped6^K^ICt7XVWZ08$MARSy7J5CB&Y09FqGSP%eF4Xm!Y&;S4c0d!JMQvg8b z*k%9#0QE^kK~y-6V_+BsWB^7cW+o;UoYKs!Z0sDIT--do*yWk{_yq)oghfQf#3iuF zOGrvd%gD;fD<~={tEghLKuujkQ%hS%S5Kc^9E&9ehDOFFre-=?<`$M>R@OEc3V3bp z>>V7PoLyYq+&v6Ey)YDb`}q3#2LuKMhlGZOt3*U%D2S4jf+o6OiE6%NySi* zmY$KBm7SBDmtT-ssG5$cAhIYuqqwBBth^$#k~cjPQvpL-ReE}LO-*ebQ+j$mrW1fh zG&DA)gF$mq12zRf74>MQvE+fhr=~8bBZohdfvb2;h_+#sB~svpVD84M1K1 O0000L*WH8BpQ;j^sU~J#U zXMBc%TYssA^Wua2Hfd@9f5kD(1*&8$3GxeOaCmkj4akY~ba4#Pn3$X(@x_6m_xy^E zW8y|`p-M|~ayk|{+`J*`+8MB`u%l49Nq_%? v)(OZFHQVM8#t?L=<5>|W&wK-(Dh39l``jDXfAY`)TEgJz>gTe~DWM4fej7nD literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/prizeticket.rsi/ticket_2.png b/Resources/Textures/Objects/Fun/prizeticket.rsi/ticket_2.png new file mode 100644 index 0000000000000000000000000000000000000000..7e59f474e6afe60ae3ab60f57809c8af34f75458 GIT binary patch literal 296 zcmV+@0oVSCP)nvfozZ+GC-wDJ#y;?UAKl{Vo-fSNZ-TH*qFa%r#s!I zyT=&u5vwLCVyh7${ed0%B3*nx@v)txJ09QUF4FVy%9`XOSw)(FloeSbS(99gEeegS zk*aW#TE3DpT~S!nfTAGP6sQAD!3)zAD6Z1>RPbou)Z{7dK#yd5f)c6n;HTlbJU0h7 uAHF|KdIj3ju%Lh;z>$!qCDRx%b(cT?1uhZg=w2fL0000LPd@yJnJb8B3Fw{$?%5 zTycWshKNt$3L*WH8BpQ;j^xZ*zvh zxWR#e`};Kkpe$oakY6x^!?PP{Ku(0Gi(`n!#N-5tR}KLI3{%%HS<<0%XoZS~22aT0 zjtdVSJ$jL$!5}VBB*-f&D3;LjGATr)B(+q;P2$iBj=)BP5SElS#Z9_;4$%`>C0KfU ic`wGaJ-f7!fuY8h!*$u8HS>XXFnGH9xvXL*tXREa|Dod#9zIb~ zQThM>|E8_GCQqB4>7peBRKr*j5bjhC}wnoYp^fZA-7eTWf9~TU7S0KbYZEwW;&e)VbEp4|y*t=$%?{S&CEZ zg@|OA^fCSo_7Z=tUJ6*h{jf%XE5p6h;is(kSE!u$sB&YkQo)jUB{}@xS+{h{vbE_l spXl^za-ZLFE+d=s(AM%bh4!@~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/toys.rsi/abductor_agent.png b/Resources/Textures/Objects/Fun/toys.rsi/abductor_agent.png new file mode 100644 index 0000000000000000000000000000000000000000..59aefaca07e7749b974fa22339b73ab6c6497d45 GIT binary patch literal 333 zcmV-T0kZyyP)|Pft($_7uPX0004WQchC5j-~U+~ ztX=IyuRHyQadD0iL#h7@XwEc^urUSa$b2@9%Z4#k;8ixVQ25LS+8!-yHCh1{w$1i@ zf1EvB0$RLTK@ybKpfck* fXyUH*o&R87$FT@FHY1YU00000NkvXXu0mjfK|G4_ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/toys.rsi/deer.png b/Resources/Textures/Objects/Fun/toys.rsi/deer.png new file mode 100644 index 0000000000000000000000000000000000000000..d9bc621422f15d402100ccc4db92cf2945fc808b GIT binary patch literal 787 zcmV+u1MK{XP)111v!9uNc%2mvP(0~!qj84Lm(4+AC=0vHSeE*J(K4+Ip+ z`1bYN)5 z?CEPm9xE0FJst*ZKNzi-dvp^tWUb^ZJMOf@Ga6$eWw3wlW&L?;hD9tA%j22?H&WjPi;AOn0y85I!@O)e5J8V7A#NxZ6?nty1&v#A>n1Y$T9PcIZYAqyJ~0~`+o85kHjIXOc- zHDN<2O-V<0cXmidLm3zsLOL}=EgDQN5_U%&Of3>66$cj<6&M&778DXcIyWXJCKwnP zB^weM85k514$oH1WB>pF0d!JMQvg8b*k%9#0Tf9@K~y-6V_+CWfRTv_NHVkFQ^Lx? zz{U+i;J5Zs2hlRa2dhN3Iu%2{5ULO77!F-W#tlP#V#)*A}S^# zA})bL8l*r{N?Jrl7Ah|%uYjgNQAt@vRZSf#&#IxRg>Hnlj;@|QQ~|4jp^-7V0%H?X zGjl!*Rxq%%GO|WjU}I}%@8Bro4jl}w~w!%n7@BOU{G*KXc(qv!XqMu z{G*~{VtL}6E#ng~6(q9yCncw(rln_C3JMBla-*rp%J%oq$>qq)FDNWxD=sN5D@RpO zQCU?DbbL*1U427iQ*#S%E1Cgq?d=_4Mtf&hcaM+|&HxA6)!WC4M|u?C1^`{NE|(m$ RiGu(D002ovPDHLkV1iAZ1!MpK literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/toys.rsi/gnome.png b/Resources/Textures/Objects/Fun/toys.rsi/gnome.png new file mode 100644 index 0000000000000000000000000000000000000000..7fdb97a688d5b7b186d105ea4078e5b5b49669b3 GIT binary patch literal 330 zcmV-Q0k!^#P)W*ESj{|j*iSX%*2 z1+7p!m9lY;Za(WB~=ft@Z7^i6(G4KQFZ~>66i6EF2P!R+@ zgNgkNLG(ERf+fZnLWIC9;gN%Z$gFt^eC$Tl0g%KAP`2)S|Kw6jCA$?|IhXl$3rX~n%-eKyeBXYP4iz)pcQKVEL=#?3-Mjo z!IRO7?DxQy#qPJj7;CRzH!!yU3~<40;Z3gvL`PuzTN%(W4A8O+mEev7)AeQ05;-w> zy3(U??v6mF<|TMI_n>X60S?)@ss1QL>%Q?JLdOt%#fLEpW6%rnegsdi1|HvyPvEsJ zvfqM~v@KeC1ut&Hzsff!0Zl34l4&9(z)zTBoP{{)kG5r=GtBCv=4DytbzNs!xfXC< j^Z<&FPA@pmn*WhEIh+!Y{~FWU00000NkvXXu0mjfgTJQ^ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/toys.rsi/ipc.png b/Resources/Textures/Objects/Fun/toys.rsi/ipc.png new file mode 100644 index 0000000000000000000000000000000000000000..ed8aac5cea8d71131d90a21f0ebef13d924e45b7 GIT binary patch literal 335 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy-T^)#t_Kbr_`>AJbN9Nt$DPGrnVmcZbygYNiFuDnOB(F8K zE_iqEF-LCU?yJ8!&j~urKP)-3jhEAwg3Pu001;s4;@8L3;+NC0d!JMQvg8b*k%9#0Rl-x zK~yM_y^%3)!!Qs8PbyTf(jEZ^U}c_@AYf&gKz@)1xO8XPfQq~zAMgWQrlVM>;44ES z3M3#+s$92&<#D+r`p*Gawkus}%^oZ8cw~!i(apyZZ#%RLxZNLa(BVg`>2!ZNdCWk3 zH;6oaTJx=IU~{o7PP_R=$kb~V*_>ywg7>|F*XO|Nm#GoheZ}lWW!?mNmE8 zGHRK8WB4GYA4dXiQ3H|3yn*3^8Ui90=A978O6pI$u3*Q_AG5@2yXuVF*C)3pEp&+r|a6}Ii= z&X+PhX>!~y&+D|#)a>c(xH>(kOli})*E$#Solm^Tp35?wH*;sw*0QUfAFkb~RyyQt z==z#v-roJyq3TtPy?0-*f7qwpx9WPZ(B4K(m*onp?HL!{ci3Llal43TL-q5#(>wNa zE&nLW`#@xCfw#cK9>Iuvt5f_mla}w~58P=S;+4`YP~p#$#xGEOte?f?w_=~;!^^Jm vclSSK6y7Q%&!}`I3g`*G)CkWsUtb0-Ae#e-LEuvGWDw=)>gTe~DWM4fC&l8Y literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Fun/toys.rsi/plushie_slips.png b/Resources/Textures/Objects/Fun/toys.rsi/plushie_slips.png new file mode 100644 index 0000000000000000000000000000000000000000..55b389ab5680f9fe9c767066c392c9b6c2c66abd GIT binary patch literal 462 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/box-inhand-right.png b/Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/box-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..49b15d7ac2b2f45646caf8b0b6f594ce448b14f9 GIT binary patch literal 632 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 Dubaq! literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/meta.json b/Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/meta.json new file mode 100644 index 00000000000..0241de806c0 --- /dev/null +++ b/Resources/Textures/Objects/Storage/Happyhonk/rock_carrier.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by ghostprince", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "box" + }, + { + "name": "box-open" + }, + { + "name": "box-inhand-left", + "directions": 4 + }, + { + "name": "box-inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Structures/Machines/prizecounter.rsi/icon.png b/Resources/Textures/Structures/Machines/prizecounter.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4a2e7df7335b73b42ad5446541406a9a48aa5643 GIT binary patch literal 817 zcmV-11J3-3P)p)7%NqbjXCKE~#<{}ti9lH*+?1FR;&O&h<8P|^ zs|@7iGuMIsA?`nXKu1RhySuwp?T@eDiAUFrk6m5S)~;*7E;!B{N7poghPyL3)-E_8 z)xbc}WxC~}K(eB!#ZJH9kSX`c3De;)OY@6FR#(c_E~Q}^W<`;<)>iFTY9^6L)SWvw zJ4-yeMnGt*IY##o>LEDu$XQ!ipU>yhHR0&JhdVDswe zuQvo>RgX|lPc&hR#R7mNNw__pt7SlvBmfRwE|O^l(mBA)q06O>QBO}$%{DAG*0@pz zyk2kV1qo5a=l3I>w++#$f~E}UkuWNLj*$!)dK)H05sTTZ#g)Wjv4!p~neHyRtbaNj zCeS}rQydy(K$0Y~ih{*#rf__W^ZfZ2&j-LAzlE`2XQ+7Hq3*GsHsSVou9ksPky7zW zeu)J#B^zH)Yu}q!%RrCEa~2fadSpP!6z5%ZU%Coj4LoZsdQIpWSRP2Qy|G2lV6WDW zjt#RM`9^Sjgx4=;E+wY7FK zYe?uaG?jr;mgX0kn3^;sQZG}w25My>FmP8J6OXPjH*4&RsUErpf}1{qCLe5~wQTP2 v2tP!3uC+?4417p^zP81UU@HB4eiQrwW}$l%iA*<200000NkvXXu0mjftsrv! literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/prizecounter.rsi/meta.json b/Resources/Textures/Structures/Machines/prizecounter.rsi/meta.json new file mode 100644 index 00000000000..c8a01ff8d86 --- /dev/null +++ b/Resources/Textures/Structures/Machines/prizecounter.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "unlit" + }, + { + "name": "panel" + } + ] +} diff --git a/Resources/Textures/Structures/Machines/prizecounter.rsi/panel.png b/Resources/Textures/Structures/Machines/prizecounter.rsi/panel.png new file mode 100644 index 0000000000000000000000000000000000000000..65dce282de08f8ca0868d98b80d2f132f3e28665 GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=DjSL74G){)!Z!pogc6V@QPi+Y1YM85DR}FTM}B%X;*m+(Eqv z7fzOgEUbm+r(F5c1XRfIAbPR5xpDmGHA$wK>`P)EGhh4on|+?^oaOUa6xvJ}FTa(} TsK1vv6{OVD)z4*}Q$iB}ex5h( literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/prizecounter.rsi/unlit.png b/Resources/Textures/Structures/Machines/prizecounter.rsi/unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..45074c1ac4a1cbe9a64a9151997f3bdd7fc0fe12 GIT binary patch literal 444 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCilm0(?ST6Ly}S{Pf%Z|Nraj>%)YE-o1Ob#>gm4TDnU|M@&p?Td;uDq$O9D z%M=H3uJm9FGF8{s*0!^=J6&Mpsjn2B_fSC6PfS?2%&E(a)l*$r`OdXK`!+r?1D3Tb z{ZE%zUa8wzD;5j1Dx&PgK_I16666;QvcbbrP>gF{s5`X`p&`BXO`5i+*a97IvpHNd8v|Sq?l{r+=AVM+JBH9$#`V3$_xk5F z1juJQbP0l+XkK DBx$@{ literal 0 HcmV?d00001 From 794b8ebeaf5db889d008cb0bc1a866f9cc23174b Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 13 Aug 2024 17:17:16 +0000 Subject: [PATCH 096/135] Automatic Changelog Update (#654) --- Resources/Changelog/Changelog.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 164bbbb316f..15c67e383a4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5284,3 +5284,13 @@ Entries: speaking it. id: 6259 time: '2024-08-13T17:12:15.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Add + message: A ton of new plushies has arrived + - type: Add + message: >- + Prize counter are here, get your prizes by winning games and getting + prize tickets! and find prize balls!! + id: 6260 + time: '2024-08-13T17:16:52.0000000+00:00' From bebe4359d2a7c6995f6580b91c1d59a1e0c2d3a2 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:23:55 +0200 Subject: [PATCH 097/135] Revert "Early-Merge Psionic Refactor Changes" --- Content.Server/Cloning/CloningSystem.cs | 13 ----- .../StationEvents/Events/MassMindSwapRule.cs | 10 ++-- .../StationEvents/Events/NoosphericFryRule.cs | 2 +- .../Psionics/Abilities/DispelPowerSystem.cs | 32 ++++++------- .../Abilities/MetapsionicPowerSystem.cs | 36 +++++++------- .../Psionics/Abilities/MindSwapPowerSystem.cs | 32 ++++++------- .../Abilities/NoosphericZapPowerSystem.cs | 28 +++++------ .../Abilities/PsionicAbilitiesSystem.cs | 6 +-- .../PsionicRegenerationPowerSystem.cs | 24 +++++----- .../Abilities/PyrokinesisPowerSystem.cs | 30 +++++++----- .../RegenerativeStasisPowerSystem.cs | 20 ++++---- .../Abilities/TelegnosisPowerSystem.cs | 19 ++++---- .../Psionics/Glimmer/GlimmerReactiveSystem.cs | 8 ++-- .../Structures/GlimmerSourceComponent.cs | 28 ++--------- .../Structures/GlimmerStructuresSystem.cs | 47 ++----------------- .../PsionicInvisibilityPowerSystem.cs | 27 +++++------ .../Psionics/PsionicInsulationComponent.cs | 3 -- .../Psionics/SharedPsionicAbilitiesSystem.cs | 30 ------------ .../nyanotrasen/psionics/psychic-feedback.ftl | 3 -- Resources/Locale/en-US/traits/traits.ftl | 8 ++-- .../Entities/Mobs/NPCs/glimmer_creatures.yml | 1 - .../Entities/Mobs/NPCs/regalrat.yml | 1 + .../Prototypes/Entities/Mobs/NPCs/xeno.yml | 2 + .../Entities/Mobs/Player/skeleton.yml | 1 + .../Entities/Mobs/Species/human.yml | 1 + .../Entities/Clothing/Head/hats.yml | 2 - .../Structures/Research/glimmer_prober.yml | 1 - Resources/Prototypes/Traits/psionics.yml | 1 - 28 files changed, 152 insertions(+), 264 deletions(-) diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 00ffd27703e..92e658591a0 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -24,7 +24,6 @@ using Content.Shared.Mind.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Roles.Jobs; -using Content.Shared.Psionics.Abilities; using Robust.Server.Containers; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -202,18 +201,6 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity(bodyToClone, out var insul)) - { - if (clonePod.ConnectedConsole != null) - { - _chatSystem.TrySendInGameICMessage(clonePod.ConnectedConsole.Value, - Loc.GetString("cloning-console-insulation-error"), - InGameICChatType.Speak, false); - } - - return false; - } - // Check if they have the uncloneable trait if (TryComp(bodyToClone, out _)) { diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/MassMindSwapRule.cs b/Content.Server/Nyanotrasen/StationEvents/Events/MassMindSwapRule.cs index 3be2eed6387..89f3bc97501 100644 --- a/Content.Server/Nyanotrasen/StationEvents/Events/MassMindSwapRule.cs +++ b/Content.Server/Nyanotrasen/StationEvents/Events/MassMindSwapRule.cs @@ -66,11 +66,11 @@ protected override void Started(EntityUid uid, MassMindSwapRuleComponent compone // Do the swap. _mindSwap.Swap(actor, other); - //if (!component.IsTemporary) - //{ - // _mindSwap.GetTrapped(actor); - // _mindSwap.GetTrapped(other); - //} + if (!component.IsTemporary) + { + _mindSwap.GetTrapped(actor); + _mindSwap.GetTrapped(other); + } } while (true); } } diff --git a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs b/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs index d7880af9032..cf7b8e6cc9c 100644 --- a/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs +++ b/Content.Server/Nyanotrasen/StationEvents/Events/NoosphericFryRule.cs @@ -103,7 +103,7 @@ protected override void Started(EntityUid uid, NoosphericFryRuleComponent compon while (queryReactive.MoveNext(out var reactive, out _, out var xform, out var physics)) { // shoot out three bolts of lighting... - //_glimmerReactiveSystem.BeamRandomNearProber(reactive, 3, 12); + _glimmerReactiveSystem.BeamRandomNearProber(reactive, 3, 12); // try to anchor if we can if (!xform.Anchored) diff --git a/Content.Server/Psionics/Abilities/DispelPowerSystem.cs b/Content.Server/Psionics/Abilities/DispelPowerSystem.cs index 3d7d5c20c7c..73c6f5d339c 100644 --- a/Content.Server/Psionics/Abilities/DispelPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/DispelPowerSystem.cs @@ -32,7 +32,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnPowerUsed); + SubscribeLocalEvent(OnPowerUsed); SubscribeLocalEvent(OnDispelled); SubscribeLocalEvent(OnDmgDispelled); @@ -44,17 +44,18 @@ public override void Initialize() private void OnInit(EntityUid uid, DispelPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); - _actions.AddAction(uid, ref component.DispelActionEntity, component.DispelActionId); - _actions.TryGetActionData(component.DispelActionEntity, out var actionData); + _actions.AddAction(uid, ref component.DispelActionEntity, component.DispelActionId ); + _actions.TryGetActionData( component.DispelActionEntity, out var actionData ); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.DispelActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.DispelFeedback); - //It's fully intended that Dispel doesn't increase Amplification, and instead heavily spikes Dampening - //Antimage archetype. - psionic.Dampening += 1f; + _actions.StartUseDelay(component.DispelActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.DispelFeedback); + //It's fully intended that Dispel doesn't increase Amplification, and instead heavily spikes Dampening + //Antimage archetype. + psionic.Dampening += 1f; + } } private void OnShutdown(EntityUid uid, DispelPowerComponent component, ComponentShutdown args) @@ -69,9 +70,11 @@ private void OnShutdown(EntityUid uid, DispelPowerComponent component, Component } } - private void OnPowerUsed(EntityUid uid, DispelPowerComponent component, DispelPowerActionEvent args) + private void OnPowerUsed(DispelPowerActionEvent args) { - if (!_psionics.CheckCanTargetCast(uid, args.Target, out var psionic)) + if (HasComp(args.Target) || HasComp(args.Performer)) + return; + if (!TryComp(args.Performer, out var psionic) || !HasComp(args.Target)) return; var ev = new DispelledEvent(); @@ -79,9 +82,6 @@ private void OnPowerUsed(EntityUid uid, DispelPowerComponent component, DispelPo if (ev.Handled) { - _actions.TryGetActionData(component.DispelActionEntity, out var actionData); - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.DispelActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); args.Handled = true; _psionics.LogPowerUsed(args.Performer, "dispel", psionic, 1, 1, true); diff --git a/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs b/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs index a1b40b92320..8c72a02737b 100644 --- a/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs @@ -33,30 +33,32 @@ public override void Initialize() private void OnInit(EntityUid uid, MetapsionicPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); if (!TryComp(uid, out ActionsComponent? comp)) return; _actions.AddAction(uid, ref component.ActionWideMetapsionicEntity, component.ActionWideMetapsionic, component: comp); _actions.AddAction(uid, ref component.ActionFocusedMetapsionicEntity, component.ActionFocusedMetapsionic, component: comp); - UpdateActions(uid, component, psionic); + _actions.TryGetActionData(component.ActionWideMetapsionicEntity, out var actionData); + if (actionData is { UseDelay: not null }) + { + _actions.StartUseDelay(component.ActionWideMetapsionicEntity); + _actions.StartUseDelay(component.ActionFocusedMetapsionicEntity); + } + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.MetapsionicFeedback); + psionic.Amplification += 0.1f; + psionic.Dampening += 0.5f; + } - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.MetapsionicFeedback); - psionic.Amplification += 0.1f; - psionic.Dampening += 0.5f; } - private void UpdateActions(EntityUid uid, MetapsionicPowerComponent? component = null, PsionicComponent? psionic = null) + private void UpdateActions(EntityUid uid, MetapsionicPowerComponent? component = null) { - if (!Resolve(uid, ref component) || !Resolve(uid, ref psionic) - || !_actions.TryGetActionData(component.ActionWideMetapsionicEntity, out var actionData)) + if (!Resolve(uid, ref component)) return; - - if (actionData is { UseDelay: not null }) - { - _actions.SetCooldown(component.ActionWideMetapsionicEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - _actions.SetCooldown(component.ActionFocusedMetapsionicEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - } + _actions.StartUseDelay(component.ActionWideMetapsionicEntity); + _actions.StartUseDelay(component.ActionFocusedMetapsionicEntity); } private void OnShutdown(EntityUid uid, MetapsionicPowerComponent component, ComponentShutdown args) @@ -93,7 +95,7 @@ private void OnWidePowerUsed(EntityUid uid, MetapsionicPowerComponent component, } _popups.PopupEntity(Loc.GetString("metapsionic-pulse-failure"), uid, uid, PopupType.Large); _psionics.LogPowerUsed(uid, "metapsionic pulse", psionic, 2, 4); - UpdateActions(uid, component, psionic); + UpdateActions(uid, component); args.Handled = true; } @@ -126,7 +128,7 @@ private void OnFocusedPowerUsed(FocusedMetapsionicPowerActionEvent args) _psionics.LogPowerUsed(args.Performer, "focused metapsionic pulse", psionic, 3, 6); args.Handled = true; - UpdateActions(args.Performer, component, psionic); + UpdateActions(args.Performer, component); } private void OnDoAfter(EntityUid uid, MetapsionicPowerComponent component, FocusedMetapsionicDoAfterEvent args) diff --git a/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs b/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs index b4129581ec1..25f0434c797 100644 --- a/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs @@ -29,7 +29,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnPowerUsed); + SubscribeLocalEvent(OnPowerUsed); SubscribeLocalEvent(OnPowerReturned); SubscribeLocalEvent(OnDispelled); SubscribeLocalEvent(OnMobStateChanged); @@ -41,15 +41,16 @@ public override void Initialize() private void OnInit(EntityUid uid, MindSwapPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); _actions.AddAction(uid, ref component.MindSwapActionEntity, component.MindSwapActionId); - _actions.TryGetActionData(component.MindSwapActionEntity, out var actionData); + _actions.TryGetActionData( component.MindSwapActionEntity, out var actionData); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.MindSwapActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.MindSwapFeedback); - psionic.Amplification += 1f; + _actions.StartUseDelay(component.MindSwapActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.MindSwapFeedback); + psionic.Amplification += 1f; + } } private void OnShutdown(EntityUid uid, MindSwapPowerComponent component, ComponentShutdown args) @@ -63,16 +64,17 @@ private void OnShutdown(EntityUid uid, MindSwapPowerComponent component, Compone } } - private void OnPowerUsed(EntityUid uid, MindSwapPowerComponent component, MindSwapPowerActionEvent args) + private void OnPowerUsed(MindSwapPowerActionEvent args) { - if (!(TryComp(args.Target, out var damageable) && damageable.DamageContainerID == "Biological") - || !_psionics.CheckCanTargetCast(uid, args.Target, out var psionic)) + if (!(TryComp(args.Target, out var damageable) && damageable.DamageContainerID == "Biological")) return; - _actions.TryGetActionData(component.MindSwapActionEntity, out var actionData); - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.MindSwapActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); + if (HasComp(args.Target)) + return; + + if (!TryComp(args.Performer, out var psionic)) + return; Swap(args.Performer, args.Target); @@ -157,8 +159,6 @@ private void OnSwapInit(EntityUid uid, MindSwappedComponent component, Component { psionic.ActivePowers.Add(component); psionic.PsychicFeedback.Add(component.MindSwappedFeedback); - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.MindSwapReturnActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); } } diff --git a/Content.Server/Psionics/Abilities/NoosphericZapPowerSystem.cs b/Content.Server/Psionics/Abilities/NoosphericZapPowerSystem.cs index a1776acbd3c..ffadc61c199 100644 --- a/Content.Server/Psionics/Abilities/NoosphericZapPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/NoosphericZapPowerSystem.cs @@ -23,20 +23,21 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnPowerUsed); + SubscribeLocalEvent(OnPowerUsed); } private void OnInit(EntityUid uid, NoosphericZapPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); _actions.AddAction(uid, ref component.NoosphericZapActionEntity, component.NoosphericZapActionId ); - _actions.TryGetActionData(component.NoosphericZapActionEntity, out var actionData); + _actions.TryGetActionData( component.NoosphericZapActionEntity, out var actionData ); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.NoosphericZapActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.NoosphericZapFeedback); - psionic.Amplification += 1f; + _actions.StartUseDelay(component.NoosphericZapActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.NoosphericZapFeedback); + psionic.Amplification += 1f; + } } private void OnShutdown(EntityUid uid, NoosphericZapPowerComponent component, ComponentShutdown args) @@ -50,14 +51,13 @@ private void OnShutdown(EntityUid uid, NoosphericZapPowerComponent component, Co } } - private void OnPowerUsed(EntityUid uid, NoosphericZapPowerComponent component, NoosphericZapPowerActionEvent args) + private void OnPowerUsed(NoosphericZapPowerActionEvent args) { - if (_psionics.CheckCanTargetCast(uid, args.Target, out var psionic)) - { + if (!TryComp(args.Performer, out var psionic)) + return; - _actions.TryGetActionData(component.NoosphericZapActionEntity, out var actionData); - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.NoosphericZapActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); + if (!HasComp(args.Performer)) + { _beam.TryCreateBeam(args.Performer, args.Target, "LightningNoospheric"); _stunSystem.TryParalyze(args.Target, TimeSpan.FromSeconds(1 * psionic.Amplification), false); diff --git a/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs b/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs index d65186309d3..24e6bbb8d3b 100644 --- a/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs +++ b/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs @@ -7,7 +7,6 @@ using Robust.Shared.Random; using Robust.Shared.Prototypes; using Content.Shared.Popups; -using Robust.Shared.Serialization.Manager; namespace Content.Server.Psionics.Abilities { @@ -20,7 +19,6 @@ public sealed class PsionicAbilitiesSystem : EntitySystem [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedPopupSystem _popups = default!; - [Dependency] private readonly ISerializationManager _serialization = default!; public override void Initialize() { @@ -52,7 +50,7 @@ public void AddRandomPsionicPower(EntityUid uid) return; } - var newPool = _serialization.CreateCopy(pool, null, false, true); + var newPool = pool; foreach (var component in pool.Weights.Keys) { var checkedComponent = _componentFactory.GetComponent(component); @@ -75,8 +73,6 @@ public void RemovePsionics(EntityUid uid) if (RemComp(uid)) { _popups.PopupEntity(Loc.GetString("mindbreaking-feedback", ("entity", uid)), uid, PopupType.Medium); - EnsureComp(uid, out var insul); - insul.MindBroken = true; } if (!TryComp(uid, out var psionic)) diff --git a/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs b/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs index f675cc6ed89..15fc092ebcf 100644 --- a/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs @@ -39,16 +39,17 @@ public override void Initialize() private void OnInit(EntityUid uid, PsionicRegenerationPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); - _actions.AddAction(uid, ref component.PsionicRegenerationActionEntity, component.PsionicRegenerationActionId); - _actions.TryGetActionData(component.PsionicRegenerationActionEntity, out var actionData); + _actions.AddAction(uid, ref component.PsionicRegenerationActionEntity, component.PsionicRegenerationActionId ); + _actions.TryGetActionData( component.PsionicRegenerationActionEntity, out var actionData ); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.PsionicRegenerationActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.RegenerationFeedback); - psionic.Amplification += 0.5f; - psionic.Dampening += 0.5f; + _actions.StartUseDelay(component.PsionicRegenerationActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.RegenerationFeedback); + psionic.Amplification += 0.5f; + psionic.Dampening += 0.5f; + } } private void OnPowerUsed(EntityUid uid, PsionicRegenerationPowerComponent component, PsionicRegenerationPowerActionEvent args) @@ -65,9 +66,6 @@ private void OnPowerUsed(EntityUid uid, PsionicRegenerationPowerComponent compon if (actionData != null && actionData.Cooldown.HasValue && actionData.Cooldown.Value.End > curTime) return; - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.PsionicRegenerationActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - _doAfterSystem.TryStartDoAfter(doAfterArgs, out var doAfterId); component.DoAfter = doAfterId; @@ -118,7 +116,7 @@ private void OnMobStateChangedEvent(EntityUid uid, PsionicRegenerationPowerCompo _psionics.LogPowerUsed(uid, "psionic regeneration", psionic, 10, 20); - _actions.SetCooldown(component.PsionicRegenerationActionEntity, 2 * (actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification))); + _actions.StartUseDelay(component.PsionicRegenerationActionEntity); } } } diff --git a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs index 62e0c3ce56c..f3e2cc69fd5 100644 --- a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs @@ -4,9 +4,10 @@ using Content.Shared.Psionics.Glimmer; using Content.Server.Atmos.Components; using Content.Server.Weapons.Ranged.Systems; +using Robust.Server.GameObjects; using Content.Shared.Actions.Events; using Content.Server.Explosion.Components; -using Robust.Shared.Audio.Systems; +using Robust.Server.Audio; using Robust.Shared.Timing; using Content.Shared.Popups; using Content.Shared.Psionics.Events; @@ -16,13 +17,13 @@ namespace Content.Server.Psionics.Abilities { public sealed class PyrokinesisPowerSystem : EntitySystem { - [Dependency] private readonly SharedTransformSystem _xform = default!; + [Dependency] private readonly TransformSystem _xform = default!; [Dependency] private readonly SharedActionsSystem _actions = default!; [Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!; [Dependency] private readonly GunSystem _gunSystem = default!; [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly AudioSystem _audioSystem = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; public override void Initialize() @@ -37,26 +38,28 @@ public override void Initialize() private void OnInit(EntityUid uid, PyrokinesisPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); _actions.AddAction(uid, ref component.PyrokinesisPrechargeActionEntity, component.PyrokinesisPrechargeActionId); _actions.TryGetActionData(component.PyrokinesisPrechargeActionEntity, out var actionData); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.PyrokinesisPrechargeActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.PyrokinesisFeedback); - psionic.Amplification += 1f; + _actions.StartUseDelay(component.PyrokinesisPrechargeActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.PyrokinesisFeedback); + psionic.Amplification += 1f; + } } private void OnPrecharge(PyrokinesisPrechargeActionEvent args) { - if (_psionics.CheckCanSelfCast(args.Performer, out var psionic) + if (!HasComp(args.Performer) + && TryComp(args.Performer, out var psionic) && TryComp(args.Performer, out var pyroComp)) { _actions.AddAction(args.Performer, ref pyroComp.PyrokinesisActionEntity, pyroComp.PyrokinesisActionId); _actions.TryGetActionData(pyroComp.PyrokinesisActionEntity, out var actionData); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(pyroComp.PyrokinesisActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); + _actions.StartUseDelay(pyroComp.PyrokinesisActionEntity); _actions.TryGetActionData(pyroComp.PyrokinesisPrechargeActionEntity, out var prechargeData); if (prechargeData is { UseDelay: not null }) _actions.StartUseDelay(pyroComp.PyrokinesisPrechargeActionEntity); @@ -97,14 +100,15 @@ private void OnShutdown(EntityUid uid, PyrokinesisPowerComponent component, Comp private void OnPowerUsed(PyrokinesisPowerActionEvent args) { - if (_psionics.CheckCanSelfCast(args.Performer, out var psionic) + if (!HasComp(args.Performer) + && TryComp(args.Performer, out var psionic) && TryComp(args.Performer, out var pyroComp)) { var spawnCoords = Transform(args.Performer).Coordinates; var ent = Spawn("ProjectileAnomalyFireball", spawnCoords); - if (_glimmerSystem.GlimmerOutput <= 25 * psionic.Dampening) + if (_glimmerSystem.GlimmerOutput >= 25 * psionic.Dampening) EnsureComp(ent); if (TryComp(ent, out var fireball)) diff --git a/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs b/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs index 87ec5adbce8..cc67badbe72 100644 --- a/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs @@ -26,16 +26,17 @@ public override void Initialize() private void OnInit(EntityUid uid, RegenerativeStasisPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); _actions.AddAction(uid, ref component.RegenerativeStasisActionEntity, component.RegenerativeStasisActionId); _actions.TryGetActionData(component.RegenerativeStasisActionEntity, out var actionData); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.RegenerativeStasisActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.RegenerativeStasisFeedback); - psionic.Amplification += 0.5f; - psionic.Dampening += 0.5f; + _actions.StartUseDelay(component.RegenerativeStasisActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.RegenerativeStasisFeedback); + psionic.Amplification += 0.5f; + psionic.Dampening += 0.5f; + } } private void OnShutdown(EntityUid uid, RegenerativeStasisPowerComponent component, ComponentShutdown args) @@ -62,11 +63,8 @@ private void OnPowerUsed(EntityUid uid, RegenerativeStasisPowerComponent compone solution.AddReagent("Epinephrine", FixedPoint2.New(MathF.Min(2.5f * psionic.Dampening + psionic.Amplification, 15f))); solution.AddReagent("Nocturine", 10f + (1 * psionic.Amplification + psionic.Dampening)); _bloodstreamSystem.TryAddToChemicals(args.Target, solution, stream); - _popupSystem.PopupEntity(Loc.GetString("regenerative-stasis-begin", ("entity", args.Target)), args.Target, PopupType.Medium); + _popupSystem.PopupEntity(Loc.GetString("regenerative-stasis-begin", ("entity", uid)), uid, PopupType.Medium); _psionics.LogPowerUsed(uid, "regenerative stasis", psionic, 4, 6); - _actions.TryGetActionData(component.RegenerativeStasisActionEntity, out var actionData); - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.RegenerativeStasisActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); args.Handled = true; } } diff --git a/Content.Server/Psionics/Abilities/TelegnosisPowerSystem.cs b/Content.Server/Psionics/Abilities/TelegnosisPowerSystem.cs index 95b7995e673..c5f8471a654 100644 --- a/Content.Server/Psionics/Abilities/TelegnosisPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/TelegnosisPowerSystem.cs @@ -27,16 +27,17 @@ public override void Initialize() private void OnInit(EntityUid uid, TelegnosisPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); _actions.AddAction(uid, ref component.TelegnosisActionEntity, component.TelegnosisActionId ); _actions.TryGetActionData( component.TelegnosisActionEntity, out var actionData ); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.TelegnosisActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.TelegnosisFeedback); - psionic.Amplification += 0.3f; - psionic.Dampening += 0.3f; + _actions.StartUseDelay(component.TelegnosisActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.TelegnosisFeedback); + psionic.Amplification += 0.3f; + psionic.Dampening += 0.3f; + } } private void OnShutdown(EntityUid uid, TelegnosisPowerComponent component, ComponentShutdown args) @@ -66,10 +67,6 @@ private void OnPowerUsed(EntityUid uid, TelegnosisPowerComponent component, Tele component.ProjectionUid = projection; _mindSwap.Swap(uid, projection); - _actions.TryGetActionData( component.TelegnosisActionEntity, out var actionData ); - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.TelegnosisActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - if (EnsureComp(projection, out var projectionComponent)) projectionComponent.OriginalEntity = uid; diff --git a/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs b/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs index 584b1a61e2c..85034574885 100644 --- a/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs +++ b/Content.Server/Psionics/Glimmer/GlimmerReactiveSystem.cs @@ -374,10 +374,10 @@ public override void Update(float frameTime) _ghostSystem.MakeVisible(true); _revenantSystem.MakeVisible(true); GhostsVisible = true; - //foreach (var reactive in reactives) - //{ - // BeamRandomNearProber(reactive.Owner, 1, 12); - //} + foreach (var reactive in reactives) + { + BeamRandomNearProber(reactive.Owner, 1, 12); + } } else if (GhostsVisible == true) { _ghostSystem.MakeVisible(false); diff --git a/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs index 34cdba29bb2..5babb6c446d 100644 --- a/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs +++ b/Content.Server/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs @@ -6,42 +6,22 @@ namespace Content.Server.Psionics.Glimmer ///
public sealed partial class GlimmerSourceComponent : Component { - [DataField] + [DataField("accumulator")] public float Accumulator = 0f; - [DataField] + [DataField("active")] public bool Active = true; /// /// Since glimmer is an int, we'll do it like this. /// - [DataField] + [DataField("secondsPerGlimmer")] public float SecondsPerGlimmer = 10f; /// /// True if it produces glimmer, false if it subtracts it. /// - [DataField] + [DataField("addToGlimmer")] public bool AddToGlimmer = true; - - /// - /// If not null, this entity generates this value as a baseline number of research points per second, eg: Probers. - /// Actual glimmer research sources will scale with GlimmerEquilibriumRatio - /// - [DataField] - public int? ResearchPointGeneration = null; - - /// - /// Controls whether this entity requires electrical power to generate research points. - /// - [DataField] - public bool RequiresPower = true; - - /// - /// Above GlimmerEquilibrium, glimmer generation is increased exponentially, but has an offset to prevent things from spiralling out of control. - /// Increasing the offset will make this entity's exponential growth weaker, while decreasing it makes it stronger. Negative numbers are valid by the way :) - /// - [DataField] - public int GlimmerExponentOffset = 0; } } diff --git a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs index 76ff5a823b3..309bd732ef7 100644 --- a/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs +++ b/Content.Server/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs @@ -1,7 +1,6 @@ using Content.Server.Anomaly.Components; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; -using Content.Server.Research.Components; using Content.Shared.Anomaly.Components; using Content.Shared.Mobs; using Content.Shared.Psionics.Glimmer; @@ -25,17 +24,6 @@ public override void Initialize() SubscribeLocalEvent(OnAnomalyPulse); SubscribeLocalEvent(OnAnomalySupercritical); SubscribeLocalEvent(OnMobStateChanged); - SubscribeLocalEvent(OnInit); - } - - private void OnInit(EntityUid uid, GlimmerSourceComponent component, ComponentStartup args) - { - if (component.ResearchPointGeneration != null) - { - EnsureComp(uid, out var points); - points.PointsPerSecond = component.ResearchPointGeneration.Value; - points.Active = true; - } } private void OnAnomalyVesselPowerChanged(EntityUid uid, AnomalyVesselComponent component, ref PowerChangedEvent args) @@ -59,7 +47,7 @@ private void OnAnomalyPulse(EntityUid uid, GlimmerSourceComponent component, ref // component. if (TryComp(uid, out var anomaly)) - _glimmerSystem.DeltaGlimmerOutput(5f * anomaly.Severity); + _glimmerSystem.DeltaGlimmerInput(5f * anomaly.Severity); } private void OnAnomalySupercritical(EntityUid uid, GlimmerSourceComponent component, ref AnomalySupercriticalEvent args) @@ -76,56 +64,31 @@ private void OnMobStateChanged(EntityUid uid, GlimmerSourceComponent component, public override void Update(float frameTime) { base.Update(frameTime); - var glimmerSources = Count(); foreach (var source in EntityQuery()) { - if (!_powerReceiverSystem.IsPowered(source.Owner) - && source.RequiresPower) - { - glimmerSources--; + if (!_powerReceiverSystem.IsPowered(source.Owner)) continue; - } if (!source.Active) - { - glimmerSources--; continue; - } source.Accumulator += frameTime; if (source.Accumulator > source.SecondsPerGlimmer) { + var glimmerEquilibrium = GlimmerSystem.GlimmerEquilibrium; source.Accumulator -= source.SecondsPerGlimmer; - // https://www.desmos.com/calculator/zjzefpue03 - // In Short: 1 prober makes 20 research points. 4 probers makes twice as many points as 1 prober. 9 probers makes 69 points in total between all 9. - // This is then modified by afterwards by GlimmerEquilibrium, to help smooth out the curves. But also, now if you have more drainers than probers, the probers won't generate research! - // Also, this counts things like Anomalies & Glimmer Mites! Which means scientists should be more encouraged to actively hunt mites. - // As a fun novelty, this means that a highly psionic Epistemics department can essentially "Study" their powers for actual research points! - if (source.ResearchPointGeneration != null - && TryComp(source.Owner, out var research)) - research.PointsPerSecond = (int) MathF.Round( - source.ResearchPointGeneration.Value / (MathF.Log(glimmerSources, 4) + 1) - * _glimmerSystem.GetGlimmerEquilibriumRatio()); - // Shorthand explanation: // This makes glimmer far more "Swingy", by making both positive and negative glimmer sources scale quite dramatically with glimmer - if (!_glimmerSystem.GetGlimmerEnabled()) - return; - - var glimmerEquilibrium = GlimmerSystem.GlimmerEquilibrium; - if (source.AddToGlimmer) { - _glimmerSystem.DeltaGlimmerInput((_glimmerSystem.GlimmerOutput > glimmerEquilibrium - ? MathF.Pow(_glimmerSystem.GetGlimmerOutputInteger() - source.GlimmerExponentOffset + glimmerSources, 2) : 1f) + _glimmerSystem.DeltaGlimmerInput((_glimmerSystem.GlimmerOutput > glimmerEquilibrium ? _glimmerSystem.GetGlimmerOutputInteger() : 1f) * (_glimmerSystem.GlimmerOutput < glimmerEquilibrium ? _glimmerSystem.GetGlimmerEquilibriumRatio() : 1f)); } else { - _glimmerSystem.DeltaGlimmerInput(-(_glimmerSystem.GlimmerOutput > glimmerEquilibrium - ? MathF.Pow(_glimmerSystem.GetGlimmerOutputInteger() - source.GlimmerExponentOffset + glimmerSources, 2) : 1f) + _glimmerSystem.DeltaGlimmerInput(-(_glimmerSystem.GlimmerOutput > glimmerEquilibrium ? _glimmerSystem.GetGlimmerOutputInteger() : 1f) * (_glimmerSystem.GlimmerOutput > glimmerEquilibrium ? _glimmerSystem.GetGlimmerEquilibriumRatio() : 1f)); } } diff --git a/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerSystem.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerSystem.cs index 0eeb7ec280d..540dc03341b 100644 --- a/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerSystem.cs +++ b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerSystem.cs @@ -40,20 +40,20 @@ public override void Initialize() SubscribeLocalEvent(OnShootAttempt); SubscribeLocalEvent(OnThrowAttempt); SubscribeLocalEvent(OnInsulated); - SubscribeLocalEvent(OnDoAfter); } private void OnInit(EntityUid uid, PsionicInvisibilityPowerComponent component, ComponentInit args) { - EnsureComp(uid, out var psionic); _actions.AddAction(uid, ref component.PsionicInvisibilityActionEntity, component.PsionicInvisibilityActionId); - _actions.TryGetActionData(component.PsionicInvisibilityActionEntity, out var actionData); + _actions.TryGetActionData( component.PsionicInvisibilityActionEntity, out var actionData); if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.PsionicInvisibilityActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); - - psionic.ActivePowers.Add(component); - psionic.PsychicFeedback.Add(component.InvisibilityFeedback); - psionic.Amplification += 0.5f; + _actions.StartUseDelay(component.PsionicInvisibilityActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.InvisibilityFeedback); + psionic.Amplification += 0.5f; + } } private void OnShutdown(EntityUid uid, PsionicInvisibilityPowerComponent component, ComponentShutdown args) @@ -71,7 +71,10 @@ private void OnShutdown(EntityUid uid, PsionicInvisibilityPowerComponent compone private void OnPowerUsed(EntityUid uid, PsionicInvisibilityPowerComponent component, PsionicInvisibilityPowerActionEvent args) { - if (!_psionics.CheckCanSelfCast(uid, out var psionic)) + if (!TryComp(uid, out var psionic)) + return; + + if (HasComp(uid)) return; var ev = new PsionicInvisibilityTimerEvent(_gameTiming.CurTime); @@ -88,10 +91,6 @@ private void OnPowerUsed(EntityUid uid, PsionicInvisibilityPowerComponent compon _psionics.LogPowerUsed(uid, "psionic invisibility", psionic, 8, 12); args.Handled = true; } - - _actions.TryGetActionData(component.PsionicInvisibilityActionEntity, out var actionData); - if (actionData is { UseDelay: not null }) - _actions.SetCooldown(component.PsionicInvisibilityActionEntity, actionData.UseDelay.Value - TimeSpan.FromSeconds(psionic.Dampening + psionic.Amplification)); } private void OnPowerOff(RemovePsionicInvisibilityOffPowerActionEvent args) @@ -163,7 +162,7 @@ public void ToggleInvisibility(EntityUid uid) } } - private void OnDoAfter(EntityUid uid, PsionicInvisibilityPowerComponent component, PsionicInvisibilityTimerEvent args) + public void OnDoAfter(EntityUid uid, PsionicInvisibilityPowerComponent component, PsionicInvisibilityTimerEvent args) { if (!args.Cancelled) RemComp(uid); diff --git a/Content.Shared/Psionics/PsionicInsulationComponent.cs b/Content.Shared/Psionics/PsionicInsulationComponent.cs index 4b999523bca..2ab054b1f8f 100644 --- a/Content.Shared/Psionics/PsionicInsulationComponent.cs +++ b/Content.Shared/Psionics/PsionicInsulationComponent.cs @@ -6,8 +6,5 @@ public sealed partial class PsionicInsulationComponent : Component public bool Passthrough = false; public List SuppressedFactions = new(); - - [DataField] - public bool MindBroken = false; } } diff --git a/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs b/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs index fda1ef4fd40..4dd8fa2442f 100644 --- a/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs +++ b/Content.Shared/Psionics/SharedPsionicAbilitiesSystem.cs @@ -1,12 +1,9 @@ -using System.Diagnostics.CodeAnalysis; using Content.Shared.Actions; using Content.Shared.Administration.Logs; -using Content.Shared.Examine; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Popups; using Content.Shared.Psionics.Glimmer; -using Robust.Shared.Network; using Robust.Shared.Random; using Robust.Shared.Serialization; @@ -20,7 +17,6 @@ public sealed class SharedPsionicAbilitiesSystem : EntitySystem [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; - [Dependency] private readonly INetManager _net = default!; public override void Initialize() { @@ -28,7 +24,6 @@ public override void Initialize() SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnPowerUsed); - SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnMobStateChanged); } @@ -81,37 +76,12 @@ public void SetPsionicsThroughEligibility(EntityUid uid) _actions.SetEnabled(uid, IsEligibleForPsionics(uid)); } - private void OnExamined(EntityUid uid, PsionicInsulationComponent component, ExaminedEvent args) - { - if (!component.MindBroken || !args.IsInDetailsRange) - return; - - args.PushMarkup($"[color=mediumpurple]{Loc.GetString("examine-mindbroken-message", ("entity", uid))}[/color]"); - } - private bool IsEligibleForPsionics(EntityUid uid) { return !HasComp(uid) && (!TryComp(uid, out var mobstate) || mobstate.CurrentState == MobState.Alive); } - public bool CheckCanSelfCast(EntityUid uid, [NotNullWhen(true)] out PsionicComponent? psiComp) - { - if (!HasComp(uid)) - return TryComp(uid, out psiComp); - psiComp = null; - return false; - } - - public bool CheckCanTargetCast(EntityUid performer, EntityUid target, [NotNullWhen(true)] out PsionicComponent? psiComp) - { - if (!HasComp(performer) - && !HasComp(target)) - return TryComp(performer, out psiComp); - psiComp = null; - return false; - } - public void LogPowerUsed(EntityUid uid, string power, PsionicComponent? psionic = null, int minGlimmer = 8, int maxGlimmer = 12, bool overrideGlimmer = false) { _adminLogger.Add(Database.LogType.Psionics, Database.LogImpact.Medium, $"{ToPrettyString(uid):player} used {power}"); diff --git a/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl b/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl index 76e67a5a02d..311d71d6ac7 100644 --- a/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl +++ b/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl @@ -51,6 +51,3 @@ pyrokinesis-refund-cooldown = You reclaim some of the energy spent drawing forth # Misc Psionic Messages telepathic-mute-message = You strain, but are unable to send your thoughts to the Noosphere -examine-mindbroken-message = Eyes unblinking, staring listfully into the horizon. {CAPITALIZE($entity)} is a sack of meat pretending it has a soul. - There is nothing behind its gaze. -cloning-console-insulation-error = ERROR: NON-SOPHONT LOADED, NO SOUL FOUND. diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 9bc453f50a0..be90a388260 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -41,10 +41,10 @@ trait-description-LatentPsychic = Your mind and soul are open to the noosphere, It is possible that you may be hunted by otherworldly forces, so consider keeping your powers a secret. trait-name-PsionicInsulation = χ Waveform Misalignment -trait-description-PsionicInsulation = You are a flesh automaton animated by neurotransmitters. Within your skull lies a - 1.5kg sack of meat pretending at sentience. By modern epistemiological theory, you aren't even a sophont. - The good news is that you are immune to most positive and negative effects of psychic powers. There may be other - consequences to this malady. +trait-description-PsionicInsulation = Through a quirk of fate, your brainwaves are permanently out of phase with the noösphere + You are immune to both positive and negative effects of nearly all psychic powers, + But you can never be a psionic yourself in this life. This trait is incompatible with + all other psychic traits. trait-name-NaturalTelepath = Natural Telepath trait-description-NaturalTelepath = As a naturally occuring Telepath, you are capable of fluent telepathic communication, regardless of diff --git a/Resources/Prototypes/DeltaV/Entities/Mobs/NPCs/glimmer_creatures.yml b/Resources/Prototypes/DeltaV/Entities/Mobs/NPCs/glimmer_creatures.yml index d0982c81744..1f1000f04a7 100644 --- a/Resources/Prototypes/DeltaV/Entities/Mobs/NPCs/glimmer_creatures.yml +++ b/Resources/Prototypes/DeltaV/Entities/Mobs/NPCs/glimmer_creatures.yml @@ -29,7 +29,6 @@ psychicFeedback: - "glimmer-mite-feedback" - type: GlimmerSource - glimmerExponentOffset: 3 - type: AmbientSound range: 6 volume: -3 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml index cf563989bf5..d1b3bd6a6a9 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -118,6 +118,7 @@ - type: Grammar attributes: gender: male + - type: PotentialPsionic # Nyano - type: LanguageKnowledge speaks: - GalacticCommon diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index d618e407134..397989643e6 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -121,6 +121,8 @@ molsPerSecondPerUnitMass: 0.0005 - type: Speech speechVerb: LargeMob + - type: PotentialPsionic #Nyano - Summary: makes potentially psionic. + chance: -2 - type: Psionic #Nyano - Summary: makes psionic by default. removable: false - type: LanguageKnowledge diff --git a/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml index f9132ce0ea0..bf41f2dda6e 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml @@ -8,6 +8,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others + - type: PotentialPsionic #Nyano - Summary: makes potentially psionic. - type: entity name: skeleton pirate diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index ac373725ce4..e00e06279e5 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -16,6 +16,7 @@ spawned: - id: FoodMeatHuman amount: 5 + - type: PotentialPsionic #Nyano - Summary: makes potentially psionic. - type: LanguageKnowledge speaks: - GalacticCommon diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml index 781e42c1728..83e3756c0f2 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml @@ -113,8 +113,6 @@ sprite: Nyanotrasen/Clothing/Head/Helmets/insulative_skullcap.rsi - type: Clothing sprite: Nyanotrasen/Clothing/Head/Helmets/insulative_skullcap.rsi - - type: TinfoilHat - destroyOnFry: false - type: Armor modifiers: coefficients: diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml index 161c5b4ef52..eca5b5e3758 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml @@ -11,7 +11,6 @@ psychicFeedback: - "prober-feedback" - type: GlimmerSource - researchPointGeneration: 20 - type: Construction graph: GlimmerDevices node: glimmerProber diff --git a/Resources/Prototypes/Traits/psionics.yml b/Resources/Prototypes/Traits/psionics.yml index b896a8f745c..277070617cf 100644 --- a/Resources/Prototypes/Traits/psionics.yml +++ b/Resources/Prototypes/Traits/psionics.yml @@ -17,7 +17,6 @@ points: -5 components: - type: PsionicInsulation - mindBroken: true requirements: - !type:CharacterTraitRequirement inverted: true From ecfed3e5a7a6d6ea079c034abd7836125da847b3 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Wed, 14 Aug 2024 05:12:45 +0800 Subject: [PATCH 098/135] Oni Pointy Ears And Tusks (#727) # Description Adds eight pointy ears, two tusks, one feet marking (toes resembling WarCraft trolls) and human nose markings to Onis. The pointed ears are a big reference to tieflings (similar to Onis) who often have them. Onis will now have pointy ears by default, but there is a marking to disable ears. 5 human nose markings have all been made available to Onis, Harpies, and Felinids. Onis and Felinids can now get chest scars, originally humna-only. The tusk markings are originally from Frontier goblins. The new pointy ears give players the power to make their Onis look like **tieflings, orcs, elves, goblins**, and more fantasy races. These markings can potentially be used in the future for other species like psionic elves. ## Media **Blood Elf** (Tall Ears) ![image](https://github.com/user-attachments/assets/257c8839-303c-45b2-b129-3f9183e47695)
See more **Orc** (Upward Ears, Large Tusks) ![image](https://github.com/user-attachments/assets/46bac694-de88-4e04-a12b-7ff8a8111e7b) **Night Elf** (Wide Ears) ![image](https://github.com/user-attachments/assets/18813660-cd2c-4d37-800d-bf84b1d7dee5) **Night Elf** (Slanted Ears) ![image](https://github.com/user-attachments/assets/7f39457b-875d-4c46-a5fb-428a6a535fb1) **Troll** (Large Ears, Small Tusks, Two-Toed Feet) ![image](https://github.com/user-attachments/assets/d9a0c52e-020d-4b55-bb7e-7a4afed61dcc) **Character Setup** ![image](https://github.com/user-attachments/assets/35ba27d4-e6d1-4c52-bbc7-0f057df12fc8) ![image](https://github.com/user-attachments/assets/5d9e7690-7118-48b3-95b9-50ee784660e2)
## Changelog :cl: Skubman - add: Onis have received eight new pointy ear markings in the 'Head (Side)' section that can help them resemble tieflings, orcs, elves, goblins, trolls, and more. - add: Onis get two new tusk markings in the 'Snout' section, and a Two-Toed feet marking in the 'Legs' section. - add: Felinids, Onis, and Harpies can now select Human nose markings like the schnozz, blobby nose, and nubby nose. - add: Felinids and Onis can now select the Chest Scar and Top Surgery Scar markings. - tweak: Default Onis now use the Double Curved horn and Upward Ears markings. --- .../Locale/en-US/markings/goblin_markings.ftl | 9 ++ Resources/Locale/en-US/markings/oni_feet.ftl | 2 + .../Locale/en-US/markings/pointy_ears.ftl | 26 +++++ .../Customization/Markings/human_noses.yml | 10 +- .../Mobs/Customization/Markings/oni_feet.yml | 13 +++ .../Customization/Markings/pointy_ears.yml | 89 ++++++++++++++++++ .../Mobs/Customization/Markings/scars.yml | 6 +- .../Mobs/Customization/Markings/tusks.yml | 27 ++++++ .../Prototypes/Nyanotrasen/Species/Oni.yml | 9 +- Resources/Prototypes/Species/human.yml | 1 + .../goblin_tusks.rsi/goblin_tusks_big.png | Bin 0 -> 617 bytes .../goblin_tusks.rsi/goblin_tusks_none.png | Bin 0 -> 7430 bytes .../goblin_tusks.rsi/goblin_tusks_small.png | Bin 0 -> 607 bytes .../Customization/goblin_tusks.rsi/meta.json | 23 +++++ .../Mobs/Customization/oni_feet.rsi/meta.json | 15 +++ .../Customization/oni_feet.rsi/two_toes.png | Bin 0 -> 748 bytes .../Customization/pointy_ears.rsi/meta.json | 47 +++++++++ .../pointy_ears.rsi/pointy_ears_large.png | Bin 0 -> 907 bytes .../pointy_ears.rsi/pointy_ears_none.png | Bin 0 -> 678 bytes .../pointy_ears.rsi/pointy_ears_slanted.png | Bin 0 -> 865 bytes .../pointy_ears.rsi/pointy_ears_small.png | Bin 0 -> 753 bytes .../pointy_ears.rsi/pointy_ears_standard.png | Bin 0 -> 686 bytes .../pointy_ears.rsi/pointy_ears_tall.png | Bin 0 -> 826 bytes .../pointy_ears.rsi/pointy_ears_thin.png | Bin 0 -> 601 bytes .../pointy_ears.rsi/pointy_ears_upwards.png | Bin 0 -> 789 bytes .../pointy_ears.rsi/pointy_ears_wide.png | Bin 0 -> 675 bytes 26 files changed, 268 insertions(+), 9 deletions(-) create mode 100644 Resources/Locale/en-US/markings/goblin_markings.ftl create mode 100644 Resources/Locale/en-US/markings/oni_feet.ftl create mode 100644 Resources/Locale/en-US/markings/pointy_ears.ftl create mode 100644 Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_feet.yml create mode 100644 Resources/Prototypes/Entities/Mobs/Customization/Markings/pointy_ears.yml create mode 100644 Resources/Prototypes/Entities/Mobs/Customization/Markings/tusks.yml create mode 100644 Resources/Textures/Mobs/Customization/goblin_tusks.rsi/goblin_tusks_big.png create mode 100644 Resources/Textures/Mobs/Customization/goblin_tusks.rsi/goblin_tusks_none.png create mode 100644 Resources/Textures/Mobs/Customization/goblin_tusks.rsi/goblin_tusks_small.png create mode 100644 Resources/Textures/Mobs/Customization/goblin_tusks.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Customization/oni_feet.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Customization/oni_feet.rsi/two_toes.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_large.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_none.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_slanted.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_small.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_standard.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_tall.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_thin.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_upwards.png create mode 100644 Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_wide.png diff --git a/Resources/Locale/en-US/markings/goblin_markings.ftl b/Resources/Locale/en-US/markings/goblin_markings.ftl new file mode 100644 index 00000000000..21b1afea238 --- /dev/null +++ b/Resources/Locale/en-US/markings/goblin_markings.ftl @@ -0,0 +1,9 @@ +# goblin tusks +marking-GoblinTusksBasic = No Tusks +marking-GoblinTusksBasic-goblin_tusks_none = No Tusks + +marking-GoblinTusksSmall = Small Tusks +marking-GoblinTusksSmall-goblin_tusks_small = Small Tusks + +marking-GoblinTusksBig = Long Tusks +marking-GoblinTusksBig-goblin_tusks_big = Long Tusks diff --git a/Resources/Locale/en-US/markings/oni_feet.ftl b/Resources/Locale/en-US/markings/oni_feet.ftl new file mode 100644 index 00000000000..db35a69acdb --- /dev/null +++ b/Resources/Locale/en-US/markings/oni_feet.ftl @@ -0,0 +1,2 @@ +marking-OniTwoToedFeet-two_toes= Two-Toed Feet +marking-OniTwoToedFeet= Two-Toed Feet diff --git a/Resources/Locale/en-US/markings/pointy_ears.ftl b/Resources/Locale/en-US/markings/pointy_ears.ftl new file mode 100644 index 00000000000..637f216667f --- /dev/null +++ b/Resources/Locale/en-US/markings/pointy_ears.ftl @@ -0,0 +1,26 @@ +marking-PointyEarsStandard-pointy_ears_standard = Standard Ears +marking-PointyEarsStandard = Standard Ears + +marking-PointyEarsWide-pointy_ears_wide = Wide Ears +marking-PointyEarsWide = Wide Ears + +marking-PointyEarsSmall-pointy_ears_small = Small Ears +marking-PointyEarsSmall = Small Ears + +marking-PointyEarsUpwards-pointy_ears_upwards = Upward Ears +marking-PointyEarsUpwards = Upward Ears + +marking-PointyEarsTall-pointy_ears_tall = Tall Ears +marking-PointyEarsTall = Tall Ears + +marking-PointyEarsSlanted-pointy_ears_slanted = Slanted Ears +marking-PointyEarsSlanted = Slanted Ears + +marking-PointyEarsThin-pointy_ears_thin = Thin Ears +marking-PointyEarsThin = Thin Ears + +marking-PointyEarsLarge-pointy_ears_large = Large Ears +marking-PointyEarsLarge = Large Ears + +marking-PointyEarsNone-pointy_ears_none = No Ears +marking-PointyEarsNone = No Ears diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml index 51fc2fd15a2..bfca2ff488a 100644 --- a/Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml @@ -4,7 +4,7 @@ markingCategory: Snout followSkinColor: true forcedColoring: true - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni, Harpy] sprites: - sprite: Mobs/Customization/human_noses.rsi state: schnozz @@ -15,7 +15,7 @@ markingCategory: Snout followSkinColor: true forcedColoring: true - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni, Harpy] sprites: - sprite: Mobs/Customization/human_noses.rsi state: nubby @@ -26,7 +26,7 @@ markingCategory: Snout followSkinColor: true forcedColoring: true - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni, Harpy] sprites: - sprite: Mobs/Customization/human_noses.rsi state: droop @@ -37,7 +37,7 @@ markingCategory: Snout followSkinColor: true forcedColoring: true - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni, Harpy] sprites: - sprite: Mobs/Customization/human_noses.rsi state: blob @@ -48,7 +48,7 @@ markingCategory: Snout followSkinColor: true forcedColoring: true - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni, Harpy] sprites: - sprite: Mobs/Customization/human_noses.rsi state: uppie diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_feet.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_feet.yml new file mode 100644 index 00000000000..0ff03df1a0d --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_feet.yml @@ -0,0 +1,13 @@ +- type: marking + id: OniTwoToedFeet + bodyPart: RFoot # Can't be LFoot to avoid visual glitches + markingCategory: Legs + speciesRestriction: [Oni] + coloring: + default: + type: + !type:SimpleColoring + color: "#454545" + sprites: + - sprite: Mobs/Customization/oni_feet.rsi + state: two_toes diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/pointy_ears.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/pointy_ears.yml new file mode 100644 index 00000000000..10016fb9851 --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/pointy_ears.yml @@ -0,0 +1,89 @@ +- type: marking + id: PointyEarsStandard + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_standard + +- type: marking + id: PointyEarsWide + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_wide + +- type: marking + id: PointyEarsSmall + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_small + +- type: marking + id: PointyEarsUpwards + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_upwards + +- type: marking + id: PointyEarsTall + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_tall + +- type: marking + id: PointyEarsSlanted + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_slanted + +- type: marking + id: PointyEarsThin + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_thin + +- type: marking + id: PointyEarsLarge + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_large + +- type: marking + id: PointyEarsNone + bodyPart: HeadSide + markingCategory: HeadSide + forcedColoring: true + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/pointy_ears.rsi + state: pointy_ears_none diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/scars.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/scars.yml index f4186295900..79e0a0ff012 100644 --- a/Resources/Prototypes/Entities/Mobs/Customization/Markings/scars.yml +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/scars.yml @@ -22,7 +22,7 @@ id: ScarTopSurgeryShort bodyPart: Chest markingCategory: Chest - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni] sexRestriction: [Male] followSkinColor: true sprites: @@ -33,7 +33,7 @@ id: ScarTopSurgeryLong bodyPart: Chest markingCategory: Chest - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni] sexRestriction: [Male] followSkinColor: true sprites: @@ -44,7 +44,7 @@ id: ScarChest bodyPart: Chest markingCategory: Chest - speciesRestriction: [Human, Dwarf] + speciesRestriction: [Human, Dwarf, Felinid, Oni] followSkinColor: true sprites: - sprite: Mobs/Customization/scars.rsi diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/tusks.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/tusks.yml new file mode 100644 index 00000000000..e2b74b44847 --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/tusks.yml @@ -0,0 +1,27 @@ +- type: marking + id: GoblinTusksSmall + bodyPart: Snout + markingCategory: Snout + speciesRestriction: [Oni] + coloring: + default: + type: + !type:SimpleColoring + color: "#d9d9d9" + sprites: + - sprite: Mobs/Customization/goblin_tusks.rsi + state: goblin_tusks_small + +- type: marking + id: GoblinTusksBig + bodyPart: Snout + markingCategory: Snout + speciesRestriction: [Oni] + coloring: + default: + type: + !type:SimpleColoring + color: "#d9d9d9" + sprites: + - sprite: Mobs/Customization/goblin_tusks.rsi + state: goblin_tusks_big diff --git a/Resources/Prototypes/Nyanotrasen/Species/Oni.yml b/Resources/Prototypes/Nyanotrasen/Species/Oni.yml index a6a63b29526..ba5e5661f9f 100644 --- a/Resources/Prototypes/Nyanotrasen/Species/Oni.yml +++ b/Resources/Prototypes/Nyanotrasen/Species/Oni.yml @@ -30,7 +30,14 @@ HeadTop: points: 1 required: true - defaultMarkings: [ OniHornSingleCurved ] + defaultMarkings: [ OniHornDoubleCurved ] + HeadSide: + points: 1 + required: false + defaultMarkings: [ PointyEarsUpwards ] + Snout: + points: 2 + required: false Chest: points: 1 required: false diff --git a/Resources/Prototypes/Species/human.yml b/Resources/Prototypes/Species/human.yml index 49f8839cac3..99ec35da2e1 100644 --- a/Resources/Prototypes/Species/human.yml +++ b/Resources/Prototypes/Species/human.yml @@ -33,6 +33,7 @@ RFoot: MobHumanRFoot Tail: MobHumanoidAnyMarking # Nyanotrasen - Felinid HeadTop: MobHumanoidAnyMarking # Nyanotrasen - Felinid & Oni + HeadSide: MobHumanoidAnyMarking - type: markingPoints id: MobHumanMarkingLimits diff --git a/Resources/Textures/Mobs/Customization/goblin_tusks.rsi/goblin_tusks_big.png b/Resources/Textures/Mobs/Customization/goblin_tusks.rsi/goblin_tusks_big.png new file mode 100644 index 0000000000000000000000000000000000000000..fb706ac649e82e68a92ceb77b165f81a9b9ad22f GIT binary patch literal 617 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/goblin_tusks.rsi/meta.json b/Resources/Textures/Mobs/Customization/goblin_tusks.rsi/meta.json new file mode 100644 index 00000000000..0983b297549 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/goblin_tusks.rsi/meta.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "copyright": "Sprited by erhardsteinhauer (discord)", + "license": "CC-BY-SA-4.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "goblin_tusks_small", + "directions": 4 + }, + { + "name": "goblin_tusks_big", + "directions": 4 + }, + { + "name": "goblin_tusks_none", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Customization/oni_feet.rsi/meta.json b/Resources/Textures/Mobs/Customization/oni_feet.rsi/meta.json new file mode 100644 index 00000000000..c0792d54004 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/oni_feet.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprites by angelofallars (github), two toes based off of Reptilian ( https://github.com/tgstation/tgstation/blob/8024397cc81c5f47f74cf4279e35728487d0a1a7/icons/mob/human_parts_greyscale.dmi )", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "two_toes", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Customization/oni_feet.rsi/two_toes.png b/Resources/Textures/Mobs/Customization/oni_feet.rsi/two_toes.png new file mode 100644 index 0000000000000000000000000000000000000000..898f115fe35c948630a08ca7215f16f3406a906d GIT binary patch literal 748 zcmVEX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`ULrl$=#YHN#vYURaF{>!Pd^bUt2hiqx!yIzSpkD z$8p?z_m9Wpa#H7A{+&Oo>-wRS4FCWD000000000V;i+5H5W;d*9b;72bvm6+|Jrz2 zmdf*7F~+Cf1EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`ULEMvqExSmtkQI!@e64Kx~(Pvh{Y(xViYEhjf@f9R#VO0Nw?L6*KwBdH?7%iHJ9NWK2HVo5B9A}so zdUhM7dM(ozpyG#tkNI!{Ay%_n2!Z)tE1mlF&Lu)of6%)|SCeF3hzu^`S^9@%1slaNq#| z!obJX!;{urt^NSDSQz*)ObhW(A`gm{G7QuD)#kM`Af5>TaC!fjs|EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`ULkVwY zf{(*0UV(-iU_wXeC`crs8XGYzL3u|a|CdYwOqj`Rxg!DqGiK@%Lf5mN*ZW=L+(#VA z_IU2qVELb)dT5&0Ng70w#fhlu*F05~EKVd1qCrn74I)uhE6R0?F?9WR6ID|#pTa1` zU-k3o@*MyG0000000000X03KVz;`aPSgx#hgWbCitj#V%E538Fb_A;K=zpo$(-`{+ z)(}G1o9qC(>?fGEL&$9oCo#rMW&rowRYausN)7-300000004jN2|encG>Q>+6#xJL M07*qoM6N<$f+|`kQ2+n{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_slanted.png b/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_slanted.png new file mode 100644 index 0000000000000000000000000000000000000000..93c7ee9a8c5090a149db9b67ccd4f8273e00b92d GIT binary patch literal 865 zcmV-n1D^beP)EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`ULuh1pCXauJe9V7vzf-cudi5g9!Q3HK`lP~Ap{m4 zn+-W&0B5Pcw=q=(09}MrjJv(WWXq=SUtdr*ssJD&a`2@eSN}H{%Jaw9R;=gPsNB_Z ztsiYfRaKKN!`WcCip}#sAX;Blv6+7P+9CBzX@W#V`t4S#QTE#{$!F}__5F^EML5M~ zdJ(}QoWk$8C#g?FL_|bHL_|bHL_|dYPTqU}BJ^0wk~qtr{!)j}+T*@eHvq(LSq;;Y zeS7)~9)8zWSnAD2wgCW$uAx^C(%vg@PBHf-tex-ZWwGbj@EjZSU=rQcYk|J~Wm`HA zCh#2l_@6-B5CFh>YvAg(g0fLXQP%MDV1jYC2g9`BcU;8XL2~o}qC)_Hr}xjo3_w-U rZ?^y-)8UDTh=_=Yh=_=Yi2j*BB+D2G>VL7^00000NkvXXu0mjfZCsV< literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_small.png b/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_small.png new file mode 100644 index 0000000000000000000000000000000000000000..c6cdebef00521c119c35fbefe0efc9c82d6b4b29 GIT binary patch literal 753 zcmVEX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`ULSWNx zf)4Io{0hE&*jm4WOZE&E(j}5kMhHzIAjic>3`7$Wwd()31@6sr?mc%r5&-;T?z086 z=|sbQ&x-HE^KtE-hdcjm-SRPZl5~1`-KoH8eq9aa>>|HOwrf&E7RHif+s6lT&eiTQ zGh59UlH>*>ueUCh^NYI6Wtf>HnIyH%-)OREF!B@yzI*+7t<`*?DDZndd^JB$QdN84 zoKv2pUzQI500000000000KZ=FQEDoj?TumxjWR>-p)s}65oCSd6L@m(^663x9YrW`w|K#7gt)R3%I|%k<@)8 j2LJ#700000fIsX7D^!sPg4vV500000NkvXXu0mjf7kgDr literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_standard.png b/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_standard.png new file mode 100644 index 0000000000000000000000000000000000000000..38d7137e61b3d457bc55880eb9ae2caa0b210bd5 GIT binary patch literal 686 zcmV;f0#W^mP)EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`ULb7kh-rFMN+8^##XzBzY&+k|tKySq^5YLQpf z)^Bv_?4i-6S+YI=00000000000Q|Jx^Ybi@#Np@-o)K8nm|2EVvN-BJqhHfk<^!IK zU}pd}w*YmnCd~)zh6ep06h)edN-J5U$>u(RB28qamE4~_erx~$00000006i>0AZ`i U|6;tX>;M1&07*qoM6N<$f&!T?2LJ#7 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_tall.png b/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_tall.png new file mode 100644 index 0000000000000000000000000000000000000000..f42a86613a91e271169c6539cca1b69bd1e56120 GIT binary patch literal 826 zcmV-A1I7G_P)EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`UL?m{+ z>d?KPqAwpd#@)%q-629i2xRL?4+A}rr;CwTt#?Tyk^29wUha9x#pOAG=%g%8k;SQ$ zd`7Z3{TJ~803ss3Nn~*Z@CskVSvSW1ORCFx+mA> zzc0okL}7p^4E|hrai4at`|F-j80_NL6?^YH{QCHW&l}jTtNni{kH0;Q$4+Ra_${AB zok1VV=>!0jW2stBC+H0NwKgD+pUh{LaxyooHLNzuYU5oz;GXv%boJrs8SP#dxA%7kbNVJ5V70+!wMH_Z zc^6-*0Y5*7$CtN@YCwLCr%drgL_|bHL_|bHL_}BS8_B69Xc=)$qyPW_07*qoM6N<$ Ef=F$8X#fBK literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_thin.png b/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_thin.png new file mode 100644 index 0000000000000000000000000000000000000000..a910e67f6d07167dd7bdcc25745d90da09a95c24 GIT binary patch literal 601 zcmV-f0;c_mP)EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`UL>rFpo zZfx@b00000000=X?EbuK+K7nH_3v+Z{1*@rsi?}Vy_4J_*8@|;rGuZ&XFqd`$6Xz# n{UH{sW%8y0000000G>Dliy|+{59 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_upwards.png b/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_upwards.png new file mode 100644 index 0000000000000000000000000000000000000000..8454708d9e41e25fcae454885b23a85f80053214 GIT binary patch literal 789 zcmV+w1M2*VP)EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`UL#eG)o>TsHRYBl7zn^a&?*FZ|znA~>^!$3#!VmKU*ZFhIz;%xD zPtD%Dr@lYGq|Oc$b)7#0Y`&_>;U?Sf+T>5_6iw$diF{8)#8i};$oFJApLKcxZ2o4o zGx|vRN&A$p-)c00000006+n>E*rqz;m3m2+$EPzTdeOZ(((e7s2)h zG;L34)E{6~^$852Jf|l80hPBvd5}CwB@1Jdg|YP12-5mwW??K@7@IsvYcIa`Gr$g3 z^a#k+-K`nh39xgDe6LYwNTY?6Z->Xl%Tc4kkSE~d{jJf?0{{R300000aDjdRWC-8- TTJhfo00000NkvXXu0mjfU0HEx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_wide.png b/Resources/Textures/Mobs/Customization/pointy_ears.rsi/pointy_ears_wide.png new file mode 100644 index 0000000000000000000000000000000000000000..2a643bf6c61c3eb38eddf9c80e635360a6a451ed GIT binary patch literal 675 zcmV;U0$lxxP)EX>4Tx04R}tkv&MmP!xqvQ^g_`1v`i+WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yULJ2)x2NQw6)g%&YBxV(?^-Z|WNA0RX;OtZS;fTr7K zI++l&xmB^}6(NK%Ks72e%b1g-6nxj$Jpz2ci}5V~dw;GzHE%H>AQH!!VcNtS#50?= z!FiuJ!b-AAd`>)JQiH^gTvt4P<6LxE;F%FKlb$Dz5R1hQRyvrKOpSP&II3zo)|5Tqat9cCGGtSBr6841C;;zg^i4Tn@D}J@^XAq%$LRx*p;@JFfP+I| zyhz#WKJN~7&h6hjt@-@`UL Date: Tue, 13 Aug 2024 21:13:08 +0000 Subject: [PATCH 099/135] Automatic Changelog Update (#727) --- Resources/Changelog/Changelog.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 15c67e383a4..253a6a57a20 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5294,3 +5294,26 @@ Entries: prize tickets! and find prize balls!! id: 6260 time: '2024-08-13T17:16:52.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Onis have received eight new pointy ear markings in the 'Head (Side)' + section that can help them resemble tieflings, orcs, elves, goblins, + trolls, and more. + - type: Add + message: >- + Onis get two new tusk markings in the 'Snout' section, and a Two-Toed + feet marking in the 'Legs' section. + - type: Add + message: >- + Felinids, Onis, and Harpies can now select Human nose markings like the + schnozz, blobby nose, and nubby nose. + - type: Add + message: >- + Felinids and Onis can now select the Chest Scar and Top Surgery Scar + markings. + - type: Tweak + message: Default Onis now use the Double Curved horn and Upward Ears markings. + id: 6261 + time: '2024-08-13T21:12:45.0000000+00:00' From 2067f85f3c05e07665858a8cc217960614507855 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Tue, 13 Aug 2024 22:12:43 -0400 Subject: [PATCH 100/135] Hotfix Psionic Regeneration (#730) # Description I LOVE OLD SHITCODE THAT DOESN'T VALIDATE ANYTHING. Not going to validate it in this PR because I'm just hot fixing this shit, and I'm busy as hell with serializing Psionics. I'll go do a significantly more longer-term fix 2 PRs from now. # Changelog :cl: - fix: Fix missing Psionic Regeneration sound effect --- .../PsionicRegeneration/PsionicRegenerationPowerComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs b/Content.Shared/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs index 4a62e84d191..895c5201c3a 100644 --- a/Content.Shared/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs +++ b/Content.Shared/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs @@ -18,7 +18,7 @@ public sealed partial class PsionicRegenerationPowerComponent : Component public float UseDelay = 8f; [DataField("soundUse")] - public SoundSpecifier SoundUse = new SoundPathSpecifier("/Audio/Nyanotrasen/Psionics/heartbeat_fast.ogg"); + public SoundSpecifier SoundUse = new SoundPathSpecifier("/Audio/Psionics/heartbeat_fast.ogg"); [DataField("psionicRegenerationActionId", customTypeSerializer: typeof(PrototypeIdSerializer))] From d2ff5b16b3a421d9231ab0c4c5ffcaab4bce01fd Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 14 Aug 2024 02:13:05 +0000 Subject: [PATCH 101/135] Automatic Changelog Update (#730) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 253a6a57a20..309ca52c9b7 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5317,3 +5317,9 @@ Entries: message: Default Onis now use the Double Curved horn and Upward Ears markings. id: 6261 time: '2024-08-13T21:12:45.0000000+00:00' +- author: VMSolidus + changes: + - type: Fix + message: Fix missing Psionic Regeneration sound effect + id: 6262 + time: '2024-08-14T02:12:43.0000000+00:00' From a9280bb920430367b49bca281377d54860006477 Mon Sep 17 00:00:00 2001 From: Angelo Fallaria Date: Wed, 14 Aug 2024 13:30:36 +0800 Subject: [PATCH 102/135] Vulpkanin Rework: Number Changes (#713) # Description Per #711, this PR adds new stat changes to Vulpkanins to make them more mechanically interesting and distinct from Humans. - Receive the Voracious trait by default, giving them 2x eating/drinking speed. - Takes 30% less Cold damage - Takes 30% more Heat damage, up from 15%. - Hunger rate increased by 25%. - Receive 25% more fire stacks, increasing the Heat damage and duration of being on fire. - Flash duration has been increased by 50%. - The duration of flashes, 5 seconds, will become 7.5 seconds. **Only merge** alongside #715. ## Media
Expand **New flash duration** https://github.com/user-attachments/assets/afafd890-d40b-4c63-9259-53ae6a355e53
## Changelog :cl: Skubman - add: Vulpkanins receive the Voracious trait for free, giving them 2x eating/drinking speed, but Vulpkanins get hungrier 25% faster. - tweak: Vulpkanins gain a 30% Cold resistance, but their Heat vulnerability has increased from 15% to 30%. Vulpkanins also receive 25% more Fire stacks, amplifying the damage and duration of being on fire. - tweak: Flash duration against Vulpkanins has been increased by 50%. --------- Signed-off-by: VMSolidus Co-authored-by: VMSolidus --- Content.Client/Flash/FlashSystem.cs | 6 ++++-- .../Atmos/Components/FlammableComponent.cs | 6 ++++++ .../Atmos/EntitySystems/FlammableSystem.cs | 3 +++ Content.Server/Flash/FlashSystem.cs | 2 ++ Content.Shared/Flash/FlashableComponent.cs | 14 +++++++++++++- Content.Shared/Flash/SharedFlashSystem.cs | 2 +- .../Prototypes/DeltaV/Damage/modifier_sets.yml | 3 ++- .../DeltaV/Entities/Mobs/Species/vulpkanin.yml | 8 ++++++++ Resources/Prototypes/Traits/skills.yml | 5 +++++ 9 files changed, 44 insertions(+), 5 deletions(-) diff --git a/Content.Client/Flash/FlashSystem.cs b/Content.Client/Flash/FlashSystem.cs index ad8f8b0b82b..57a91983a96 100644 --- a/Content.Client/Flash/FlashSystem.cs +++ b/Content.Client/Flash/FlashSystem.cs @@ -38,8 +38,10 @@ private void OnFlashableHandleState(EntityUid uid, FlashableComponent component, // Few things here: // 1. If a shorter duration flash is applied then don't do anything // 2. If the client-side time is later than when the flash should've ended don't do anything + var calculatedStateDuration = state.Duration * state.DurationMultiplier; + var currentTime = _gameTiming.CurTime.TotalSeconds; - var newEndTime = state.Time.TotalSeconds + state.Duration; + var newEndTime = state.Time.TotalSeconds + calculatedStateDuration; var currentEndTime = component.LastFlash.TotalSeconds + component.Duration; if (currentEndTime > newEndTime) @@ -53,7 +55,7 @@ private void OnFlashableHandleState(EntityUid uid, FlashableComponent component, } component.LastFlash = state.Time; - component.Duration = state.Duration; + component.Duration = calculatedStateDuration; var overlay = _overlayManager.GetOverlay(); overlay.ReceiveFlash(component.Duration); diff --git a/Content.Server/Atmos/Components/FlammableComponent.cs b/Content.Server/Atmos/Components/FlammableComponent.cs index 679b5510586..33a163228f1 100644 --- a/Content.Server/Atmos/Components/FlammableComponent.cs +++ b/Content.Server/Atmos/Components/FlammableComponent.cs @@ -61,5 +61,11 @@ public sealed partial class FlammableComponent : Component ///
[DataField, ViewVariables(VVAccess.ReadWrite)] public float FirestackFade = -0.1f; + + /// + /// How stronger will firestack increases be? + /// + [DataField] + public float FireStackIncreaseMultiplier = 1f; } } diff --git a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs index 53fcb720766..d34de937a41 100644 --- a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs +++ b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs @@ -274,6 +274,9 @@ public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableC if (!Resolve(uid, ref flammable)) return; + if (relativeFireStacks > 0) + relativeFireStacks *= flammable.FireStackIncreaseMultiplier; + flammable.FireStacks = MathF.Min(MathF.Max(MinimumFireStacks, flammable.FireStacks + relativeFireStacks), MaximumFireStacks); if (flammable.OnFire && flammable.FireStacks <= 0) diff --git a/Content.Server/Flash/FlashSystem.cs b/Content.Server/Flash/FlashSystem.cs index 013ee37a416..3f1e4e731df 100644 --- a/Content.Server/Flash/FlashSystem.cs +++ b/Content.Server/Flash/FlashSystem.cs @@ -133,6 +133,8 @@ public void Flash(EntityUid target, RaiseLocalEvent(used.Value, ref ev); } + flashDuration *= flashable.DurationMultiplier; + flashable.LastFlash = _timing.CurTime; flashable.Duration = flashDuration / 1000f; // TODO: Make this sane... Dirty(target, flashable); diff --git a/Content.Shared/Flash/FlashableComponent.cs b/Content.Shared/Flash/FlashableComponent.cs index c4f8074ceaf..5f3f214b6bb 100644 --- a/Content.Shared/Flash/FlashableComponent.cs +++ b/Content.Shared/Flash/FlashableComponent.cs @@ -10,6 +10,12 @@ public sealed partial class FlashableComponent : Component public float Duration; public TimeSpan LastFlash; + // + // How much to modify the duration of flashes against this entity. + // + [DataField] + public float DurationMultiplier = 1f; + [DataField] public CollisionGroup CollisionGroup = CollisionGroup.Opaque; @@ -22,10 +28,16 @@ public sealed class FlashableComponentState : ComponentState public float Duration { get; } public TimeSpan Time { get; } - public FlashableComponentState(float duration, TimeSpan time) + // + // How much to modify the duration of flashes against this entity. + // + public float DurationMultiplier { get; } + + public FlashableComponentState(float duration, TimeSpan time, float durationMultiplier) { Duration = duration; Time = time; + DurationMultiplier = durationMultiplier; } } diff --git a/Content.Shared/Flash/SharedFlashSystem.cs b/Content.Shared/Flash/SharedFlashSystem.cs index 16fdbfc2f3e..c4345154892 100644 --- a/Content.Shared/Flash/SharedFlashSystem.cs +++ b/Content.Shared/Flash/SharedFlashSystem.cs @@ -13,7 +13,7 @@ public override void Initialize() private static void OnFlashableGetState(EntityUid uid, FlashableComponent component, ref ComponentGetState args) { - args.State = new FlashableComponentState(component.Duration, component.LastFlash); + args.State = new FlashableComponentState(component.Duration, component.LastFlash, component.DurationMultiplier); } } } diff --git a/Resources/Prototypes/DeltaV/Damage/modifier_sets.yml b/Resources/Prototypes/DeltaV/Damage/modifier_sets.yml index a2b8be8bf6a..b389378eb01 100644 --- a/Resources/Prototypes/DeltaV/Damage/modifier_sets.yml +++ b/Resources/Prototypes/DeltaV/Damage/modifier_sets.yml @@ -1,7 +1,8 @@ - type: damageModifierSet id: Vulpkanin coefficients: - Heat: 1.15 + Heat: 1.30 + Cold: 0.70 - type: damageModifierSet id: Harpy diff --git a/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml index 0bcd71fbadb..909aba6632e 100644 --- a/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml @@ -8,6 +8,7 @@ - type: HumanoidAppearance species: Vulpkanin - type: Hunger + baseDecayRate: 0.02083333332 # 25% more than default - type: Carriable # Carrying system from nyanotrasen. - type: Inventory # Allows vulps to wear properly shaped helmets speciesId: vulpkanin @@ -105,6 +106,13 @@ understands: - GalacticCommon - Canilunzt + - type: ConsumeDelayModifier + foodDelayMultiplier: 0.5 + drinkDelayMultiplier: 0.5 + - type: Flammable + fireStackIncreaseMultiplier: 1.25 + - type: Flashable + durationMultiplier: 1.5 - type: entity save: false diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index 40198b724ed..e0115c0562b 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -115,6 +115,11 @@ - type: ConsumeDelayModifier foodDelayMultiplier: 0.5 drinkDelayMultiplier: 0.5 + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Vulpkanin - type: trait id: ParkourTraining From 66a72609bf05678a2d09fcaaff6bf38a51efef77 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 14 Aug 2024 05:31:03 +0000 Subject: [PATCH 103/135] Automatic Changelog Update (#713) --- Resources/Changelog/Changelog.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 309ca52c9b7..0f5134d795c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5323,3 +5323,18 @@ Entries: message: Fix missing Psionic Regeneration sound effect id: 6262 time: '2024-08-14T02:12:43.0000000+00:00' +- author: Skubman + changes: + - type: Add + message: >- + Vulpkanins receive the Voracious trait for free, giving them 2x + eating/drinking speed, but Vulpkanins get hungrier 25% faster. + - type: Tweak + message: >- + Vulpkanins gain a 30% Cold resistance, but their Heat vulnerability has + increased from 15% to 30%. Vulpkanins also receive 25% more Fire stacks, + amplifying the damage and duration of being on fire. + - type: Tweak + message: Flash duration against Vulpkanins has been increased by 50%. + id: 6263 + time: '2024-08-14T05:30:37.0000000+00:00' From 5f25d1bd643cc6ca8ac191ce4d4db4b82addf60d Mon Sep 17 00:00:00 2001 From: dootythefrooty <137359445+dootythefrooty@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:05:24 -0700 Subject: [PATCH 104/135] Oni Horn Markings (#726) # Description --- Three new Oni horn markings,] two of which have three tone support. There was a distinct lack of large horns, which I tried my hand at.

Media

![display](https://github.com/user-attachments/assets/cb0604e8-941c-48fd-8fb8-205893b87c5c)

--- # Changelog :cl: - add: Added crowned, tall bull, and tall curved Oni horns. --- Resources/Locale/en-US/markings/oni.ftl | 18 ++++++ .../Mobs/Customization/Markings/oni_horns.yml | 53 ++++++++++++++++++ .../Oni/oni_horns.rsi/crowned.png | Bin 0 -> 197 bytes .../Customization/Oni/oni_horns.rsi/meta.json | 15 +++++ .../Oni/oni_horns48x48.rsi/meta.json | 43 ++++++++++++++ .../Oni/oni_horns48x48.rsi/tall_bull.png | Bin 0 -> 527 bytes .../oni_horns48x48.rsi/tall_bull_3tone_1.png | Bin 0 -> 362 bytes .../oni_horns48x48.rsi/tall_bull_3tone_2.png | Bin 0 -> 308 bytes .../oni_horns48x48.rsi/tall_bull_3tone_3.png | Bin 0 -> 274 bytes .../Oni/oni_horns48x48.rsi/tall_curved.png | Bin 0 -> 535 bytes .../tall_curved_3tone_1.png | Bin 0 -> 260 bytes .../tall_curved_3tone_2.png | Bin 0 -> 302 bytes .../tall_curved_3tone_3.png | Bin 0 -> 323 bytes 13 files changed, 129 insertions(+) create mode 100644 Resources/Locale/en-US/markings/oni.ftl create mode 100644 Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_horns.yml create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns.rsi/crowned.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_bull.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_bull_3tone_1.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_bull_3tone_2.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_bull_3tone_3.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved_3tone_1.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved_3tone_2.png create mode 100644 Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved_3tone_3.png diff --git a/Resources/Locale/en-US/markings/oni.ftl b/Resources/Locale/en-US/markings/oni.ftl new file mode 100644 index 00000000000..6c34f437b15 --- /dev/null +++ b/Resources/Locale/en-US/markings/oni.ftl @@ -0,0 +1,18 @@ +marking-OniHornTallCurved = Tall Curved +marking-OniHornTallCurved-tall_curved = Tall Curved + +marking-OniHornTallCurved3Tone = Tall Curved Three Tone +marking-OniHornTallCurved3Tone-tall_curved_3tone_1 = Bottom Third +marking-OniHornTallCurved3Tone-tall_curved_3tone_2 = Middle Third +marking-OniHornTallCurved3Tone-tall_curved_3tone_3 = Top Third + +marking-OniHornTallBull= Tall Bull +marking-OniHornTallBull-tall_bull = Tall Bull + +marking-OniHornTallBull3Tone = Tall Bull Three Tone +marking-OniHornTallBull3Tone-tall_bull_3tone_1 = Bottom Third +marking-OniHornTallBull3Tone-tall_bull_3tone_2 = Middle Third +marking-OniHornTallBull3Tone-tall_bull_3tone_3 = Top Third + +marking-OniHornCrowned = Crowned +marking-OniHornCrowned-crowned = Crowned diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_horns.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_horns.yml new file mode 100644 index 00000000000..b7af09b6e72 --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/oni_horns.yml @@ -0,0 +1,53 @@ +- type: marking + id: OniHornTallCurved + bodyPart: HeadTop + markingCategory: HeadTop + forcedColoring: false + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_curved +- type: marking + id: OniHornTallCurved3Tone + bodyPart: HeadTop + markingCategory: HeadTop + forcedColoring: false + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_curved_3tone_1 + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_curved_3tone_2 + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_curved_3tone_3 +- type: marking + id: OniHornTallBull + bodyPart: HeadTop + markingCategory: HeadTop + forcedColoring: false + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_bull +- type: marking + id: OniHornTallBull3Tone + bodyPart: HeadTop + markingCategory: HeadTop + forcedColoring: false + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_bull_3tone_1 + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_bull_3tone_2 + - sprite: Mobs/Customization/Oni/oni_horns48x48.rsi + state: tall_bull_3tone_3 +- type: marking + id: OniHornCrowned + bodyPart: HeadTop + markingCategory: HeadTop + forcedColoring: false + speciesRestriction: [Oni] + sprites: + - sprite: Mobs/Customization/Oni/oni_horns.rsi + state: crowned diff --git a/Resources/Textures/Mobs/Customization/Oni/oni_horns.rsi/crowned.png b/Resources/Textures/Mobs/Customization/Oni/oni_horns.rsi/crowned.png new file mode 100644 index 0000000000000000000000000000000000000000..7341aaf74edbf3eb2de4a9911a6eeb196ced48c6 GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|>OEZ?Ln`LH zy=BdJSV4s4K_&*xV) z-1~jICVTCvSASGIvvc3{?w`jGG!6*<%)A~|(qr+-43q&9=WvVfV!-Sv>+n`!(T7W zrvgrPNoxe0{4{Gz*UbC;KkD+rt!2@xyskz4yw>t{Uj0Uf8{(`PZ@%9WZcnVJv^i#> zyY=+bq-nn*t^UV9&Uw0bdZEnf&sXNX-@E?Q)+*MB?Eh6WmQLAZ=r*VL(VX9c@1{y5 zUn}l446A)ne}8rS**a59d)?gWQ}^D@yZk&+!bM$osY?HGXBU@ag(j)hf)ihV z)jDS>C|GGXzi9vc<#o^gPJg?-YWjYgxXJ%x?M;7%$1iD%*nOnOF!;XZ^U(b~dl%&U z?OSy+J}o?ZUE=valLegk6rW7e%l*1)ZryV4txIa(iS1JQzk6Htlm9z{o;J)6smcDm z_S`&qU;tu(EhSf0uk?<3ma#3;U4QcWsHd4h4L`3j+J3lau6gJoYlmT(`Oj0;`*$QB zUwKrbe$T!8R{ksR?0c|Z$LTy!waCK>(E%Ka({JyY(^$N2w>_8qN#nioS8CL!ZjF9h z^4e$e`e&{;ir3uDcU*5~Z#8-Ib9M{|Fns&UzEORd+Pl%Fy0|HZbx$Cv-~+nouLw{M+4>3`U#`@UhE&XX zd*@(oi-7>^g~BOWFF3o5bscTbsm5*0m>9tLl9UbnA6D2O~_Fetd;MczTFP@sF*YAAN`akhaXl?to zKfA@(N!yBMN<_$>xMa~MSa>esTHI6n=1?boJ?0rvrW^VZ@-~bZ$boFyt=akR{0KCY2ga7~l literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_bull_3tone_3.png b/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_bull_3tone_3.png new file mode 100644 index 0000000000000000000000000000000000000000..cd427ae11790fd200924a141734818f92af5039a GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-D$|&Um^whE&XX zd*^iT5d{HOhwQ@-UsYJ`?BjftsQ-FzpL?>Maww~V{l}CeM`hRJ-P&;X^M0L%jUpRvyk$D~S!QPPk2xI@o8B!i&J#Cy zEi<<^uD&(Wyd&`QK3jXB)kxsL{@A*VxS7c}lVx}3{7Vg;r^=d=HvenIu~@;4OIlvC zUWwX%`;WJa%+_mb_nkTZ)!tgpar)IrBm;oV2d(i{e3{K29G}mDBs^XHT-G@yGywqn Cp=_!E literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved.png b/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved.png new file mode 100644 index 0000000000000000000000000000000000000000..b32391a95e847e1b61464d9b2baca287cbb9436e GIT binary patch literal 535 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-D%zFM7H-hE&XX zd*|T9#|i?i53gNIOP;^Rpu@3cVZ()!j21k3CNDRrm(7U1{di-GL-7Cd&8ladrx=Jw zu`u+VwwykvcxBn_D89M(EvIh^XWn~x*|f#a#Y26Uu4kJ1Fxbm8bT;3DGxihdj|5tHtxW@O{rrx^a zd)%{1vFx`Smi^ya^#A=6{oCfLJ)TPPr@c8IzRQ+$`mx35Y1!JPQ~o^*zuJB}VBfsy zbMLH^wtTQSq4I3bzvEvWR{vQ&O`&Ajou^aomv7Gf?bQ8e4`VscVFR1rdzPM6S2$Kt z&T#+ktF512BwnAx0t^-m@S!c%@88tt*}GS)|8QjDrhQND3z^!=U(1`g^_AmW8-`HP zP*K5&nX{H0_bfQKG;@~Alj3`~BI~dJ`S|*)mXiGXA`Zp5e#>XYu3NUM$ZkIS#9FOg zA^M>OyYKSt?vu0pUB7G9)-w0iHM_-MM@(CK`flsivWRJ^-|Na}GCYrwI$qen&djhc zdAfA#_9;_2`wdnUX=cSih6vvkj+x5)+1l85sVg)H8gH_^C7dY-IyT+SAp~ JWt~$(698-E^ql|z literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved_3tone_1.png b/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved_3tone_1.png new file mode 100644 index 0000000000000000000000000000000000000000..560776c3896ca21e437d7dd8a1d76cd73347c2db GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-D$|_IbKEhE&XX zd&iOQkb(efz^lLh2j@Pp+F_t_Bx5V**5=CmaIv@P8n@>Q0TpLwuidKr`r;p}|GC$? zi_Wc`vPpW=luJeD6#0|B{?S}|Ty0n3-u10~^VglUf6Mk~a_;SId!Nr-ChxHJ>r=L@ zwVUlryUGvSeHH+kgaQ_I-kV|+rTIF%O5Fd;sabL1!u!NublClParphQa|`@g{k$U{ kp078%*RpyuioQ2Hm@jNuee)Re_md!TPgg&ebxsLQ0Nq$-@c;k- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved_3tone_2.png b/Resources/Textures/Mobs/Customization/Oni/oni_horns48x48.rsi/tall_curved_3tone_2.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a0114786557f37680d5abc4d857e68bba03f57 GIT binary patch literal 302 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-D$|UU<4VhE&XX zd&jV^*+76bAbowa_PT?z7IWS^v+p~XBf3;k=N3cZlaB7+?`j?^j5%BX-_G~))<&S) zP{0qr^Rq&tKCBa)?tDAwTgJ{!X{+;|>r9t*&{W;EZgbP0l+XkK D4#SI! literal 0 HcmV?d00001 From 934a096d26c0284165c2df7eae33c3496333fa10 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 14 Aug 2024 09:05:56 +0000 Subject: [PATCH 105/135] Automatic Changelog Update (#726) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0f5134d795c..6ca745cf407 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5338,3 +5338,9 @@ Entries: message: Flash duration against Vulpkanins has been increased by 50%. id: 6263 time: '2024-08-14T05:30:37.0000000+00:00' +- author: dootythefrooty + changes: + - type: Add + message: Added crowned, tall bull, and tall curved Oni horns. + id: 6264 + time: '2024-08-14T09:05:24.0000000+00:00' From 441dee258c000093883f21af05298e7dabcef170 Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:06:25 +0300 Subject: [PATCH 106/135] Convert Harpy Singing Into a Trait (#714) # Description Adds a new trait that lets characters play midi without needing an instrument. Singer a 1-point positive trait. For now it's only available for vulps and felinids as they are naturally more vocal than other species. Also refactored harpy singing system a bit. # TODO - [X] Find out whatever causes this. Not critical, but probably should be fixed...

![image](https://github.com/user-attachments/assets/8e0a6bf5-5fa3-4a0a-8937-2931dfe4ee62)

Media

Outdated ![image](https://github.com/user-attachments/assets/018b6cf3-d510-46e2-8c38-4bd49e1929bd) ![image](https://github.com/user-attachments/assets/f27bd451-b3c2-4a22-ab50-35c2f4ecbcb3)

# Changelog :cl: - add: Added a new positive trait - singer. It allows you to play midi songs without an instrument, similarly to harpies. --------- Signed-off-by: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> Co-authored-by: VMSolidus --- Content.Client/Traits/SingerSystem.cs | 13 ++ .../DeltaV/Harpy/HarpySingerSystem.cs | 182 ------------------ .../Traits/Assorted/SingerSystem.cs | 161 ++++++++++++++++ .../DeltaV/Harpy/HarpySingerComponent.cs | 18 -- .../DeltaV/Harpy/HarpySingerSystem.cs | 28 --- .../DeltaV/Harpy/HarpyVisualsSystem.cs | 8 +- .../Assorted/Components/SingerComponent.cs | 16 ++ .../Prototypes/SingerInstrumentPrototype.cs | 35 ++++ .../Assorted/Systems/SharedSingerSystem.cs | 93 +++++++++ Resources/Locale/en-US/traits/traits.ftl | 2 + .../Entities/Mobs/Species/harpy.yml | 27 +-- .../Prototypes/Traits/Misc/singer_types.yml | 26 +++ Resources/Prototypes/Traits/skills.yml | 13 ++ 13 files changed, 366 insertions(+), 256 deletions(-) create mode 100644 Content.Client/Traits/SingerSystem.cs delete mode 100644 Content.Server/DeltaV/Harpy/HarpySingerSystem.cs create mode 100644 Content.Server/Traits/Assorted/SingerSystem.cs delete mode 100644 Content.Shared/DeltaV/Harpy/HarpySingerComponent.cs delete mode 100644 Content.Shared/DeltaV/Harpy/HarpySingerSystem.cs create mode 100644 Content.Shared/Traits/Assorted/Components/SingerComponent.cs create mode 100644 Content.Shared/Traits/Assorted/Prototypes/SingerInstrumentPrototype.cs create mode 100644 Content.Shared/Traits/Assorted/Systems/SharedSingerSystem.cs create mode 100644 Resources/Prototypes/Traits/Misc/singer_types.yml diff --git a/Content.Client/Traits/SingerSystem.cs b/Content.Client/Traits/SingerSystem.cs new file mode 100644 index 00000000000..4a7bd4ca043 --- /dev/null +++ b/Content.Client/Traits/SingerSystem.cs @@ -0,0 +1,13 @@ +using Content.Client.Instruments; +using Content.Shared.Instruments; +using Content.Shared.Traits.Assorted.Systems; + +namespace Content.Client.Traits; + +public sealed class SingerSystem : SharedSingerSystem +{ + protected override SharedInstrumentComponent EnsureInstrumentComp(EntityUid uid) + { + return EnsureComp(uid); // I hate this, but it's the only way. + } +} diff --git a/Content.Server/DeltaV/Harpy/HarpySingerSystem.cs b/Content.Server/DeltaV/Harpy/HarpySingerSystem.cs deleted file mode 100644 index 21b5b3a2456..00000000000 --- a/Content.Server/DeltaV/Harpy/HarpySingerSystem.cs +++ /dev/null @@ -1,182 +0,0 @@ -using Content.Server.Instruments; -using Content.Server.Speech.Components; -using Content.Server.UserInterface; -using Content.Shared.Instruments; -using Content.Shared.Instruments.UI; -using Content.Shared.ActionBlocker; -using Content.Shared.Damage; -using Content.Shared.Damage.ForceSay; -using Content.Shared.DeltaV.Harpy; -using Content.Shared.FixedPoint; -using Content.Shared.Inventory; -using Content.Shared.Inventory.Events; -using Content.Shared.Mobs; -using Content.Shared.Popups; -using Content.Shared.StatusEffect; -using Content.Shared.Stunnable; -using Content.Shared.UserInterface; -using Content.Shared.Zombies; -using Robust.Server.GameObjects; -using Robust.Shared.Player; -using Robust.Shared.Prototypes; -using Content.Shared.DeltaV.Harpy.Components; - -namespace Content.Server.DeltaV.Harpy -{ - public sealed class HarpySingerSystem : EntitySystem - { - [Dependency] private readonly InstrumentSystem _instrument = default!; - [Dependency] private readonly SharedPopupSystem _popupSystem = default!; - [Dependency] private readonly InventorySystem _inventorySystem = default!; - [Dependency] private readonly ActionBlockerSystem _blocker = default!; - [Dependency] private readonly IPrototypeManager _prototype = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMobStateChangedEvent); - SubscribeLocalEvent(OnEquip); - SubscribeLocalEvent(OnZombified); - SubscribeLocalEvent(OnKnockedDown); - SubscribeLocalEvent(OnStunned); - SubscribeLocalEvent(OnSleep); - SubscribeLocalEvent(OnStatusEffect); - SubscribeLocalEvent(OnDamageChanged); - SubscribeLocalEvent(OnBoundUIClosed); - SubscribeLocalEvent(OnBoundUIOpened); - - // This is intended to intercept the UI event and stop the MIDI UI from opening if the - // singer is unable to sing. Thus it needs to run before the ActivatableUISystem. - SubscribeLocalEvent(OnInstrumentOpen, before: new[] { typeof(ActivatableUISystem) }); - } - - private void OnEquip(GotEquippedEvent args) - { - // Check if an item that makes the singer mumble is equipped to their face - // (not their pockets!). As of writing, this should just be the muzzle. - if (TryComp(args.Equipment, out var accent) && - accent.ReplacementPrototype == "mumble" && - args.Slot == "mask") - { - CloseMidiUi(args.Equipee); - } - } - - private void OnMobStateChangedEvent(EntityUid uid, InstrumentComponent component, MobStateChangedEvent args) - { - if (args.NewMobState is MobState.Critical or MobState.Dead) - CloseMidiUi(args.Target); - } - - private void OnZombified(ref EntityZombifiedEvent args) - { - CloseMidiUi(args.Target); - } - - private void OnKnockedDown(EntityUid uid, InstrumentComponent component, ref KnockedDownEvent args) - { - CloseMidiUi(uid); - } - - private void OnStunned(EntityUid uid, InstrumentComponent component, ref StunnedEvent args) - { - CloseMidiUi(uid); - } - - private void OnSleep(EntityUid uid, InstrumentComponent component, ref SleepStateChangedEvent args) - { - if (args.FellAsleep) - CloseMidiUi(uid); - } - - private void OnStatusEffect(EntityUid uid, InstrumentComponent component, StatusEffectAddedEvent args) - { - if (args.Key == "Muted") - CloseMidiUi(uid); - } - - /// - /// Almost a copy of Content.Server.Damage.ForceSay.DamageForceSaySystem.OnDamageChanged. - /// Done so because DamageForceSaySystem doesn't output an event, and my understanding is - /// that we don't want to change upstream code more than necessary to avoid merge conflicts - /// and maintenance overhead. It still reuses the values from DamageForceSayComponent, so - /// any tweaks to that will keep ForceSay consistent with singing interruptions. - /// - private void OnDamageChanged(EntityUid uid, InstrumentComponent instrumentComponent, DamageChangedEvent args) - { - if (!TryComp(uid, out var component) || - args.DamageDelta == null || - !args.DamageIncreased || - args.DamageDelta.GetTotal() < component.DamageThreshold || - component.ValidDamageGroups == null) - return; - - var totalApplicableDamage = FixedPoint2.Zero; - foreach (var (group, value) in args.DamageDelta.GetDamagePerGroup(_prototype)) - { - if (!component.ValidDamageGroups.Contains(group)) - continue; - - totalApplicableDamage += value; - } - - if (totalApplicableDamage >= component.DamageThreshold) - CloseMidiUi(uid); - } - - /// - /// Closes the MIDI UI if it is open. - /// - private void CloseMidiUi(EntityUid uid) - { - if (HasComp(uid) && - TryComp(uid, out var actor)) - { - _instrument.ToggleInstrumentUi(uid, actor.PlayerSession); - } - } - - /// - /// Prevent the player from opening the MIDI UI under some circumstances. - /// - private void OnInstrumentOpen(EntityUid uid, HarpySingerComponent component, OpenUiActionEvent args) - { - // CanSpeak covers all reasons you can't talk, including being incapacitated - // (crit/dead), asleep, or for any reason mute inclding glimmer or a mime's vow. - var canNotSpeak = !_blocker.CanSpeak(uid); - var zombified = TryComp(uid, out var _); - var muzzled = _inventorySystem.TryGetSlotEntity(uid, "mask", out var maskUid) && - TryComp(maskUid, out var accent) && - accent.ReplacementPrototype == "mumble"; - - // Set this event as handled when the singer should be incapable of singing in order - // to stop the ActivatableUISystem event from opening the MIDI UI. - args.Handled = canNotSpeak || muzzled || zombified; - - // Tell the user that they can not sing. - if (args.Handled) - _popupSystem.PopupEntity(Loc.GetString("no-sing-while-no-speak"), uid, uid, PopupType.Medium); - } - - private void OnBoundUIClosed(EntityUid uid, HarpySingerComponent component, BoundUIClosedEvent args) - { - if (args.UiKey is not InstrumentUiKey) - return; - - TryComp(uid, out AppearanceComponent? appearance); - _appearance.SetData(uid, HarpyVisualLayers.Singing, SingingVisualLayer.False, appearance); - } - - private void OnBoundUIOpened(EntityUid uid, HarpySingerComponent component, BoundUIOpenedEvent args) - { - if (args.UiKey is not InstrumentUiKey) - return; - - TryComp(uid, out AppearanceComponent? appearance); - _appearance.SetData(uid, HarpyVisualLayers.Singing, SingingVisualLayer.True, appearance); - - } - } -} diff --git a/Content.Server/Traits/Assorted/SingerSystem.cs b/Content.Server/Traits/Assorted/SingerSystem.cs new file mode 100644 index 00000000000..7b560957b6e --- /dev/null +++ b/Content.Server/Traits/Assorted/SingerSystem.cs @@ -0,0 +1,161 @@ +using Content.Server.Instruments; +using Content.Server.Speech.Components; +using Content.Server.UserInterface; +using Content.Shared.ActionBlocker; +using Content.Shared.Damage; +using Content.Shared.Damage.ForceSay; +using Content.Shared.FixedPoint; +using Content.Shared.Instruments; +using Content.Shared.Inventory; +using Content.Shared.Inventory.Events; +using Content.Shared.Mobs; +using Content.Shared.Popups; +using Content.Shared.StatusEffect; +using Content.Shared.Stunnable; +using Content.Shared.Traits.Assorted.Components; +using Content.Shared.Traits.Assorted.Prototypes; +using Content.Shared.Traits.Assorted.Systems; +using Content.Shared.UserInterface; +using Content.Shared.Zombies; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; + +namespace Content.Server.Traits.Assorted; + +public sealed class SingerSystem : SharedSingerSystem +{ + [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly InstrumentSystem _instrument = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnEquip); + SubscribeLocalEvent(OnMobStateChangedEvent); + SubscribeLocalEvent(OnKnockedDown); + SubscribeLocalEvent(OnStunned); + SubscribeLocalEvent(OnSleep); + SubscribeLocalEvent(OnStatusEffect); + SubscribeLocalEvent(OnDamageChanged); + // This is intended to intercept and cancel the UI event before it reaches ActivatableUISystem. + SubscribeLocalEvent(OnInstrumentOpen, before: [typeof(ActivatableUISystem)]); + } + + protected override SharedInstrumentComponent EnsureInstrumentComp(EntityUid uid) + { + return EnsureComp(uid); + } + + protected override void SetUpSwappableInstrument(EntityUid uid, SingerInstrumentPrototype singer) + { + if (singer.InstrumentList.Count <= 1) + return; + + var swappableComp = EnsureComp(uid); + swappableComp.InstrumentList = singer.InstrumentList; + } + + private void OnEquip(GotEquippedEvent args) + { + // Check if an item that makes the singer mumble is equipped to their face + // (not their pockets!). As of writing, this should just be the muzzle. + if (TryComp(args.Equipment, out var accent) && + accent.ReplacementPrototype == "mumble" && + args.Slot == "mask") + { + CloseMidiUi(args.Equipee); + } + } + + private void OnMobStateChangedEvent(EntityUid uid, SharedInstrumentComponent component, MobStateChangedEvent args) + { + if (args.NewMobState is MobState.Critical or MobState.Dead) + CloseMidiUi(args.Target); + } + + private void OnKnockedDown(EntityUid uid, SharedInstrumentComponent component, ref KnockedDownEvent args) + { + CloseMidiUi(uid); + } + + private void OnStunned(EntityUid uid, SharedInstrumentComponent component, ref StunnedEvent args) + { + CloseMidiUi(uid); + } + + private void OnSleep(EntityUid uid, SharedInstrumentComponent component, ref SleepStateChangedEvent args) + { + if (args.FellAsleep) + CloseMidiUi(uid); + } + + private void OnStatusEffect(EntityUid uid, SharedInstrumentComponent component, StatusEffectAddedEvent args) + { + if (args.Key == "Muted") + CloseMidiUi(uid); + } + + /// + /// Almost a copy of Content.Server.Damage.ForceSay.DamageForceSaySystem.OnDamageChanged. + /// Done so because DamageForceSaySystem doesn't output an event, and my understanding is + /// that we don't want to change upstream code more than necessary to avoid merge conflicts + /// and maintenance overhead. It still reuses the values from DamageForceSayComponent, so + /// any tweaks to that will keep ForceSay consistent with singing interruptions. + /// + private void OnDamageChanged(EntityUid uid, SharedInstrumentComponent instrumentComponent, DamageChangedEvent args) + { + if (!TryComp(uid, out var component) || + args.DamageDelta == null || + !args.DamageIncreased || + args.DamageDelta.GetTotal() < component.DamageThreshold || + component.ValidDamageGroups == null) + return; + + var totalApplicableDamage = FixedPoint2.Zero; + foreach (var (group, value) in args.DamageDelta.GetDamagePerGroup(ProtoMan)) + { + if (!component.ValidDamageGroups.Contains(group)) + continue; + + totalApplicableDamage += value; + } + + if (totalApplicableDamage >= component.DamageThreshold) + CloseMidiUi(uid); + } + + /// + /// Prevent the player from opening the MIDI UI under some circumstances. + /// + private void OnInstrumentOpen(EntityUid uid, SingerComponent component, OpenUiActionEvent args) + { + // CanSpeak covers all reasons you can't talk, including being incapacitated + // (crit/dead), asleep, or for any reason mute inclding glimmer or a mime's vow. + // TODO why the fuck is any of this hardcoded? + var canNotSpeak = !_actionBlocker.CanSpeak(uid); + var zombified = TryComp(uid, out var _); + var muzzled = _inventory.TryGetSlotEntity(uid, "mask", out var maskUid) && + TryComp(maskUid, out var accent) && + accent.ReplacementPrototype == "mumble"; + + // Set this event as handled when the singer should be incapable of singing in order + // to stop the ActivatableUISystem event from opening the MIDI UI. + args.Handled = canNotSpeak || muzzled || zombified; + + // Tell the user that they can not sing. + if (args.Handled) + _popup.PopupEntity(Loc.GetString("no-sing-while-no-speak"), uid, uid, PopupType.Medium); + } + + public override void CloseMidiUi(EntityUid uid) + { + if (HasComp(uid) && + TryComp(uid, out var actor)) + { + _instrument.ToggleInstrumentUi(uid, actor.PlayerSession); + } + } +} diff --git a/Content.Shared/DeltaV/Harpy/HarpySingerComponent.cs b/Content.Shared/DeltaV/Harpy/HarpySingerComponent.cs deleted file mode 100644 index f2edeeb8726..00000000000 --- a/Content.Shared/DeltaV/Harpy/HarpySingerComponent.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Robust.Shared.GameStates; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization; - -namespace Content.Shared.DeltaV.Harpy -{ - [RegisterComponent, NetworkedComponent] - public sealed partial class HarpySingerComponent : Component - { - [DataField("midiActionId", serverOnly: true, - customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? MidiActionId = "ActionHarpyPlayMidi"; - - [DataField("midiAction", serverOnly: true)] // server only, as it uses a server-BUI event !type - public EntityUid? MidiAction; - } -} diff --git a/Content.Shared/DeltaV/Harpy/HarpySingerSystem.cs b/Content.Shared/DeltaV/Harpy/HarpySingerSystem.cs deleted file mode 100644 index 50e8b6302c0..00000000000 --- a/Content.Shared/DeltaV/Harpy/HarpySingerSystem.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Content.Shared.Actions; - -namespace Content.Shared.DeltaV.Harpy -{ - public class HarpySingerSystem : EntitySystem - { - [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnShutdown); - } - - private void OnStartup(EntityUid uid, HarpySingerComponent component, ComponentStartup args) - { - _actionsSystem.AddAction(uid, ref component.MidiAction, component.MidiActionId); - } - - private void OnShutdown(EntityUid uid, HarpySingerComponent component, ComponentShutdown args) - { - _actionsSystem.RemoveAction(uid, component.MidiAction); - } - } -} - diff --git a/Content.Shared/DeltaV/Harpy/HarpyVisualsSystem.cs b/Content.Shared/DeltaV/Harpy/HarpyVisualsSystem.cs index f75fcee8d42..edab8530228 100644 --- a/Content.Shared/DeltaV/Harpy/HarpyVisualsSystem.cs +++ b/Content.Shared/DeltaV/Harpy/HarpyVisualsSystem.cs @@ -16,11 +16,11 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnDidEquipEvent); - SubscribeLocalEvent(OnDidUnequipEvent); + SubscribeLocalEvent(OnDidEquipEvent); + SubscribeLocalEvent(OnDidUnequipEvent); } - private void OnDidEquipEvent(EntityUid uid, HarpySingerComponent component, DidEquipEvent args) + private void OnDidEquipEvent(EntityUid uid, Traits.Assorted.Components.SingerComponent component, DidEquipEvent args) { if (args.Slot == "outerClothing" && _tagSystem.HasTag(args.Equipment, HarpyWingsTag)) { @@ -29,7 +29,7 @@ private void OnDidEquipEvent(EntityUid uid, HarpySingerComponent component, DidE } } - private void OnDidUnequipEvent(EntityUid uid, HarpySingerComponent component, DidUnequipEvent args) + private void OnDidUnequipEvent(EntityUid uid, Traits.Assorted.Components.SingerComponent component, DidUnequipEvent args) { if (args.Slot == "outerClothing" && _tagSystem.HasTag(args.Equipment, HarpyWingsTag)) { diff --git a/Content.Shared/Traits/Assorted/Components/SingerComponent.cs b/Content.Shared/Traits/Assorted/Components/SingerComponent.cs new file mode 100644 index 00000000000..9c79166ef6c --- /dev/null +++ b/Content.Shared/Traits/Assorted/Components/SingerComponent.cs @@ -0,0 +1,16 @@ +using Content.Shared.Traits.Assorted.Prototypes; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Traits.Assorted.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SingerComponent : Component +{ + // Traits are server-only, and is this is added via traits, it must be replicated to the client. + [DataField(required: true), AutoNetworkedField] + public ProtoId Proto = string.Empty; + + [DataField(serverOnly: true)] + public EntityUid? MidiAction; +} diff --git a/Content.Shared/Traits/Assorted/Prototypes/SingerInstrumentPrototype.cs b/Content.Shared/Traits/Assorted/Prototypes/SingerInstrumentPrototype.cs new file mode 100644 index 00000000000..6a49854f6ea --- /dev/null +++ b/Content.Shared/Traits/Assorted/Prototypes/SingerInstrumentPrototype.cs @@ -0,0 +1,35 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Traits.Assorted.Prototypes; + +[Prototype("SingerInstrument")] +public sealed class SingerInstrumentPrototype : IPrototype +{ + [IdDataField] + public string ID { get; private set; } = default!; + + /// + /// Configuration for SwappableInstrumentComponent. + /// string = display name of the instrument + /// byte 1 = instrument midi program + /// byte 2 = instrument midi bank + /// + [DataField(required: true)] + public Dictionary InstrumentList = new(); + + /// + /// Instrument in that is used by default. + /// + [DataField(required: true)] + public string DefaultInstrument = string.Empty; + + /// + /// The BUI configuration for the instrument. + /// + [DataField] + public PrototypeData? MidiUi; + + // The below is server only, as it uses a server-BUI event !type + [DataField(serverOnly: true, required: true)] + public EntProtoId MidiActionId; +} diff --git a/Content.Shared/Traits/Assorted/Systems/SharedSingerSystem.cs b/Content.Shared/Traits/Assorted/Systems/SharedSingerSystem.cs new file mode 100644 index 00000000000..08d0f5c76d0 --- /dev/null +++ b/Content.Shared/Traits/Assorted/Systems/SharedSingerSystem.cs @@ -0,0 +1,93 @@ +using Content.Shared.Actions; +using Content.Shared.DeltaV.Harpy.Components; +using Content.Shared.Instruments; +using Content.Shared.Traits.Assorted.Components; +using Content.Shared.Traits.Assorted.Prototypes; +using Content.Shared.Zombies; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Traits.Assorted.Systems; + +public abstract class SharedSingerSystem : EntitySystem +{ + [Dependency] protected readonly IPrototypeManager ProtoMan = default!; + + [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedInstrumentSystem _instrument = default!; + [Dependency] private readonly SharedUserInterfaceSystem _ui = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnZombified); + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnBoundUIClosed); + SubscribeLocalEvent(OnBoundUIOpened); + } + + private void OnStartup(Entity ent, ref ComponentStartup args) + { + if (!ProtoMan.TryIndex(ent.Comp.Proto, out var singer)) + return; + + _actionsSystem.AddAction(ent, ref ent.Comp.MidiAction, singer.MidiActionId); + + var instrumentComp = EnsureInstrumentComp(ent); + var defaultData = singer.InstrumentList[singer.DefaultInstrument]; + _instrument.SetInstrumentProgram(instrumentComp, defaultData.Item1, defaultData.Item2); + SetUpSwappableInstrument(ent, singer); + + if (singer.MidiUi is {} uiData && !_ui.TryGetUi(ent, uiData.UiKey, out _)) + _ui.AddUi(ent.Owner, uiData); + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + _actionsSystem.RemoveAction(ent, ent.Comp.MidiAction); + } + + private void OnZombified(ref EntityZombifiedEvent args) + { + CloseMidiUi(args.Target); + } + + private void OnBoundUIClosed(EntityUid uid, SingerComponent component, BoundUIClosedEvent args) + { + if (args.UiKey is not InstrumentUiKey) + return; + + TryComp(uid, out AppearanceComponent? appearance); + _appearance.SetData(uid, HarpyVisualLayers.Singing, SingingVisualLayer.False, appearance); + } + + private void OnBoundUIOpened(EntityUid uid, SingerComponent component, BoundUIOpenedEvent args) + { + if (args.UiKey is not InstrumentUiKey) + return; + + TryComp(uid, out AppearanceComponent? appearance); + _appearance.SetData(uid, HarpyVisualLayers.Singing, SingingVisualLayer.True, appearance); + } + + /// + /// Closes the MIDI UI if it is open. Does nothing on client side. + /// + public virtual void CloseMidiUi(EntityUid uid) + { + } + + /// + /// Sets up the swappable instrument on the entity, only on the server. + /// + protected virtual void SetUpSwappableInstrument(EntityUid uid, SingerInstrumentPrototype singer) + { + } + + /// + /// Ensures an InstrumentComponent on the entity. Uses client-side comp on client and server-side comp on the server. + /// + protected abstract SharedInstrumentComponent EnsureInstrumentComp(EntityUid uid); +} diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 46ee8572a0b..828afa76669 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -188,3 +188,5 @@ trait-description-WeaponsGeneralist = You are a jack of all trades with melee weapons, enabling you to be versatile with your weapon arsenal. Your melee damage bonus for all Brute damage types (Blunt, Slash, Piercing) becomes 25%. +trait-name-Singer = Singer +trait-description-Singer = You are naturally capable of singing simple melodies with your voice. \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Species/harpy.yml b/Resources/Prototypes/Entities/Mobs/Species/harpy.yml index 05d70e8adc5..f4055170b4c 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/harpy.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/harpy.yml @@ -5,30 +5,8 @@ id: MobHarpyBase abstract: true components: - - type: HarpySinger - - type: Instrument - allowPercussion: false - program: 52 - - type: SwappableInstrument - instrumentList: - "Voice": {52: 0} - "Trumpet": {56: 0} - "Electric": {27: 0} - "Bass": {33: 0} - "Rock": {29: 0} - "Acoustic": {24: 0} - "Flute": {73: 0} - "Sax": {66: 0} - - type: UserInterface - interfaces: - - key: enum.InstrumentUiKey.Key - type: InstrumentBoundUserInterface - - key: enum.VoiceMaskUIKey.Key - type: VoiceMaskBoundUserInterface - - key: enum.HumanoidMarkingModifierKey.Key - type: HumanoidMarkingModifierBoundUserInterface - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface + - type: Singer + proto: HarpySinger - type: Sprite scale: 0.9, 0.9 layers: @@ -140,6 +118,7 @@ understands: - GalacticCommon - SolCommon + - type: entity save: false name: Urist McHands diff --git a/Resources/Prototypes/Traits/Misc/singer_types.yml b/Resources/Prototypes/Traits/Misc/singer_types.yml new file mode 100644 index 00000000000..28e4712ee99 --- /dev/null +++ b/Resources/Prototypes/Traits/Misc/singer_types.yml @@ -0,0 +1,26 @@ +- type: SingerInstrument + id: HarpySinger + instrumentList: + "Voice": {52: 0} + "Trumpet": {56: 0} + "Electric": {27: 0} + "Bass": {33: 0} + "Rock": {29: 0} + "Acoustic": {24: 0} + "Flute": {73: 0} + "Sax": {66: 0} + defaultInstrument: "Voice" + midiUi: + key: enum.InstrumentUiKey.Key + type: InstrumentBoundUserInterface + midiActionId: ActionHarpyPlayMidi + +- type: SingerInstrument + id: NormalSinger + instrumentList: + "Voice": {52: 0} + defaultInstrument: "Voice" + midiUi: + key: enum.InstrumentUiKey.Key + type: InstrumentBoundUserInterface + midiActionId: ActionHarpyPlayMidi # TODO: custom action maybe? diff --git a/Resources/Prototypes/Traits/skills.yml b/Resources/Prototypes/Traits/skills.yml index e0115c0562b..7856a68ab34 100644 --- a/Resources/Prototypes/Traits/skills.yml +++ b/Resources/Prototypes/Traits/skills.yml @@ -155,3 +155,16 @@ inverted: true species: - Felinid + +- type: trait + id: Singer + category: Auditory + points: -1 + requirements: + - !type:CharacterSpeciesRequirement + inverted: true + species: + - Harpy + components: + - type: Singer + proto: NormalSinger From 037065ad10ebf0d085d1f4202b40e81c83fe27f0 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Thu, 15 Aug 2024 06:06:52 +0000 Subject: [PATCH 107/135] Automatic Changelog Update (#714) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6ca745cf407..85688b844aa 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5344,3 +5344,11 @@ Entries: message: Added crowned, tall bull, and tall curved Oni horns. id: 6264 time: '2024-08-14T09:05:24.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Add + message: >- + Added a new positive trait - singer. It allows you to play midi songs + without an instrument, similarly to harpies. + id: 6265 + time: '2024-08-15T06:06:25.0000000+00:00' From df73a1cb0b7c615ac30b8422d9d6936f8dad5577 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Date: Thu, 15 Aug 2024 08:24:07 +0200 Subject: [PATCH 108/135] Xenowears (#519) # Description Add a bit of clothing specie related and some tiny misc changes. Normally i wanted to add the spooders changes here but with the other spider specie coming in il hold myself for now. --- # TODO - [x] Add clothings - [x] Loadouts/Vending machines ---

Media

![image](https://github.com/Simple-Station/Einstein-Engines/assets/45297731/47865d65-754d-4b70-9c10-19bc9aa55ac6)

--- # Changelog :cl: - add: Xenowears! new non-human related clothings. --------- Signed-off-by: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> Co-authored-by: VMSolidus --- .../Components/EmitsSoundOnMoveComponent.cs | 35 +++++++ .../EntitySystems/EmitsSoundOnMoveSystem.cs | 96 ++++++++++++++++++ Resources/Prototypes/Actions/types.yml | 2 +- .../Catalog/Cargo/cargo_vending.yml | 2 +- .../Inventories/clothesmate.yml | 1 + .../VendingMachines/Inventories/theater.yml | 2 + .../Entities/Clothing/Neck/mantles.yml | 22 ++++ .../Entities/Clothing/Neck/misc.yml | 14 +++ .../Entities/Clothing/OuterClothing/misc.yml | 11 ++ .../Entities/Clothing/clothwarps.yml | 38 +++++++ Resources/Prototypes/Loadouts/neck.yml | 25 ++++- Resources/Prototypes/Loadouts/shoes.yml | 9 +- .../Graphs/clothing/clothwarp.yml | 13 +++ .../Recipes/Construction/clothing.yml | 11 ++ .../Misc/bellcollar.rsi/equipped-NECK.png | Bin 0 -> 4691 bytes .../Neck/Misc/bellcollar.rsi/icon.png | Bin 0 -> 4596 bytes .../Neck/Misc/bellcollar.rsi/inhand-left.png | Bin 0 -> 5166 bytes .../Neck/Misc/bellcollar.rsi/inhand-right.png | Bin 0 -> 5175 bytes .../Neck/Misc/bellcollar.rsi/meta.json | 26 +++++ .../mantles/oldmantle.rsi/equipped-NECK.png | Bin 0 -> 568 bytes .../Neck/mantles/oldmantle.rsi/icon.png | Bin 0 -> 671 bytes .../Neck/mantles/oldmantle.rsi/meta.json | 18 ++++ .../unathimantle.rsi/equipped-NECK.png | Bin 0 -> 1076 bytes .../Neck/mantles/unathimantle.rsi/icon.png | Bin 0 -> 537 bytes .../Neck/mantles/unathimantle.rsi/meta.json | 18 ++++ .../unathirobe.rsi/equipped-OUTERCLOTHING.png | Bin 0 -> 1400 bytes .../Misc/unathirobe.rsi/icon.png | Bin 0 -> 582 bytes .../Misc/unathirobe.rsi/meta.json | 18 ++++ .../Misc/clothWrap.rsi/equipped-FEET.png | Bin 0 -> 315 bytes .../Misc/clothWrap.rsi/equipped-HAND.png | Bin 0 -> 469 bytes .../Shoes/Misc/clothWrap.rsi/icon.png | Bin 0 -> 704 bytes .../Shoes/Misc/clothWrap.rsi/meta.json | 22 ++++ 32 files changed, 379 insertions(+), 4 deletions(-) create mode 100644 Content.Shared/Clothing/Components/EmitsSoundOnMoveComponent.cs create mode 100644 Content.Shared/Clothing/EntitySystems/EmitsSoundOnMoveSystem.cs create mode 100644 Resources/Prototypes/Entities/Clothing/clothwarps.yml create mode 100644 Resources/Prototypes/Recipes/Construction/Graphs/clothing/clothwarp.yml create mode 100644 Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/equipped-NECK.png create mode 100644 Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/equipped-NECK.png create mode 100644 Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/equipped-NECK.png create mode 100644 Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Neck/mantles/unathimantle.rsi/meta.json create mode 100644 Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/equipped-OUTERCLOTHING.png create mode 100644 Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/icon.png create mode 100644 Resources/Textures/Clothing/OuterClothing/Misc/unathirobe.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-FEET.png create mode 100644 Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-HAND.png create mode 100644 Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/meta.json diff --git a/Content.Shared/Clothing/Components/EmitsSoundOnMoveComponent.cs b/Content.Shared/Clothing/Components/EmitsSoundOnMoveComponent.cs new file mode 100644 index 00000000000..095b0daf384 --- /dev/null +++ b/Content.Shared/Clothing/Components/EmitsSoundOnMoveComponent.cs @@ -0,0 +1,35 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Map; + +namespace Content.Shared.Clothing.Components; + +/// +/// Indicates that the clothing entity emits sound when it moves. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class EmitsSoundOnMoveComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + [DataField(required: true), AutoNetworkedField] + public SoundSpecifier SoundCollection = default!; + + [ViewVariables(VVAccess.ReadWrite)] + [DataField("requiresGravity"), AutoNetworkedField] + public bool RequiresGravity = true; + + [ViewVariables(VVAccess.ReadOnly)] + public EntityCoordinates LastPosition = EntityCoordinates.Invalid; + + /// + /// The distance moved since the played sound. + /// + [ViewVariables(VVAccess.ReadOnly)] + public float SoundDistance = 0f; + + /// + /// Whether this item is equipped in a inventory item slot. + /// + [ViewVariables(VVAccess.ReadOnly)] + public bool IsSlotValid = true; +} diff --git a/Content.Shared/Clothing/EntitySystems/EmitsSoundOnMoveSystem.cs b/Content.Shared/Clothing/EntitySystems/EmitsSoundOnMoveSystem.cs new file mode 100644 index 00000000000..3224b5bca32 --- /dev/null +++ b/Content.Shared/Clothing/EntitySystems/EmitsSoundOnMoveSystem.cs @@ -0,0 +1,96 @@ +using System.Numerics; +using Content.Shared.Clothing.Components; +using Content.Shared.Gravity; +using Content.Shared.Inventory; +using Content.Shared.Inventory.Events; +using Content.Shared.Mobs.Components; +using Content.Shared.Movement.Components; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Physics.Components; +using Robust.Shared.Timing; + +namespace Content.Shared.Clothing.Systems; + +public sealed class EmitsSoundOnMoveSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedMapSystem _grid = default!; + [Dependency] private readonly SharedGravitySystem _gravity = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + private EntityQuery _moverQuery; + private EntityQuery _physicsQuery; + private EntityQuery _clothingQuery; + + public override void Initialize() + { + _moverQuery = GetEntityQuery(); + _physicsQuery = GetEntityQuery(); + _clothingQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnEquipped); + SubscribeLocalEvent(OnUnequipped); + } + + private void OnEquipped(EntityUid uid, EmitsSoundOnMoveComponent component, GotEquippedEvent args) + { + component.IsSlotValid = !args.SlotFlags.HasFlag(SlotFlags.POCKET); + } + + private void OnUnequipped(EntityUid uid, EmitsSoundOnMoveComponent component, GotUnequippedEvent args) + { + component.IsSlotValid = true; + } + + public override void Update(float frameTime) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + UpdateSound(uid, comp); + } + query.Dispose(); + } + + private void UpdateSound(EntityUid uid, EmitsSoundOnMoveComponent component) + { + if (!_physicsQuery.TryGetComponent(uid, out var physics)) + return; + + // Space does not transmit sound + if (Transform(uid).GridUid == null) + return; + + if (component.RequiresGravity && _gravity.IsWeightless(uid, physics, Transform(uid))) + return; + + var parent = Transform(uid).ParentUid; + + var isWorn = parent is { Valid: true } && + _clothingQuery.TryGetComponent(uid, out var clothing) + && clothing.InSlot != null + && component.IsSlotValid; + // If this entity is worn by another entity, use that entity's coordinates + var coordinates = isWorn ? Transform(parent).Coordinates : Transform(uid).Coordinates; + var distanceNeeded = (isWorn && _moverQuery.TryGetComponent(parent, out var mover) && mover.Sprinting) + ? 1.5f // The parent is a mob that is currently sprinting + : 2f; // The parent is not a mob or is not sprinting + + if (!coordinates.TryDistance(EntityManager, component.LastPosition, out var distance) || distance > distanceNeeded) + component.SoundDistance = distanceNeeded; + else + component.SoundDistance += distance; + + component.LastPosition = coordinates; + if (component.SoundDistance < distanceNeeded) + return; + component.SoundDistance -= distanceNeeded; + + var sound = component.SoundCollection; + var audioParams = sound.Params + .WithVolume(sound.Params.Volume) + .WithVariation(sound.Params.Variation ?? 0f); + + _audio.PlayPredicted(sound, uid, uid, audioParams); + } +} diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index f5dff1f453a..cf0a99f3bad 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -375,4 +375,4 @@ useDelay: 40 event: !type:FabricateActionEvent - fabrication: FoodGumball + fabrication: FoodGumball \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml index 7062b2eb155..f7191df9ab4 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml @@ -43,7 +43,7 @@ sprite: Objects/Specific/Service/vending_machine_restock.rsi state: base product: CrateVendingMachineRestockAutoDrobeFilled - cost: 1700 + cost: 1730 category: cargoproduct-category-name-service group: market diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml index bc8f73d618c..6c99f925ee9 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/clothesmate.yml @@ -20,6 +20,7 @@ ClothingEyesGlasses: 6 ClothingHandsGlovesColorBlack: 4 ClothingEyesGlassesCheapSunglasses: 2 + ClothingClothWrap: 4 contrabandInventory: ClothingMaskNeckGaiter: 2 ClothingUniformJumpsuitTacticool: 1 diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml index 79305325bf7..9a1566dab99 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/theater.yml @@ -88,6 +88,8 @@ ClothingShoesBootsCowboyBlack: 1 ClothingShoesBootsCowboyWhite: 1 ClothingMaskNeckGaiterRed: 2 + ClothingNeckBellCollar: 2 + ClothingOuterUnathiRobe: 1 emaggedInventory: ClothingShoesBling: 1 ClothingShoesBootsCowboyFancy: 1 diff --git a/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml b/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml index 7b4ab078911..efdec875e69 100644 --- a/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml +++ b/Resources/Prototypes/Entities/Clothing/Neck/mantles.yml @@ -74,3 +74,25 @@ sprite: Clothing/Neck/mantles/qmmantle.rsi - type: Clothing sprite: Clothing/Neck/mantles/qmmantle.rsi + +- type: entity + parent: ClothingNeckBase + id: ClothingNeckOldMantle + name: old wrap + description: A tattered fabric wrap, faded over the years. Smells faintly of cigars. + components: + - type: Sprite + sprite: Clothing/Neck/mantles/oldmantle.rsi + - type: Clothing + sprite: Clothing/Neck/mantles/oldmantle.rsi + +- type: entity + parent: ClothingNeckBase + id: ClothingNeckUnathiMantle + name: hide mantle + description: A rather grisly selection of cured hides and skin, sewn together to form a ragged mantle. + components: + - type: Sprite + sprite: Clothing/Neck/mantles/unathimantle.rsi + - type: Clothing + sprite: Clothing/Neck/mantles/unathimantle.rsi diff --git a/Resources/Prototypes/Entities/Clothing/Neck/misc.yml b/Resources/Prototypes/Entities/Clothing/Neck/misc.yml index 51325c0bbbd..11921b9a50d 100644 --- a/Resources/Prototypes/Entities/Clothing/Neck/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/Neck/misc.yml @@ -79,3 +79,17 @@ event: !type:StethoscopeActionEvent checkCanInteract: false priority: -1 + +- type: entity + parent: ClothingNeckBase + id: ClothingNeckBellCollar + name: bell collar + description: A way to inform others about your presence, or just to annoy everyone around you! + components: + - type: Sprite + sprite: Clothing/Neck/Misc/bellcollar.rsi + - type: Clothing + sprite: Clothing/Neck/Misc/bellcollar.rsi + - type: EmitsSoundOnMove + soundCollection: + collection: FootstepJester diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml index d17fb275c13..4b2c3c9c3ff 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml @@ -377,3 +377,14 @@ sprite: Clothing/OuterClothing/Misc/red_racoon.rsi - type: Clothing sprite: Clothing/OuterClothing/Misc/red_racoon.rsi + +- type: entity + parent: ClothingOuterBase + id: ClothingOuterUnathiRobe + name: roughspun robes + description: A traditional Unathi garment. + components: + - type: Sprite + sprite: Clothing/OuterClothing/Misc/unathirobe.rsi + - type: Clothing + sprite: Clothing/OuterClothing/Misc/unathirobe.rsi diff --git a/Resources/Prototypes/Entities/Clothing/clothwarps.yml b/Resources/Prototypes/Entities/Clothing/clothwarps.yml new file mode 100644 index 00000000000..eadeaa0b286 --- /dev/null +++ b/Resources/Prototypes/Entities/Clothing/clothwarps.yml @@ -0,0 +1,38 @@ +- type: entity + parent: Clothing + id: ClothingClothWrap + name: cloth wraps + description: A roll of treated canvas used for wrapping claws or paws. + components: + - type: Item + size: Small + storedRotation: -90 + - type: Sprite + state: icon + sprite: Clothing/Shoes/Misc/clothWrap.rsi + - type: Clothing + slots: + - gloves + - FEET + sprite: Clothing/Shoes/Misc/clothWrap.rsi + - type: Construction + graph: ClothingClothWrap + node: shoes + - type: Butcherable + butcheringType: Knife + spawned: + - id: MaterialCloth1 + amount: 1 + - type: Food + requiresSpecialDigestion: true + - type: SolutionContainerManager + solutions: + food: + maxVol: 10 + reagents: + - ReagentId: Fiber + Quantity: 10 + - type: Tag + tags: + - ClothMade + - WhitelistChameleon diff --git a/Resources/Prototypes/Loadouts/neck.yml b/Resources/Prototypes/Loadouts/neck.yml index c7fc7003653..3e0227d1dae 100644 --- a/Resources/Prototypes/Loadouts/neck.yml +++ b/Resources/Prototypes/Loadouts/neck.yml @@ -6,6 +6,30 @@ items: - ClothingNeckHeadphones +- type: loadout + id: LoadoutNeckBellCollar + category: Neck + cost: 2 + exclusive: true + items: + - ClothingNeckBellCollar + +- type: loadout + id: LoadoutNeckOldMantle + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckOldMantle + +- type: loadout + id: LoadoutNeckUnathiMantle + category: Neck + cost: 1 + exclusive: true + items: + - ClothingNeckUnathiMantle + # Scarves - type: loadout id: LoadoutNeckScarfStripedRed @@ -120,7 +144,6 @@ items: - ClothingNeckTieGreen - #Pride Accessories - type: loadout id: LoadoutItemsPrideLGBTPin diff --git a/Resources/Prototypes/Loadouts/shoes.yml b/Resources/Prototypes/Loadouts/shoes.yml index 470cac29834..e67ca70b392 100644 --- a/Resources/Prototypes/Loadouts/shoes.yml +++ b/Resources/Prototypes/Loadouts/shoes.yml @@ -341,7 +341,6 @@ items: - ClothingUnderSocksCoder -# Socks - type: loadout id: LoadoutShoesUnderSocksBee category: Shoes @@ -355,3 +354,11 @@ - Harpy items: - ClothingUnderSocksBee + +- type: loadout + id: LoadoutShoesClothWrap + category: Shoes + cost: 1 + exclusive: true + items: + - ClothingClothWrap diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/clothing/clothwarp.yml b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/clothwarp.yml new file mode 100644 index 00000000000..864d8f18d20 --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/clothwarp.yml @@ -0,0 +1,13 @@ +- type: constructionGraph + id: ClothingClothWrap + start: start + graph: + - node: start + edges: + - to: shoes + steps: + - material: Cloth + amount: 2 + doAfter: 1 + - node: shoes + entity: ClothingClothWrap diff --git a/Resources/Prototypes/Recipes/Construction/clothing.yml b/Resources/Prototypes/Recipes/Construction/clothing.yml index f1eb270af73..54218d28226 100644 --- a/Resources/Prototypes/Recipes/Construction/clothing.yml +++ b/Resources/Prototypes/Recipes/Construction/clothing.yml @@ -96,3 +96,14 @@ description: Comfy, yet haunted by the ghosts of ducks you fed bread to as a child. icon: { sprite: Clothing/Shoes/Misc/duck-slippers.rsi, state: icon } objectType: Item + +- type: construction + name: cloth wraps + id: ClothingClothWrap + graph: ClothingClothWrap + startNode: start + targetNode: shoes + category: construction-category-clothing + description: A roll of treated canvas used for wrapping claws or paws. + icon: { sprite: Clothing/Shoes/Misc/clothWrap.rsi, state: icon } + objectType: Item diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/equipped-NECK.png b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/equipped-NECK.png new file mode 100644 index 0000000000000000000000000000000000000000..2190dc844dba0dffd0b5b4050a7c3043c64205a0 GIT binary patch literal 4691 zcmeHLdsGzH8J`7>1Ou@x8hkX)88E1v*?H`XnX)|GMcByd78b!O>g>$y?&$8$usgtl zl{DHI`%q((iZP_NYSWWPQy;NSMM{fujEymzCZS10-GZ8EqUcFZ(U@rO%r48)=A0f* z>wgUAa=&};cYpW$e&2ULnE8=oacNrWj8q7M(rjhc3eXoRE#*G&`z4|79O!!Z8k^f@ zn-8Uc0npS;fHaB@Xqp5$Ns|mEgSkzheG|xvj?!jmCaV2Ufjl!NKLg~sF&$+Op-F<$ zK;H%$3FHjWzXY1_Wb~{*0aj-eZ=9eQDDM(8)9mjxu8wHESVY66ZDJZ%H9}hv{w)NZ1WygwUb+4-YH8OQluCwk9 z$Mc`=LAHMH3B;Llc)`o*kF>TFKfNityZgHmns@U+O}$jt``%xwrc5X-T2b4UQM>Q> z-8oN8BOabLG;p@##M$o@d7V4m^=~EZ3Osk2TX5>q((azzuFNiY&*s0LA}?jnn|S_4 z{WfUTV1NFbcl&nlUGmoQ2U0d4KXeNB_oww=wx5X{T{4TAvusX5&cmk58;);VQJvp1 zutHuIdG;H+r+<;Nb;?h=)0fgae_p;N{NubA*3cIxFWXjidU@O7N4Fflc5+qb=}&Us zT=5%fL-w=-6YfVc-gPXTXzYLO%D$SicUrnm6n^@}oZ!3*^EYm1HC5iHY71}9{_(gKV+nGCSl6T(9?l{-$DlNKel&+XLe$h41ZKWkolb>MT&8;NFBhCOa*e&5W<|f2;Y1g&4f`b}UQm8vSYp_$bI9d`G8c3ud70wTGZo0y{Fa`leX2dJY5{+Sv zjg8tyomLEbFoL2e3@0&?M1ckxY6{3q7!8E76o@E>l@GB&L6QYA04tb`ORSg82m;pO zVf*}&-5!SzgkmfJKCmz&VT2aP{C+HPM@TMd03b1gzII2**(C8;1s@XYgDhXtzz5{4 zLq#Ss*jJc3_RodV>II*eoEdQyGRr|NJl#`}0b01W~Ah*A2o;2t4slx@n2>Q15| z;J7&cDD7e2Rb`-Mx6@XUtyd1USkK-|pd%=fFyINhm-4|7NH_&kt&r+= zj-?j@LOAm;wgh=b7K2Vv^qG-((Ty+L!FA#o znXxi54^E4hVdroe&c$_f%rXVeE^>mq>Az_!mj})V`XJ*9Yu#e zLA^>atX>M5VWTdDm60Xzb(Kzgcwpy0V`1m}&`ZuIg>cmQE2L87GI ziIX5_Xgw7p47>L(>R7#z*O>^^$mLO}-laF7l*>SY3&V1pku>2rLyk83e{#|I?>P~3 zF&|UP;&4#&vHu8rR3V{`0&1djpgx0gkHzbKj583Dd-=rD?Oq-M!{djHiQjR$#_1Xp z17lJi&#rO0#>Bvwl*hB{|3+8p$QvUc0RQMUg7?9xmkYOmcgg!)i%PBPTP1YM(*78b z?w87zg&=71x0I%VcC}@K$w{)!UNY&U2c}P*K09msft%oaLAuRa>`Jj5PX5({}UnHe}(ARe*`}Ieci>);o#WOlg z-oc?mm-<3?CGzSc8D_mEGNR>uUf0svST4 zS-~eATi^AhZW=iGs_pdtVqa(3-aCJUsvkN(b8F73svT{UiQn#c+eMQ@cP7hNZQkyV zOk4B1^~RM2e}1g)z2x%q)h(UpI$8^(?n2NHs_9nkD+e$9Ay@AC-Glu{`wrJ#pTDRe zJ1u=^+h+%FtbfH=dgjRY{Zi=SYvQx*?n603hxuBwx2vJ$QnD{cHtQl^m4oju;Q9M) Z&51>e_Fs3;cu^VJN)}sRU9ft?zX0;DP$K{U literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/icon.png b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1790484039767872acd61f6aa8c7c32bde7b8669 GIT binary patch literal 4596 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/meta.json b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/meta.json new file mode 100644 index 00000000000..464e2e4a352 --- /dev/null +++ b/Resources/Textures/Clothing/Neck/Misc/bellcollar.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by mnemotechnician (GitHub)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-NECK", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/equipped-NECK.png b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/equipped-NECK.png new file mode 100644 index 0000000000000000000000000000000000000000..d317412c9dd1a52e5f283dce4e6a55af629aa8bc GIT binary patch literal 568 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|VnL zPZ!6KiaBp*IeHxq5NNAE_~=knRJXS7BSse6Ht~Q9Tb1%+A_cB1U70E^7_0q))uye< zJs>dZQs~)<4y$kvs0TNTFjsSE>3@1*WHf?6VGbbDKRcrzp7Am??*<< z@%8K9e>idIXJV22)wvILl+E15a&P)aiRJPliaXUr1+^2(t8EhwCe3`D@vxotL zbK}#$eR0+LJoD7ksw8harsAjH_13*h`s``KtkMu&vCx27ZF1^Ey&#e4GE4uf9TNQ{ zzL9Cx+4CDNggrl5?Bf==qx(pitAV-F&SQew4f>}0Y8ILIs~Kd?U|+sFy5iFG!bPeR zp3b)AowVj_-HrbY8pl~2EY%oJ88V`K6jwWFyEfe^e*5%i>5IKiX0GB|pKY(p z$<5z$yCRM$;?Jd|rPX@UsyF7QHc#q3x#oAr8O1kY literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/icon.png b/Resources/Textures/Clothing/Neck/mantles/oldmantle.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4cf647611dcfd9c7110ec2321da9c381e628dc06 GIT binary patch literal 671 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-HAND.png b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/equipped-HAND.png new file mode 100644 index 0000000000000000000000000000000000000000..b78a810df85f2ed9659b419c1dd8f095848db8f9 GIT binary patch literal 469 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|R5b zr;B4q#hkaZ4)!)12)NcSd8??tYeDZ4u1jtLTPB7usup^Q>exrE|CVATv3A10`sq&| ze4LTKf!{b@;5d^)AFG25cY}o(L!l1CqX>p08yPw#ix%v^|9sV|g57uhE_TZIAGh%p z{XR)1jDSqO(qu`kBeE%syllJG{zPd4zaZZZN@$DTPGUqLh>F;h| zd!_WRb-c;{`#)qN8SflaQ9Sgs=GfCB%{pcaca!p_!k+l#uL4h8uD>?@!dvvmfXA52 zlWB1}!|~5NKT?=CF>RBv>s+yA@8^1{*VzJ4XC*V@a4$r{FM`4QeC+jyTN;=R^*6}K zy>;i{OgLzG^{(ckB|j7WcZjX)lnxHPDzj3v?S8`*{R2Wj0u$s9y#9JC#EYNPBlYM_33+4a$43qcAz-t c6VpD%CkzX$9mdKI;Vst0A&@vMgRZ+ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/icon.png b/Resources/Textures/Clothing/Shoes/Misc/clothWrap.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8f531e890c1a5d777b5a5ad2569bff2e68ba72d0 GIT binary patch literal 704 zcmV;x0zdtUP)Ox2pG(>|7;mh!O_z=dpGHQ%5RtX_ud_M@`Q7lLs zGzMs)mv-)47se&_5=`o%XFuosW-{l@h-@}XBg1HD^(LSRXafERfIM!3T<)!HgP|qW z-rf;?)b-+DO~TFf50x;~4j=$}Qo|z3x?`Qd_u@iM7=|mQY#Yg3ccruu0=$+4*{Aoz zD2T{_wbj=-X-bO4t+Rl*ICRg>S~CVTs($eV}^SXfx?vmG1H z^?;Dl?oU$bG#w{9F$@FS_7E5tritgp=sJ_)TmD_$Q-}n3^x$qdHg=svq7@-vduN;V z{2EJ(Ul=%l1!*}5@w<-J0a|N@E?=cs$k)wX7x3`Gov+tMM_E}}MyUYXu?Ry*#N(7o zB|-#B)u>i|0tJN$iO_WmDj?4bu9z%(V6Ws&Y5U}^DF zl-kh%p$=<1J3GW;F8TadGMNlohs@5*qIHedcngjfBbn@^H#LCkw$Rp|WPUCisSP6y zq9>2Y)+Eremx)_w}lZQ<3+XR3POo8775NMk-y7wqnq zDHIA!Ox~tcE|br%<2VlI`uj*E+F4%uveI_ruAFNo?Cj z1sWj)Qc6~rJ{OZ+m(Coe=%Ik=>1ktXYUXGf1n9y0-At^1AYOYhxx)Z$>N*<0000 Date: Thu, 15 Aug 2024 06:24:31 +0000 Subject: [PATCH 109/135] Automatic Changelog Update (#519) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 85688b844aa..0d1db3042f8 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5352,3 +5352,9 @@ Entries: without an instrument, similarly to harpies. id: 6265 time: '2024-08-15T06:06:25.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Add + message: Xenowears! new non-human related clothings. + id: 6266 + time: '2024-08-15T06:24:07.0000000+00:00' From d9a04690a4f32711f90d92803c7ce7660c2193fa Mon Sep 17 00:00:00 2001 From: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:11:05 +0200 Subject: [PATCH 110/135] Vulpkanin Update (#715) ![WarningTrystan](https://github.com/user-attachments/assets/958f868b-11b9-48f0-80ab-13d9ff243f06) # Description This PR is the rework regarding the unique feature for vulpkanins, this is mostly due to the "FORCED" Issue by VM: https://github.com/Simple-Station/Einstein-Engines/issues/711 This PR will mostly add the new features that will mostly make Vulpkanins unique. For Vulpkanin Stats changed please check this PR: https://github.com/Simple-Station/Einstein-Engines/pull/713 - Flash Damge: Flashable has 2 new variables "EyeDamageChance" (Float) and "EyeDamage" (int), those are default to 0 but if changed could give a chance from 0 to 1 to give EyeDamage from the EyeDamage Value, this is not fixed to vulpkanin and can be added to anything with the "Flashable" Component. - ScentTracker: Add a new Forensics type "Scent", scent will spread on everything you wear and only the ent with the "ScentTrackerSystem" can track a scent, tracking a scent will leave an effect on those who has or the item with the scent, scent can be cleaned away with soap or you can compleatly generate a new scent of a person by cleaning yourself, note: someone with a scent does not mean his the one making that scent, they may just have an item with the scent in their bag! - Vulpkanins Screams: I have 5 Fox Screams that need to be edited and need to be added in-game for vulpkanins with a lisence, just need to have the time to do it and this PR seem the perfect place for it. --- # TODO - [x] Flash Damage - [x] Scent System - [x] ScentTracker System - [x] Vulpkanin Screams ---

Media

![image](https://github.com/user-attachments/assets/3bd60c0f-2528-4be7-a52d-defe2990c475) ![image](https://github.com/user-attachments/assets/6756b6af-3f76-4faa-9fbd-c35964b267b3) ![image](https://github.com/user-attachments/assets/b4ff84a2-64eb-4985-876b-d3e93fc8bd12) ![image](https://github.com/user-attachments/assets/dd4b47ea-ae39-44c3-b5a2-27ee68703857)

--- # Changelog :cl: FoxxoTrystan - add: Forensics Scent Type and Vulpkanins can now track scents, better keep yourself clean! - tweak: Vulpkanins eyes are sensetive, please dont flash them with lights as this could damage them. - add: Vulpkanins now has their own screams! --------- Signed-off-by: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Co-authored-by: VMSolidus Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- .../Forensics/ScentTrackerSystem.cs | 31 +++++ .../Behaviors/SpawnEntitiesBehavior.cs | 4 +- Content.Server/Flash/FlashSystem.cs | 9 ++ .../Forensics/Components/ScentComponent.cs | 11 ++ .../Forensics/Systems/ForensicsSystem.cs | 109 +++++++++++++-- .../Forensics/Systems/ScentTrackerSystem.cs | 130 ++++++++++++++++++ Content.Shared/Flash/FlashableComponent.cs | 21 ++- Content.Shared/Flash/SharedFlashSystem.cs | 2 +- Content.Shared/Forensics/Events.cs | 5 +- .../Forensics}/ForensicsComponent.cs | 23 +++- .../Forensics/ScentTrackerComponent.cs | 20 +++ .../Audio/Voice/Vulpkanin/attritbutions.yml | 4 + .../Audio/Voice/Vulpkanin/vulpscream1.ogg | Bin 0 -> 10464 bytes .../Audio/Voice/Vulpkanin/vulpscream2.ogg | Bin 0 -> 10250 bytes .../Audio/Voice/Vulpkanin/vulpscream3.ogg | Bin 0 -> 13946 bytes .../Audio/Voice/Vulpkanin/vulpscream4.ogg | Bin 0 -> 14982 bytes .../Audio/Voice/Vulpkanin/vulpscream5.ogg | Bin 0 -> 11328 bytes Resources/Locale/en-US/forensics/scent.ftl | 10 ++ .../Entities/Mobs/Species/vulpkanin.yml | 7 +- .../DeltaV/SoundCollections/vulpkanin.yml | 9 ++ .../DeltaV/Voice/speech_emote_sounds.yml | 4 +- .../Prototypes/Entities/Mobs/Species/base.yml | 1 + .../Objects/Specific/Forensics/forensics.yml | 19 +++ 23 files changed, 393 insertions(+), 26 deletions(-) create mode 100644 Content.Client/Forensics/ScentTrackerSystem.cs create mode 100644 Content.Server/Forensics/Components/ScentComponent.cs create mode 100644 Content.Server/Forensics/Systems/ScentTrackerSystem.cs rename {Content.Server/Forensics/Components => Content.Shared/Forensics}/ForensicsComponent.cs (56%) create mode 100644 Content.Shared/Forensics/ScentTrackerComponent.cs create mode 100644 Resources/Audio/Voice/Vulpkanin/attritbutions.yml create mode 100644 Resources/Audio/Voice/Vulpkanin/vulpscream1.ogg create mode 100644 Resources/Audio/Voice/Vulpkanin/vulpscream2.ogg create mode 100644 Resources/Audio/Voice/Vulpkanin/vulpscream3.ogg create mode 100644 Resources/Audio/Voice/Vulpkanin/vulpscream4.ogg create mode 100644 Resources/Audio/Voice/Vulpkanin/vulpscream5.ogg create mode 100644 Resources/Locale/en-US/forensics/scent.ftl diff --git a/Content.Client/Forensics/ScentTrackerSystem.cs b/Content.Client/Forensics/ScentTrackerSystem.cs new file mode 100644 index 00000000000..4e6254502aa --- /dev/null +++ b/Content.Client/Forensics/ScentTrackerSystem.cs @@ -0,0 +1,31 @@ +using Content.Shared.Forensics; +using Robust.Shared.Random; +using Robust.Shared.Timing; +using Robust.Client.Player; + +namespace Content.Client.Forensics +{ + public sealed class ScentTrackerSystem : EntitySystem + { + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = AllEntityQuery(); + while (query.MoveNext(out var uid, out var comp)) + if (TryComp(_playerManager.LocalEntity, out var scentcomp) + && scentcomp.Scent != string.Empty + && scentcomp.Scent == comp.Scent + && _timing.CurTime > comp.TargetTime) + { + comp.TargetTime = _timing.CurTime + TimeSpan.FromSeconds(1.0f); + Spawn("ScentTrackEffect", _transform.GetMapCoordinates(uid).Offset(_random.NextVector2(0.25f))); + } + } + } +} \ No newline at end of file diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs index 0fa3c06c04b..65851f17360 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs @@ -1,11 +1,12 @@ using System.Numerics; -using Content.Server.Forensics; +using Content.Shared.Forensics; using Content.Server.Stack; using Content.Shared.Prototypes; using Content.Shared.Stacks; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; +using Content.Server.Administration.Commands; namespace Content.Server.Destructible.Thresholds.Behaviors { @@ -85,6 +86,7 @@ public void TransferForensics(EntityUid spawned, DestructibleSystem system, Enti if (!system.Random.Prob(0.4f)) return; + comp.Fingerprints = forensicsComponent.Fingerprints; comp.Fibers = forensicsComponent.Fibers; } diff --git a/Content.Server/Flash/FlashSystem.cs b/Content.Server/Flash/FlashSystem.cs index 3f1e4e731df..7706bfec4ea 100644 --- a/Content.Server/Flash/FlashSystem.cs +++ b/Content.Server/Flash/FlashSystem.cs @@ -21,6 +21,8 @@ using Robust.Shared.Timing; using InventoryComponent = Content.Shared.Inventory.InventoryComponent; using Content.Shared.Traits.Assorted.Components; +using Robust.Shared.Random; +using Content.Shared.Eye.Blinding.Systems; namespace Content.Server.Flash { @@ -37,6 +39,8 @@ internal sealed class FlashSystem : SharedFlashSystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly StunSystem _stun = default!; [Dependency] private readonly TagSystem _tag = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly BlindableSystem _blindingSystem = default!; public override void Initialize() { @@ -139,6 +143,11 @@ public void Flash(EntityUid target, flashable.Duration = flashDuration / 1000f; // TODO: Make this sane... Dirty(target, flashable); + if (TryComp(target, out var blindable) + && !blindable.IsBlind + && _random.Prob(flashable.EyeDamageChance)) + _blindingSystem.AdjustEyeDamage((target, blindable), flashable.EyeDamage); + _stun.TrySlowdown(target, TimeSpan.FromSeconds(flashDuration/1000f), true, slowTo, slowTo); diff --git a/Content.Server/Forensics/Components/ScentComponent.cs b/Content.Server/Forensics/Components/ScentComponent.cs new file mode 100644 index 00000000000..85331f36126 --- /dev/null +++ b/Content.Server/Forensics/Components/ScentComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Server.Forensics; + +/// +/// This component is for mobs that have a Scent. +/// +[RegisterComponent] +public sealed partial class ScentComponent : Component +{ + [DataField] + public string Scent = String.Empty; +} diff --git a/Content.Server/Forensics/Systems/ForensicsSystem.cs b/Content.Server/Forensics/Systems/ForensicsSystem.cs index 1663c20fedb..dff134a5113 100644 --- a/Content.Server/Forensics/Systems/ForensicsSystem.cs +++ b/Content.Server/Forensics/Systems/ForensicsSystem.cs @@ -11,6 +11,7 @@ using Content.Shared.Inventory; using Content.Shared.Weapons.Melee.Events; using Robust.Shared.Random; +using Content.Shared.Inventory.Events; namespace Content.Server.Forensics { @@ -23,9 +24,11 @@ public sealed class ForensicsSystem : EntitySystem public override void Initialize() { SubscribeLocalEvent(OnInteract); + SubscribeLocalEvent(OnEquip); SubscribeLocalEvent(OnFiberInit); SubscribeLocalEvent(OnFingerprintInit); SubscribeLocalEvent(OnDNAInit); + SubscribeLocalEvent(OnScentInit); SubscribeLocalEvent(OnBeingGibbed); SubscribeLocalEvent(OnMeleeHit); @@ -40,6 +43,11 @@ private void OnInteract(EntityUid uid, FingerprintComponent component, ContactIn ApplyEvidence(uid, args.Other); } + private void OnEquip(EntityUid uid, ScentComponent component, DidEquipEvent args) + { + ApplyScent(uid, args.Equipment); + } + private void OnFiberInit(EntityUid uid, FiberComponent component, MapInitEvent args) { component.Fiberprint = GenerateFingerprint(length: 7); @@ -53,35 +61,49 @@ private void OnFingerprintInit(EntityUid uid, FingerprintComponent component, Ma private void OnDNAInit(EntityUid uid, DnaComponent component, MapInitEvent args) { component.DNA = GenerateDNA(); + + } + + private void OnScentInit(EntityUid uid, ScentComponent component, MapInitEvent args) + { + component.Scent = GenerateFingerprint(length: 5); + + var updatecomp = EnsureComp(uid); + updatecomp.Scent = component.Scent; + + Dirty(uid, updatecomp); } private void OnBeingGibbed(EntityUid uid, DnaComponent component, BeingGibbedEvent args) { - foreach(EntityUid part in args.GibbedParts) + foreach (EntityUid part in args.GibbedParts) { var partComp = EnsureComp(part); partComp.DNAs.Add(component.DNA); partComp.CanDnaBeCleaned = false; + Dirty(part, partComp); } } private void OnMeleeHit(EntityUid uid, ForensicsComponent component, MeleeHitEvent args) { - if((args.BaseDamage.DamageDict.TryGetValue("Blunt", out var bluntDamage) && bluntDamage.Value > 0) || + if ((args.BaseDamage.DamageDict.TryGetValue("Blunt", out var bluntDamage) && bluntDamage.Value > 0) || (args.BaseDamage.DamageDict.TryGetValue("Slash", out var slashDamage) && slashDamage.Value > 0) || (args.BaseDamage.DamageDict.TryGetValue("Piercing", out var pierceDamage) && pierceDamage.Value > 0)) { - foreach(EntityUid hitEntity in args.HitEntities) + foreach (EntityUid hitEntity in args.HitEntities) { - if(TryComp(hitEntity, out var hitEntityComp)) + if (TryComp(hitEntity, out var hitEntityComp)) component.DNAs.Add(hitEntityComp.DNA); } } + Dirty(uid, component); } private void OnRehydrated(Entity ent, ref GotRehydratedEvent args) { CopyForensicsFrom(ent.Comp, args.Target); + Dirty(args.Target, ent.Comp); } /// @@ -112,19 +134,43 @@ private void OnAfterInteract(EntityUid uid, CleansForensicsComponent component, if (args.Handled) return; - if (!TryComp(args.Target, out var forensicsComp)) + if (TryComp(args.Target, out var forensicsComp) + && forensicsComp.DNAs.Count > 0 && forensicsComp.CanDnaBeCleaned + && forensicsComp.Fingerprints.Count + forensicsComp.Fibers.Count > 0 + && forensicsComp.Scent != string.Empty) + { + var cleanDelay = component.CleanDelay; + if (HasComp(args.Target)) + cleanDelay += 30; + + var doAfterArgs = new DoAfterArgs(EntityManager, args.User, cleanDelay, new CleanForensicsDoAfterEvent(), uid, target: args.Target, used: args.Used) + { + BreakOnHandChange = true, + NeedHand = true, + BreakOnDamage = true, + BreakOnTargetMove = true, + MovementThreshold = 0.01f, + DistanceThreshold = forensicsComp.CleanDistance, + }; + + _doAfterSystem.TryStartDoAfter(doAfterArgs); + _popupSystem.PopupEntity(Loc.GetString("forensics-cleaning", ("target", args.Target)), args.User, args.User); + + args.Handled = true; return; + } - if((forensicsComp.DNAs.Count > 0 && forensicsComp.CanDnaBeCleaned) || (forensicsComp.Fingerprints.Count + forensicsComp.Fibers.Count > 0)) + if (TryComp(args.Target, out var scentComp)) { - var doAfterArgs = new DoAfterArgs(EntityManager, args.User, component.CleanDelay, new CleanForensicsDoAfterEvent(), uid, target: args.Target, used: args.Used) + var cleanDelay = component.CleanDelay + 30; + var doAfterArgs = new DoAfterArgs(EntityManager, args.User, cleanDelay, new CleanForensicsDoAfterEvent(), uid, target: args.Target, used: args.Used) { BreakOnHandChange = true, NeedHand = true, BreakOnDamage = true, BreakOnTargetMove = true, MovementThreshold = 0.01f, - DistanceThreshold = forensicsComp.CleanDistance, + DistanceThreshold = 1.5f, }; _doAfterSystem.TryStartDoAfter(doAfterArgs); @@ -144,6 +190,7 @@ private void OnCleanForensicsDoAfter(EntityUid uid, ForensicsComponent component targetComp.Fibers = new(); targetComp.Fingerprints = new(); + targetComp.Scent = String.Empty; if (targetComp.CanDnaBeCleaned) targetComp.DNAs = new(); @@ -154,6 +201,30 @@ private void OnCleanForensicsDoAfter(EntityUid uid, ForensicsComponent component if (TryComp(args.Used, out var residue)) targetComp.Residues.Add(string.IsNullOrEmpty(residue.ResidueColor) ? Loc.GetString("forensic-residue", ("adjective", residue.ResidueAdjective)) : Loc.GetString("forensic-residue-colored", ("color", residue.ResidueColor), ("adjective", residue.ResidueAdjective))); + + // If the ent has a Scent Component, we compleatly generate a new one and apply the new scent to all currently weared items. + if (TryComp(args.Target, out var scentComp)) + { + var generatedscent = GenerateFingerprint(length: 5); + scentComp.Scent = generatedscent; + targetComp.Scent = generatedscent; + + if (args.Target is { Valid: true } target + && _inventory.TryGetSlots(target, out var slotDefinitions)) + foreach (var slot in slotDefinitions) + { + if (!_inventory.TryGetSlotEntity(target, slot.Name, out var slotEnt)) + continue; + + EnsureComp(slotEnt.Value, out var recipientComp); + recipientComp.Scent = generatedscent; + + Dirty(slotEnt.Value, recipientComp); + } + } + + if (args.Target is { Valid: true } targetuid) + Dirty(targetuid, targetComp); } public string GenerateFingerprint(int length = 16) @@ -193,10 +264,28 @@ private void ApplyEvidence(EntityUid user, EntityUid target) } if (HasComp(gloves)) + { + Dirty(target, component); return; + } } if (TryComp(user, out var fingerprint)) + { component.Fingerprints.Add(fingerprint.Fingerprint ?? ""); + Dirty(target, component); + } + } + + private void ApplyScent(EntityUid user, EntityUid target) + { + if (HasComp(target)) + return; + + var component = EnsureComp(target); + if (TryComp(user, out var scent)) + component.Scent = scent.Scent; + + Dirty(target, component); } private void OnTransferDnaEvent(EntityUid uid, DnaComponent component, ref TransferDnaEvent args) @@ -204,6 +293,8 @@ private void OnTransferDnaEvent(EntityUid uid, DnaComponent component, ref Trans var recipientComp = EnsureComp(args.Recipient); recipientComp.DNAs.Add(component.DNA); recipientComp.CanDnaBeCleaned = args.CanDnaBeCleaned; + + Dirty(args.Recipient, recipientComp); } #region Public API @@ -221,6 +312,8 @@ public void TransferDna(EntityUid recipient, EntityUid donor, bool canDnaBeClean EnsureComp(recipient, out var recipientComp); recipientComp.DNAs.Add(donorComp.DNA); recipientComp.CanDnaBeCleaned = canDnaBeCleaned; + + Dirty(recipient, recipientComp); } } diff --git a/Content.Server/Forensics/Systems/ScentTrackerSystem.cs b/Content.Server/Forensics/Systems/ScentTrackerSystem.cs new file mode 100644 index 00000000000..e3542eaba47 --- /dev/null +++ b/Content.Server/Forensics/Systems/ScentTrackerSystem.cs @@ -0,0 +1,130 @@ +using Content.Server.Popups; +using Content.Shared.DoAfter; +using Content.Shared.Verbs; +using Content.Shared.Forensics; +using Content.Shared.Examine; +using Robust.Shared.Utility; +using Content.Shared.IdentityManagement; + +namespace Content.Server.Forensics +{ + public sealed class ScentTrackerSystem : EntitySystem + { + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + public override void Initialize() + { + SubscribeLocalEvent>(AddVerbs); + SubscribeLocalEvent(TrackScentDoAfter); + SubscribeLocalEvent((uid, _, args) => OnExamine(uid, args)); + } + + private void AddVerbs(EntityUid uid, ScentTrackerComponent component, GetVerbsEvent args) + { + TrackScentVerb(uid, component, args); + StopTrackScentVerb(uid, component, args); + } + + private void TrackScentVerb(EntityUid uid, ScentTrackerComponent component, GetVerbsEvent args) + { + if (!args.CanInteract + || !args.CanAccess + || args.User == args.Target) + return; + + InnateVerb verbTrackScent = new() + { + Act = () => AttemptTrackScent(uid, args.Target, component), + Text = Loc.GetString("track-scent"), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/psionic_invisibility.png")), + Priority = 1 + }; + args.Verbs.Add(verbTrackScent); + } + + private void AttemptTrackScent(EntityUid user, EntityUid target, ScentTrackerComponent component) + { + if (!HasComp(user)) + return; + + var doAfterEventArgs = new DoAfterArgs(EntityManager, user, component.SniffDelay, new ScentTrackerDoAfterEvent(), user, target: target) + { + BreakOnUserMove = true, + BreakOnDamage = true, + BreakOnTargetMove = true + }; + + _popupSystem.PopupEntity(Loc.GetString("start-tracking-scent", ("user", Identity.Name(user, EntityManager)), ("target", Identity.Name(target, EntityManager))), user); + _doAfterSystem.TryStartDoAfter(doAfterEventArgs); + } + + private void TrackScentDoAfter(Entity entity, ref ScentTrackerDoAfterEvent args) + { + if (args.Handled + || args.Cancelled + || args.Args.Target == null) + return; + + TrackScent(args.Args.User, args.Args.Target.Value); + + args.Handled = true; + } + + private void StopTrackScentVerb(EntityUid uid, ScentTrackerComponent component, GetVerbsEvent args) + { + if (args.User != args.Target + || component.Scent == string.Empty) + return; + + InnateVerb verbStopTrackScent = new() + { + Act = () => StopTrackScent(uid, component), + Text = Loc.GetString("stop-track-scent"), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/psionic_invisibility.png")), + Priority = 2 + }; + args.Verbs.Add(verbStopTrackScent); + } + + private void OnExamine(EntityUid uid, ExaminedEvent args) + { + if (!TryComp(args.Examiner, out var component) + || !TryComp(args.Examined, out var forcomp)) + return; + + if (forcomp.Scent != string.Empty && component.Scent == forcomp.Scent) + args.PushMarkup(Loc.GetString("examined-scent"), -1); + } + + #region Utilities + public void TrackScent(EntityUid uid, EntityUid target) + { + if (!TryComp(uid, out var component) + || !TryComp(target, out var forcomp)) + return; + + if (forcomp.Scent != string.Empty) + { + component.Scent = forcomp.Scent; + _popupSystem.PopupEntity(Loc.GetString("tracking-scent", ("target", Identity.Name(target, EntityManager))), uid, uid); + } + else + _popupSystem.PopupEntity(Loc.GetString("no-scent"), uid, uid); + + Dirty(uid, component); + } + + public void StopTrackScent(EntityUid uid, ScentTrackerComponent component) + { + if (!HasComp(uid)) + return; + + component.Scent = string.Empty; + _popupSystem.PopupEntity(Loc.GetString("stopped-tracking-scent"), uid, uid); + + Dirty(uid, component); + } + + #endregion + } +} diff --git a/Content.Shared/Flash/FlashableComponent.cs b/Content.Shared/Flash/FlashableComponent.cs index 5f3f214b6bb..c3beb9b23fc 100644 --- a/Content.Shared/Flash/FlashableComponent.cs +++ b/Content.Shared/Flash/FlashableComponent.cs @@ -11,6 +11,17 @@ public sealed partial class FlashableComponent : Component public TimeSpan LastFlash; // + // Chance to get EyeDamage on flash + // + [DataField] + public float EyeDamageChance; + + // + // How many EyeDamage when flashed? (If EyeDamageChance check passed) + // + [DataField] + public int EyeDamage; + // How much to modify the duration of flashes against this entity. // [DataField] @@ -27,16 +38,16 @@ public sealed class FlashableComponentState : ComponentState { public float Duration { get; } public TimeSpan Time { get; } - - // - // How much to modify the duration of flashes against this entity. - // + public float EyeDamageChance { get; } + public int EyeDamage { get; } public float DurationMultiplier { get; } - public FlashableComponentState(float duration, TimeSpan time, float durationMultiplier) + public FlashableComponentState(float duration, TimeSpan time, float eyeDamageChance, int eyeDamage, float durationMultiplier) { Duration = duration; Time = time; + EyeDamageChance = eyeDamageChance; + EyeDamage = eyeDamage; DurationMultiplier = durationMultiplier; } } diff --git a/Content.Shared/Flash/SharedFlashSystem.cs b/Content.Shared/Flash/SharedFlashSystem.cs index c4345154892..2646ae5e695 100644 --- a/Content.Shared/Flash/SharedFlashSystem.cs +++ b/Content.Shared/Flash/SharedFlashSystem.cs @@ -13,7 +13,7 @@ public override void Initialize() private static void OnFlashableGetState(EntityUid uid, FlashableComponent component, ref ComponentGetState args) { - args.State = new FlashableComponentState(component.Duration, component.LastFlash, component.DurationMultiplier); + args.State = new FlashableComponentState(component.Duration, component.LastFlash, component.EyeDamageChance, component.EyeDamage, component.DurationMultiplier); } } } diff --git a/Content.Shared/Forensics/Events.cs b/Content.Shared/Forensics/Events.cs index 7300b78d76b..7f85c35ad02 100644 --- a/Content.Shared/Forensics/Events.cs +++ b/Content.Shared/Forensics/Events.cs @@ -11,7 +11,7 @@ public sealed partial class ForensicScannerDoAfterEvent : SimpleDoAfterEvent [Serializable, NetSerializable] public sealed partial class ForensicPadDoAfterEvent : DoAfterEvent { - [DataField("sample", required: true)] public string Sample = default!; + [DataField("sample", required: true)] public string Sample = default!; private ForensicPadDoAfterEvent() { @@ -25,6 +25,9 @@ public ForensicPadDoAfterEvent(string sample) public override DoAfterEvent Clone() => this; } +[Serializable, NetSerializable] +public sealed partial class ScentTrackerDoAfterEvent : SimpleDoAfterEvent { } + [Serializable, NetSerializable] public sealed partial class CleanForensicsDoAfterEvent : SimpleDoAfterEvent { diff --git a/Content.Server/Forensics/Components/ForensicsComponent.cs b/Content.Shared/Forensics/ForensicsComponent.cs similarity index 56% rename from Content.Server/Forensics/Components/ForensicsComponent.cs rename to Content.Shared/Forensics/ForensicsComponent.cs index e4579c5f3aa..8c5be03603e 100644 --- a/Content.Server/Forensics/Components/ForensicsComponent.cs +++ b/Content.Shared/Forensics/ForensicsComponent.cs @@ -1,18 +1,23 @@ -namespace Content.Server.Forensics +using Robust.Shared.GameStates; + +namespace Content.Shared.Forensics { - [RegisterComponent] + [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class ForensicsComponent : Component { - [DataField("fingerprints")] + [DataField, AutoNetworkedField] public HashSet Fingerprints = new(); - [DataField("fibers")] + [DataField, AutoNetworkedField] public HashSet Fibers = new(); - [DataField("dnas")] + [DataField, AutoNetworkedField] public HashSet DNAs = new(); - [DataField("residues")] + [DataField, AutoNetworkedField] + public string Scent = String.Empty; + + [DataField, AutoNetworkedField] public HashSet Residues = new(); /// @@ -27,5 +32,11 @@ public sealed partial class ForensicsComponent : Component /// [DataField("canDnaBeCleaned")] public bool CanDnaBeCleaned = true; + + /// + /// Moment in time next effect will be spawned + /// + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan TargetTime = TimeSpan.Zero; } } diff --git a/Content.Shared/Forensics/ScentTrackerComponent.cs b/Content.Shared/Forensics/ScentTrackerComponent.cs new file mode 100644 index 00000000000..789ec90adb2 --- /dev/null +++ b/Content.Shared/Forensics/ScentTrackerComponent.cs @@ -0,0 +1,20 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Forensics +{ + [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] + public sealed partial class ScentTrackerComponent : Component + { + /// + /// The currently tracked scent. + /// + [DataField, AutoNetworkedField] + public string Scent = String.Empty; + + /// + /// The time (in seconds) that it takes to sniff an entity. + /// + [DataField] + public float SniffDelay = 5.0f; + } +} diff --git a/Resources/Audio/Voice/Vulpkanin/attritbutions.yml b/Resources/Audio/Voice/Vulpkanin/attritbutions.yml new file mode 100644 index 00000000000..125f8a9b85b --- /dev/null +++ b/Resources/Audio/Voice/Vulpkanin/attritbutions.yml @@ -0,0 +1,4 @@ +- files: [vulpscream1, vulpscream2, vulpscream3, vulpscream4, vulpscream5] + copyright: 'inspectorj' + license: https://www.soundsnap.com/licence + source: https://www.soundsnap.com diff --git a/Resources/Audio/Voice/Vulpkanin/vulpscream1.ogg b/Resources/Audio/Voice/Vulpkanin/vulpscream1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..2f76639d13ddb8b7d3faaba07b83a9ea812acc6e GIT binary patch literal 10464 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 literal 0 HcmV?d00001 diff --git a/Resources/Audio/Voice/Vulpkanin/vulpscream2.ogg b/Resources/Audio/Voice/Vulpkanin/vulpscream2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..594e25f47e95ed5956deb8c98811c984686bed9a GIT binary patch literal 10250 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 literal 0 HcmV?d00001 diff --git a/Resources/Audio/Voice/Vulpkanin/vulpscream3.ogg b/Resources/Audio/Voice/Vulpkanin/vulpscream3.ogg new file mode 100644 index 0000000000000000000000000000000000000000..6d66c4a6e1f9407c8770ce73a60c9b0235cf0ac6 GIT binary patch literal 13946 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 L1Wy48AOHUWbQu4Q literal 0 HcmV?d00001 diff --git a/Resources/Audio/Voice/Vulpkanin/vulpscream4.ogg b/Resources/Audio/Voice/Vulpkanin/vulpscream4.ogg new file mode 100644 index 0000000000000000000000000000000000000000..594cc082bcff85c1e005fbb06ee0adb006c7ace0 GIT binary patch literal 14982 zcmaiabzD@<*Z6F~(%s>b5~7Q=3N9duAd*XWw@3&|cxgmXL|Q~ZkdTx{gjK)<1SLhv zAPp=)34gOZ-{fb`lvIpWVV4S)ztU8+f3IlFKYSQr_bI1y?#lA} zmG;XM<>}$`9{A_x?{db~El?fyxxhYoBD{$NUoYo>$mk%7nW2f5`a$ABc~Wb)QKz*203{7dpLM{1qGi8Jg-g#xjF^A?b65*RpsQ>#30BiFc>1JpY#t3 zaC3o(dIYJ^(9r$fL7q;b`(4iL5Al(vfoNu0Mh5CcCfM?D^AB`W*Yx-DbMg(+g@9u^ zrrIVajm%COo>o78CX66QICsXy$=B|gRUYX;iLELey{8~nQ z?*+96d_M7Monng-Jb23Hg+x%ANJ*hql8sdKU>X@v2@*BKIOCEv@gi{&>XzxTd(~kp zNe#lhs4!Noe}8n;JYlaUUMTK8QI#?Fqw0oWoQ|3$D}*f);#jm=^J1&iAhNiUu2C$F z+M;0GqkU4zF+Idq?l`QHR7%VT;?v<+2CbyL*po^d{Ba(dVch@75ZBaAi>1+g${TlF z6OMpJt(7zGg=RT_oQxWNPaHwfl?$W+P*^OLTr5S;%72d@JOzN2WX$>Gtl+b2g3sy& z8SqS2II6?pA)an>iSCsTy6NIp=@Ps5{H4l$FYfK$2Y1Qgq!<}9>YU}I-KBE{0AHw@ zTxywI>Y2QdbOj%mP=y8v09YtSQQP#$iHu_}&B$ZTev|*}w#jni+a-rKWPRo3UO|&Y z#PHGV&I23Y3;2)KbR*&g`FK(a?EFY3|o@b=hO01n_vr9?R6zjzaF-9 z+s>QZ(5J$JsH}E>mV1{3^Es%G2>3r7zqU_@B8X4+KVogYOdMk~8 zwctrO&gRU2a7lB0kx0iMo3FJzwCGuqaR@JwdDcX4?>`1d0}@^&p3_A4-yi2Bkp$kr z=h9_`F?uo;<;5unU+in>+xX6=KyAX)_*gw;nkK?~M>A%Pcpm|8xJNI?QGS=*s84NC zJcIRLHQ|JU0L~M;{&w=7xc)2g{#W}9e<&Jqs2g+YyjCO+aoHKG_!%p^y;ia_RkkCW z`&nf9*))etX1h(UN6!4O+m3cuMRouVrHe_Yi%O@zSG^*BlH~bR29Ri|5t;l>>dJf7 zbn%nv5?<*Z=d;Rl^OkZ8WGZ)204o)RdL`cpORfk@E)To1n3V3Bn^j(sC;R-)r}mna z|KH89>)_%rD~g{86hC1iu44ilyVgY*sn!+jmKWCv-1p*@;y*eLai~LsS_J=-H2yOI z05CqQ<9snBXuvKpVj@R2l^Ze988IdQ|1N{qiUu6eurNoXz@T+dUv>5s&Bdzhr&1+_ zW2e>TOUC-7V)7SQEBUALJ%WJ)Czr)_2GnGPN*}A8 zsJK0BtXF@>`mkPUvzgEPeE9fWs?=Klu289&Ph~wM0<`dtp=dCT3q|4tAezyHUOGO* zc|dw0&E&b-yr6TkT3No!fST0JjOS{5Z(e7YE`^WM3;7uXC+G98zd9)e{eyyne_B$C zt~!8qFPIGwG`Oy4z$szCp<~EtH^!kelBw9QsAOzLHsCZEF(X@X8<4Xk3=|9uILW3Q zI%F=gX_f)G$?c`0--H=?ikm#r>}InTX^|B&rC=~YeT2Os@X@Z>Zz}u0tjJ?#>Y95~_}3vJcA0K77H(GSZgx*b zLuS@by>2!b8wq($4w)GZ`IzfBxdF*S$XW3Y5N|Ag?!5mLPk}KxWGchX0h00fJE*+r z^gmMT=Q62ruU3rlL}%STyGiBtPJ^6~sYL#R9)|7>uA28?+cK>*OFq%iRbRe10Y3wY!5wNGg#amK<_ARU)x(!(3qrzXu8WTGWq z5pQC0nKw2~O;RH0w4PK^sga(3QQWAObbY*uwQu!Ep7mv=xL4LvrAlkT-t+ba=!MUPgbG+pnML@BSfOnqjCGwc|* z_HFCU36d)9P1p04D7CaXrPj@2>FDCKD5%%peoU%8gl12C~xAlZT^%teCa* zAS+WnI4WmZ=@Cmk?|R5eUw+ic9CBMZElcenztV0-?l2eqJ!n zIJfWF zk7GlMFtUVpAu#&v6WxWT#A)D?+kg-dBEtBD@Wjl2P{EFl&#a`N9}2T9OZ@z>xInVLaeC#kK{4EF!l zX8%*A{ht;NY#6G7jicj*()FsOA`w{>0+~{HOLGDl579|0rKr&qWn@50Ii<+sOG}2W z^)rK5^-fkajXPK6#~PXFRrm6{K%W}5uBso+I}H7n+owuxTu{$T?y+Uiz=QQP6Ce3e z>!7a>vPYe(losB`vOa3$bg5}un+^Xe-E8gCuf9QuGpZl44qBxalb7Y!-^Q-O0@F4{ zZ9zD0^&zbj0HLuMa4aTOp-TKF*A*Hbsxc>C1J7)W7fh; zxc&<(%}DtNkFGQ${XclHjySkb2x%eAL~oZCPi-yz7bZ=uY;{EI|cTp{w$0?&TwMJKd(^5k_|XmjnQ3kGbik zo0@&{9u*>Z`SJ=aJ?R8_?dOC$(x&tx@ghOVBIu%CbNybpu(M(T9-4qiG9qFCBQvW8 zt>#`*KqIVfwOkW)758BiX)^(vJQom`l=^@s#rNvG>BR-}&BpBia)?!nHHNk49iZ2x zJfu@O@-1QS+ga?*ViVfkofr`SxXXEhV`Uo>Jf85F=0xHXT3uKT!^;s+XaPk8ee9TG z;fw04h~kf*5E??mUA>h7_N2kYER8@4?B%I zP)29)25uDJZt&Md_=rlTlzYn`{BzUSZ>IX@?LJ#k+VRg(7a41YXfcbIZ?N(NdtPTe z;>!!{;}y->b5Dbe9sMEKo$|RRq&q_2(d+3`N0P!P*9C=NLSN-2R421;N8GoZP=)o=G+3=}T<&V0*dkj-l7iRiuE{J2v^>XZ+l^aqFO8^eU)=GXqO|KTFZ_BuX2#9HUf6Sd=@xK&aOtHQ zhp;Y6Ix0fzjneFm`(h`w6~1g0KI~R01ok6u$K50KmuV^bWA_xxuI18qd&GA7chX9^ zq036A+&6K_+Tk*E%}(6(-p2+nZlvhbSJMSoiN zY8052m4*9udyWE!k2~v&^dJnucAlGRHTaWuga`2%`RO^@=DV?vboG5`6KUr4=P%s%Y zpX~wYTR+Elf7Oo*bxuMOO!E%-e~^?t2QC;`;6pAX@RTzFqeCKCht| z#W`^xv*i8Z7?!E&i=I5Im&aZ+a*nV&2m5O!u;~y}eEu|LBnjuc&oW9KlkEA>f(R_V zc2H<>AcMYXU1sIxOjAWL_C`fce!Dw!Gl8c9fT;#C5OZD#P~^w8&u@268_-Q`tVP7w zrAUgMymP?v#orz$DVt@NG4t~$I@o4oL~jiXhkUVG?*^t75?XzI^kIUv;_))MmH`72Xc$2hj^maqedX=?5l->@Zu zPTc{&x8&xt;BrlnU%Kogl?dkJOTQg5StoJUfUsJxbMBQg_3n&n}*Wa%82e+OQkWw;gJ;1b_e%dbYXZg2;#Z>dw6C_LZCP`@t z6-7O~(9_(s(NY%cin!s{OPUIa+n0uwbJ1PrP@6&U1 zfBl)=OxMu_Z%a(Pth9n$b9V0yeB}rE^oHW%zDLF8zlQlQtxt0iA|(njJ5ZGmGG)GC z)ZSx{Tc_xqgfV(h#|H|a<;;tc3$DxE;@dGXa@? z{7BS@$DZ`W?>DKFqYDbJKje$n3`%=E&LEe3g$+di#r694M`i1ty54X&IWT;a-6*Mw zP_QsE_Lr%dMbiAkIdipP>$^EW%gn-ffnRF1aoE=EQGVN^U#Dlcid%7fcAAK9MY z->GLC1za?%1dhQ^{MBx@EZ<8fIzH?1FnvF*|Aa`#+{SS3XhN~`iSeb{!~Ju0#l`H? zy3L7u?!}?YU%WEXUapThlkig0!op$)*t(&yzG*0C&HxdR=Y1jZSB&>@PR{Da!FOis zQ_+X+C^`lXYd_xpY)TZn1X#iFolLhQ^~=#UkfyD=S~y9$99_ssPsE zpu27Ae`ODhyU^( zsjH)h@jAXLDu6TMxhcZ`LxmbfKd^wt6OfR@*cgVoJN&KQQ}fJ)#^Q_>GD#eGsj>Il zr(aHqyP8T)>s78h$f4>arA@Z3K0eDCakV0Ib)%{)_W4{atER260YloG!kQU2{^p@v zmIA4PGhvyRG37t`wCQW9erJXT)@fJ?TUr2M9=(ef|4Q+z6fJiy=GDzT4yI6X1&M1=Y!pW0~NZiqkS~u1BvZ@tLhs=M;#6`pL&;Oh;o%gihevr zOS+;uRR>tQou&MNcIB!c|zM7|$n(W3~GwKH`6aMu1Gx>O$#A^YljsFMH zNiI^cc8ch4z52?zkizDRR(=#KfXu0I^Mbi5w{2XKWY}upP_k(_fkn8FvibeF9%Fel z`&R*>;>s-y$aSgboB~AFu(eNcdONq3;S^*G^Fngd8DDZudx9w@geHNWf(#9>FY1@?b4 z32TcZL-|P0NYepLciMhIQnm)e^R%-dikDd>@R|TU z;T4;620Vt3fR1n!V;KMrkubWRC~(*p8*qzqnVtBK)>2B00OVC?xmbITmNHyvH_fRu z%Y6spTCYVo$z@{&@12i5NwoJfJTnadkwOwvzD7qA^|?*?p$m%8COc&G3?CfDJHTw` zdLI~V4oWv4eo|UKvTBV2{+WPD8K}p4*f@ei>~FCYHnWX=J0$EOr`U5Kr9rXUCZ4{K z?rDKWYqnICrpxl+dRhGCGya((&v(2O#9Y(oev^MH1Rc1KQ&UI1bvn%+g&$zD``8Yp zjNa55IGb#c@RA;^z6VgNd^93HH^R+JoTm+F!3Q`Mp6C|C6DNEg`i2;5J1v_VgDaDU zc|80VbSZiEmVj<$`{V3y6pMa9@0Sq(GFczjeD*t~Gx6=5QoPrc+M~!pV2>YQwsoVU zHQF5FbE#D9_P~Ls^a#x)s<6ng9w4HKKjO}h(-ev%RTomE&tO>p=%4^S$ggR{{ncY3 zQDoZ-w?nIMiHl9U0-Bh%M<>vu{;MQ{0{a|~^nJWxBjeBDG_4{(N>=05~KyJEP;^eR|R-{h~wk@x-~$r&&-jh*Pm(dH5lc>TQD(G?-RxepFq> zioANV=>Pf8*7J}33AGr3om!d=a}?{WI4eyZB|T>d5FY{(_8~|LGU#M561fa?wO6!s zOwnoTs>{Z9s5#O_qN@c1NH%9KvY-PQ={NE;R$txs37C~Iz5IE$!Cb`S=DYjmV8?R) zlTJbanERoaIyf&R(%>5g_xN3RG2*IpRkY(+twI%MMhe}a15lKRo*l%YA}Xw;B+$U; zc?lr(oV{wVhY-Hqy98Y2br&U0oS-FqS@~gr2lSZpY`$}6T~{=O&s>%sH+Urrgsl>m z#k;vko7?_*^`F&bDqN{)7D~dZ(gmOxJTEax0BaJ!n;}MEn;(cu|4evKk2r9WzMv>a zru0zx#puF=rJTrw5j=PdCMdS8MAd--TCFap)ZSM&b$I`2zYkK_^nnAVlt z(8;5jWtw3sZ92>qq#Pl%*bzmyRRaJs0tx`$_XviB2a&)`4(P5V0b4^xoUu?&%-_@C zdA2Oz+6yKVabTMZ7|AkI#_>RWwF#w1V||{ta}M7r!bm#K&U>|cFwJbXmhaFh&?zO^ zYL#~yVTlq5^8F#x>qIRoR^dFyUIQXHCPLnRg{NQoq1z-ma za-dk6WzpM*W@)E0ZS*8gC`AaR{cu3G;VZ(%2%5&;v#@%v!4~3Z5I$Bw2ICjKQ8|fh zz%i+CBh>?Cukxx8k%M9!(da?|w$0!!)a-#Y5cR!r0@$4u@LlJ}0mls)avbgws&yL; z2&e)n8qcif=q-VQ&)$=Vm2|`eI`5#Cr}??TtT+iBA_06;=s_bz9Z66`aGI0b&7 z0MU+t^4^FvYe8S8fLgsqPtv3X-m(Cm89N^WLZzahswrw8$miDtpnz}M1&sj0=Xr(% zKJ5zHxC_%#kHgYM_EOG-H;*=}-D00y&7=8wMb;4otTi$~KnE7gqA1Z=U<>$P0e*n2 z%m}=r@Bq@0yXYt#GVqoIf+VCE13*~PT?}A`Mxz>57!`Ia79gjud^5`cROj^oX)j3R1PBwt zJ&Q(AMs6Y7hXTe*F-ZXrxC&{c%EW}ya(PjM3G}3w$KeSAg$qjlu}#(0iw6MXe9I{` za4D&D2jIE@DB#U%)m7n`z16?;Dt_wsY4`3GaDm1l6HxpBh_c0jEA8xHkdE>Y4UPb7 zBna>#+ArU6x6V`oDe^l?77ZGan*GWN3c>6N6c$hpFQnrI_lP4G*|~90-AG&1_aO}Lug-60+7Rs*U?Q4 zxcnqeW-=LuE4^(3AOK1RKw>dQ2c<};0NPck-~PWvC~yJ&HZK)MX5k7?Y%~fyJ&FT6 zV>suGbbiXw8>4p_Zgg(UkFOr044{hN=z#zoG>}1q(|b_BmkH?}g|i1}g#ls@?KvjE z{x{IEiUuTsFi8Y6h{}ErPMd<(5PAfF4eI-R8BzGdY6n%$u+&0HNFR2=Yj44ZvndQAA>|0O>+Yf0LvS7TCl)}f^I_WRtJ)W7{FWTQJyElhU$L|9tbL- z!@|*pIwG?vFzbSmL>z)f-du)~j6~qM9(aS}1RK6=Pq&AwG5Ht}725Pn8~J&DJ5<*$ zD{Zl8z0>bh!UF2gk%!0VK*SlC^O%704{6Y6Bndd+p)1W`Jf(>#XG{h;mq%ZBA9D;K z&gUT8G$+7H4^B_Q1Owc)Zx$QfyHyO`lJKz{cy8|p=$$9zIg#7KNSF5Vh294j|=Lt0=IZUd4Od&veor2Q}7L!TC2{J1JZzKHx)Zr6BMv>wj0-Ek1f0IEa-3lNQ-z4HYC zDT-a*J`~9QC|;7GSy-}?aw)m23=^d ziUE#?MS-Ik0m=ZMnrVs8i;OtIRz7{01t87P!P!ZXkeP+60F7Y`I|@wWIp9hElSSwm zfQ3aIfTxvK4E!k3&X)eVYLXmoIPvs{tmHnvdE4+H~fkE~ys(HPJ~1|$^Nt7CmhYP#gWvClNfOrRV*3H_TNEP(=@ z-9L`jqWD2US%1=Hk{o(trnJ%iEVP}wUs#hV3KVbw(qDND@>vB0aKj9QpqgDNQ#vRL z0l?Mn1&RQe1IN5o%e7DeYh-Dd_MsvGcpF``O=%UoLG?P-D?;C&OJJTJwMb^f0UV5| zepVZ=&$x}5@_L4yt?2pT)kDbX#W8@KfeOLA*>DL9sE01_sHA|Ys!vJpHl^GdlNibG7R#ZJ{Qxhgopd?Eh)*Znvl6qGb{mn4hb z5VpQAd*s`T--G>dD+3NYUZeqA3}Dra7D)P|fiF8?1m%RJ;YoCU~A00qn|%>g5^+DBGaJs?Z4pfWb^*3v+J%G zl#j5GP}{H`5k-O57;vfs4g5La_I6g0IuQVHx4Z=6MSv+u7AaI^1z=Hn)(9+qR{?lV zFvTDUKMR4g1F{)sD~Zwc6){ru2o~&^_j6cyoyBZ1R!{LyzP+{HO@YhgPn4Pgpuk9d zf(690G;s3-c!A?}NWC0P$)OSVFsFYdgPNrgEDi+(FZ36CG+1+wk6{Pp5CwQZOM#6M zbnu`$aWAMg%%SAtFTs;G^7J5S$vSx zLi+FXqKMne8D`qxr8G$m1ax(wghc_7g8@1UmWBBXAkhXqzXG$=ySJwtp@SQ~HA@re zgTd+XnTcC*a5~0Rmvc2Y?AZCD(e2O{QGc zQa!yMcQV~IgH)nv)R1+ zTU}P2uantv@0aS{J}A<)ek@SVh2{mo z_9(rPJ!#2~oy34*{iXxIW;)ggPM|20{I;kYO0m@`-YC`)UUt`XIYQa*nM9(vA2Ayn z5kG}a|C0mksq4-02jFkR>(a~N3l{}WD0L_!d*`}XKpYNqi=!NK0VS3W1fl@pw2in? z`|X&RLCTa32gw*Up2{v|bmHb^R+OG*49p8icFwmBoGXD8!}5^p+@mVBi=8w(=0c1G z=#}G?E>(f-`Or@?w8{~303Y$-s`qPvsLbvR1-{8(&BA~3&?s`^)T&JfzRTrmgdu#v<6~?vUu8w zXXP}~c+w-I7KQD+o%-%1HI{&zV*5~{0wSk==ZX-;H`jS7hokSaQ|4TwtW}HFB*cF? z)Px%gSem~Kjt{*1cc5WX5}@qY%v4lAhBFMlG`SFBfJqZ(bP(XqDdSf6lmir1x$=E} zUIw5qA2VxMhU~fIYUI!^v^RxdQ++b;e$d7p!&}!C^zT2icU8JB#dxMx;4S;HANsDW z9c2gN&cD-vFTDEvU1iq`z*_0HSjkOd$DLW;L3OXx_B(j-d99HH7aiXAI=>;a^!c-s z7Jk1XD3t7J3hc5cQic^DhuJ@Id=jfmc(UReH(D}UH=!rKp}YS0SL@H~U}IvbK2d@3CY|i4Fd<{F|$A z5S>!OLt`3#O`l|w^Xcpqc?r|<X9;Oq|U)RfkodbA(4zxG^l6w31*RK|p@5MyMc1OD za{blND{HNzOU;jhO$Zl>x95ob7%U|+>P9=xK0Xd(H>!c^II4Gle+gyP3IVd_G-6_P z)|V?S9l|BN*>BaZ4IH@YF^ZIO@%mp#NV;?5P0W z!`oXVE28aTdd8-C26Cp~bxNP_2cj110MDo9>m4NP1`UnI5RTSvGw#3(dbtX}FHN$> z?paisJ$mfrpcF1DK5kj+t|9nr;hi1(L!jFuAwhHeQ*x5ghvl-1=d2yrH9UJF9zSf2 z@s^`_iju@fBVx${Vt4lS`SCMNn~8uV%E_1GH(EFsLxUYx9yjgNW;;R%VSuAPcYWdz zvRyAr%f)!>&N)#+%FbBb&XE(hP6(`j7H%BAo8j}>k^LNfAD5bd?Kpj(%+j5FvvC%i zPs}zoefs39f6SL_+=7Oux@!W{eQm5wACba2V6409WePJ;e(#eIx3J^aP!JzvbP^Il zpOc^Bi_R&iFijQgDf0@F7MBuF(>X`ZO-GMoI1V7Z7kRn=`&F#mO=eAazXazKsII8*=ZtsU#U(n@9JQ zHTYIPdQKyk@#wmhOK}|S!+qwcY6>e<|5W9*AvEQ;x;g!_%f>zehRNl%nn*^K)o1ZG z{VnbtM;-R2nZ^PAaKoOEixOzO!AnMl)Kg98Q|BwB!cOR336~6R!5(B{&6AFPx7Ktz z-lS1`ED2R-2ImWME)t?_Z8ax2$|*&(A9#XqFm^drQQOsY`iRA7jqD^_(#79z0+nyK zD%Aq)^GUmV(~a+vN?tB`@OS1bDZamTNnS&7^1h@{m)m6H!98l50^cM!qdlcSRD4zC zH8K-r!>^@hc8i-&LqU>g;3qc@AIZqX+x*8N=HAYkWMm7 zhOJfT-HR|>U=Cc+sF=E8q#^oM_hP}=XF9NbJNUh}(_0amid+U7 z@wR6B><%GolMNv#~exsK*n5BO47*oW(}*`q)WGlcHbM(Ivo+-MO9h$ zvX@zzt;N%d0CVVHk@tDkF_ss;xbaX>_yq6K*L*|bf4|+FW~%8vaUKq~<46AR5RmFB z;41zwvZ^L{(g&cBDlx1C*2jE#y0T8c?G*^vT2>;H3lE%HLOsU5HOVZ%i~9~QW=b#y z`h}|UKTL|nMReW^H+goYl4+BFrny9At%w^VrF8)X2mYgSn1NySpLJ$HDuRO2)?y=8lOL>78S#J7&0u3*1;o))M2VP43e;Pil(ZK%f(ehZs9 zcRi(vQJNE6RGJ)L>*Q|l<9YM_nE3;au`e9$uWdtbb@WC~ca-!f93vVxRQFHz{Cxgt z@y8^`&oOA0EhBQpGju*NOG+aiGG=%rIXq~8E$vlZVqx|0-2JJPLiV2x^EdsqqFEcb z+XEl%t&b9Ydsx$m$J9>r?D>46iA-dl#EpQud!64c6=aWuCI?)T)ji6EW~cI=_p8uG zw`zJC45`<+5hL7zP}-eyTFc8q?6xN5?EcPa56-7{ZC*Rq)me76piDVK9Ch%G12V>67F;)c z@r&`P^~#QKJ1hevO!n*FN^?JD(sm?GBqjPe@utY%_t7cSO}GSQ<*tq!H81a#FvYu5 zh^3iVb2%@w8SAN;4Bwh?-2bg4mlcQLpyFoxDg-cvTj%sL&K-ed%Lgkw(XLZYJ~RiNewThbn(ninRv>P{*()B zS_QA((M&Zl2(4`>6V7U`v*dlHLp-)ssy>OAb^dONcbsKsfowmJy-tF#9dC)}QSRMk zFYqy_iP4B}FLEPABzp|``8CpoE>J{EFrGuGwi%Cnm4I2>U!xb|;xmsa&6;Gq|vgOFvRQI{OvB)!ra!h{} zoT+yy6BJ7N(@-Ebn&UdZ7uFJ8GUA2W9)Iqr@%9%ooGBaA2cwhbygWBrdwHzxKh6%S)OafkGjA zMG-4|QUzH)?&{lMavZ!JYj8ITXL^|sn*|*2rGHFDWyco1NfJ2Llh7K{sMdout4t!> zrj=!MiHA2ctI7|llwtH6BKNR%&WYXlfrc~j{vi7a@agLP<3^YMgKYnCDl7uFS$x?IP^tuVuAGy{%D*tZu9!fhT_;Bh=?k=N_54b}88lOF(LhtzsFv&R37obKwl6ZoEon>U~F4wv# z-UM2=xv!L646nNRZKsXNK0}~%;rOQD{JG1`;Xh7KLd^tzpeff@9zSWgL*8V3Nh9|J zP#Pyz8t@O|Ueaqzf(hD(qjNU2<9i0qe&jR3Sjw4qhg%#uT2OTFf%ew8bjBB|ktYMu zX$*W4ezA8YWzpq+2nR7C-NVKka~QEomMlm0lE zX~y?E_mI3ww6EQ|$W>Ar7BUF`fJNHu_h_s@`jc{TcuID5+n2jM3hy4N1udfL8o(9h z3wDZ~$joo7_k$XScD1GKn!_wq$qQH{*Z$}?E5rBv1El-pw6NuGHbNxSvgP)!N literal 0 HcmV?d00001 diff --git a/Resources/Audio/Voice/Vulpkanin/vulpscream5.ogg b/Resources/Audio/Voice/Vulpkanin/vulpscream5.ogg new file mode 100644 index 0000000000000000000000000000000000000000..fc755173b33f3923352bee3f68745219bb91ad8d GIT binary patch literal 11328 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 CzBnNO literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/forensics/scent.ftl b/Resources/Locale/en-US/forensics/scent.ftl new file mode 100644 index 00000000000..083237f7f73 --- /dev/null +++ b/Resources/Locale/en-US/forensics/scent.ftl @@ -0,0 +1,10 @@ +track-scent = Track scent +stop-track-scent = Stop tracking scent + +start-tracking-scent = {CAPITALIZE($user)} start tracking the scent of the {CAPITALIZE($target)} +stopped-tracking-scent = You stopped tracking the scent + +tracking-scent = You are now tracking the {CAPITALIZE($target)} scent +no-scent = There no scent to track + +examined-scent = [color=#ffff00]Has the scent you're tracking.[/color] diff --git a/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml index 909aba6632e..07152d74ef0 100644 --- a/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Entities/Mobs/Species/vulpkanin.yml @@ -98,6 +98,11 @@ Female: FemaleVulpkanin Unsexed: MaleVulpkanin - type: DogVision + - type: ScentTracker + - type: Flashable + eyeDamageChance: 0.3 + eyeDamage: 1 + durationMultiplier: 1.5 - type: Wagging - type: LanguageKnowledge speaks: @@ -111,8 +116,6 @@ drinkDelayMultiplier: 0.5 - type: Flammable fireStackIncreaseMultiplier: 1.25 - - type: Flashable - durationMultiplier: 1.5 - type: entity save: false diff --git a/Resources/Prototypes/DeltaV/SoundCollections/vulpkanin.yml b/Resources/Prototypes/DeltaV/SoundCollections/vulpkanin.yml index 63458928cc8..2a8e17ebc45 100644 --- a/Resources/Prototypes/DeltaV/SoundCollections/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/SoundCollections/vulpkanin.yml @@ -31,3 +31,12 @@ id: VulpkaninHowls files: - /Audio/DeltaV/Voice/Vulpkanin/howl.ogg + +- type: soundCollection + id: VulpkaninScreams + files: + - /Audio/Voice/Vulpkanin/vulpscream1.ogg + - /Audio/Voice/Vulpkanin/vulpscream2.ogg + - /Audio/Voice/Vulpkanin/vulpscream3.ogg + - /Audio/Voice/Vulpkanin/vulpscream4.ogg + - /Audio/Voice/Vulpkanin/vulpscream5.ogg diff --git a/Resources/Prototypes/DeltaV/Voice/speech_emote_sounds.yml b/Resources/Prototypes/DeltaV/Voice/speech_emote_sounds.yml index 011de6a7c52..119134dcf18 100644 --- a/Resources/Prototypes/DeltaV/Voice/speech_emote_sounds.yml +++ b/Resources/Prototypes/DeltaV/Voice/speech_emote_sounds.yml @@ -67,7 +67,7 @@ variation: 0.125 sounds: Scream: - collection: MaleScreams + collection: VulpkaninScreams Laugh: collection: MaleLaugh Sneeze: @@ -105,7 +105,7 @@ variation: 0.125 sounds: Scream: - collection: FemaleScreams + collection: VulpkaninScreams Laugh: collection: FemaleLaugh Sneeze: diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 9fb241c40d7..d812433b44a 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -178,6 +178,7 @@ - type: StandingState - type: Fingerprint - type: Dna + - type: Scent - type: MindContainer showExamineInfo: true - type: CanHostGuardian diff --git a/Resources/Prototypes/Entities/Objects/Specific/Forensics/forensics.yml b/Resources/Prototypes/Entities/Objects/Specific/Forensics/forensics.yml index 7450d7845e8..9b3be6d7780 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Forensics/forensics.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Forensics/forensics.yml @@ -18,3 +18,22 @@ - type: GuideHelp guides: - Forensics + +- type: entity + id: ScentTrackEffect + noSpawn: true + components: + - type: TimedDespawn + lifetime: 1 + - type: Sprite + noRot: true + drawdepth: Effects + sprite: Effects/chemsmoke.rsi + state: chemsmoke + scale: "0.08, 0.08" + color: "#ffff00" + - type: EffectVisuals + - type: Tag + tags: + - HideContextMenu + - type: AnimationPlayer \ No newline at end of file From f93b8dc6d0f6c0b9e9852e3c3464eadfa05ed109 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Thu, 15 Aug 2024 07:11:30 +0000 Subject: [PATCH 111/135] Automatic Changelog Update (#715) --- Resources/Changelog/Changelog.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0d1db3042f8..67514002bd3 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -5358,3 +5358,17 @@ Entries: message: Xenowears! new non-human related clothings. id: 6266 time: '2024-08-15T06:24:07.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Add + message: >- + Forensics Scent Type and Vulpkanins can now track scents, better keep + yourself clean! + - type: Tweak + message: >- + Vulpkanins eyes are sensetive, please dont flash them with lights as + this could damage them. + - type: Add + message: Vulpkanins now has their own screams! + id: 6267 + time: '2024-08-15T07:11:05.0000000+00:00' From 9d5dfbdffbbabf4b16b4ca079a455eb4100733f1 Mon Sep 17 00:00:00 2001 From: ShatteredSwords <135023515+ShatteredSwords@users.noreply.github.com> Date: Thu, 15 Aug 2024 05:59:11 -0400 Subject: [PATCH 112/135] Commit all files without any conflicts --- .../Cartridges/CrimeAssistUi.cs | 9 + .../Cartridges/CrimeAssistUiFragment.xaml.cs | 3 + .../Cartridges/SecWatchEntryControl.xaml | 19 -- .../Cartridges/SecWatchEntryControl.xaml.cs | 21 -- .../CartridgeLoader/Cartridges/SecWatchUi.cs | 27 --- .../Cartridges/SecWatchUiFragment.xaml | 13 -- .../Cartridges/SecWatchUiFragment.xaml.cs | 25 --- .../Cartridges}/GlimmerMonitorUi.cs | 3 +- .../Cartridges}/GlimmerMonitorUiFragment.xaml | 3 +- .../GlimmerMonitorUiFragment.xaml.cs | 20 +- .../Chat}/PsionicChatUpdateSystem.cs | 4 +- .../Glimmer/GlimmerReactiveVisuals.cs | 0 .../Psionics/UI}/AcceptPsionicsEUI.cs | 0 .../Psionics/UI}/AcceptPsionicsWindow.cs | 0 .../UserInterface/GlimmerGraph.cs | 2 +- .../UI/HumanoidProfileEditor.xaml.cs | 2 +- .../Systems/Chat/ChatUIController.cs | 9 +- .../Abilities/Mime/MimePowersComponent.cs | 12 -- .../Abilities/Mime/MimePowersSystem.cs | 38 +--- .../Components/IgniteOnCollideComponent.cs | 4 +- .../Cartridges/SecWatchCartridgeComponent.cs | 23 --- .../Cartridges/SecWatchCartridgeSystem.cs | 73 ------- .../CrimeAssistCartridgeComponent.cs | 5 + .../CrimeAssistCartridgeSystem.cs | 16 ++ .../Events/GlimmerMobSpawnRule.cs | 2 +- .../Psionics/Abilities/DispelPowerSystem.cs | 36 ++-- .../Abilities/MetapsionicPowerSystem.cs | 74 +++++++ .../Psionics/Abilities/MindSwapPowerSystem.cs | 63 ++---- .../Abilities/MindSwappedComponent.cs | 5 +- .../Abilities/NoosphericZapPowerSystem.cs | 42 ++-- .../PsionicInvisibilityPowerSystem.cs | 118 ++++------- .../PsionicRegenerationPowerSystem.cs | 113 ++++------- .../Abilities/PyrokinesisPowerSystem.cs | 66 +++++++ .../Abilities/TelegnosisPowerSystem.cs | 67 +++++++ .../Psionics/PsionicAbilitiesSystem.cs | 143 ++++++++++++++ .../Audio/GlimmerSoundComponent.cs | 6 +- .../Chat/NyanoChatSystem.cs} | 28 +-- .../Chat}/TelepathicRepeaterComponent.cs | 2 +- .../Chemistry/Effects/ChemRemovePsionic.cs | 2 +- .../ChangeGlimmerReactionEffect.cs | 2 +- .../BecomePsionicConditionComponent.cs | 11 ++ .../Systems/BecomePsionicConditionSystem.cs | 32 +++ .../Systems/RaiseGlimmerConditionSystem.cs | 5 +- .../Psionics/AcceptPsionicsEui.cs | 2 +- .../Psionics/AntiPsychicWeaponComponent.cs | 0 .../Psionics/Dreams/DreamSystem.cs | 3 + .../Psionics/Glimmer/GlimmerCommands.cs | 4 +- .../Psionics/Glimmer/GlimmerReactiveSystem.cs | 23 ++- .../Glimmer/PassiveGlimmerReductionSystem.cs | 80 ++++++++ .../Structures/GlimmerSourceComponent.cs | 0 .../Structures/GlimmerStructuresSystem.cs | 22 +-- .../Invisibility/PsionicInvisibilitySystem.cs | 26 +-- .../PsionicInvisibleContactsComponent.cs | 3 +- .../PsionicInvisibleContactsSystem.cs | 4 +- .../PsionicallyInvisibleComponent.cs | 2 +- .../Psionics/PotentialPsionicComponent.cs | 14 ++ .../PsionicAwaitingPlayerComponent.cs | 0 .../Psionics/PsionicBonusChanceComponent.cs | 0 .../Psionics/PsionicsCommands.cs | 7 +- .../Psionics/PsionicsSystem.cs | 28 +-- .../SophicScribe/SophicScribeSystem.cs | 10 +- .../StationEvents/Events/FreeProberRule.cs | 2 +- .../Events/GlimmerEventSystem.cs | 2 +- .../Events/GlimmerWispSpawnRule.cs | 2 +- .../StationEvents/Events/MassMindSwapRule.cs | 5 +- .../StationEvents/Events/NoosphericFryRule.cs | 6 +- .../Events/NoosphericStormRule.cs | 8 +- .../StationEvents/Events/NoosphericZapRule.cs | 20 +- .../Events/PsionicCatGotYourTongueRule.cs | 2 +- .../Abilities/MetapsionicPowerSystem.cs | 174 ----------------- .../Abilities/PsionicAbilitiesSystem.cs | 111 ----------- .../Abilities/PyrokinesisPowerSystem.cs | 157 --------------- .../RegenerativeStasisPowerSystem.cs | 72 ------- .../Abilities/TelegnosisPowerSystem.cs | 104 ---------- .../Glimmer/PassiveGlimmerReductionSystem.cs | 57 ------ .../Psionics/PotentialPsionicComponent.cs | 21 -- .../Psionics/Telepathy/TSayCommand.cs | 45 ----- .../EntitySystems/EventHorizonSystem.cs | 4 +- .../StationEvents/EventManagerSystem.cs | 4 +- .../Systems/ArtifactAnalyzerSystem.cs | 4 +- .../Zombies/ZombieSystem.Transform.cs | 4 +- Content.Shared/CCVar/CCVars.cs | 8 +- .../Clothing/EntitySystems/ClothingSystem.cs | 5 - .../EntitySystems/ToggleableClothingSystem.cs | 2 +- .../Cartridges/CrimeAssistUiState.cs | 18 ++ .../Cartridges/SecWatchUiState.cs | 24 --- .../Inventory/InventorySystem.Equip.cs | 2 +- .../Inventory/InventoryTemplatePrototype.cs | 2 +- .../Abilities/AcceptPsionicsEuiMessage.cs | 0 .../Dispel/DamageOnDispelComponent.cs | 4 +- .../Abilities/Dispel/DispelPowerComponent.cs | 8 +- .../Abilities/Dispel/DispellableComponent.cs | 2 +- .../MassSleep/MassSleepPowerComponent.cs | 18 ++ .../MassSleep/MassSleepPowerSystem.cs | 59 ++++++ .../Metapsionics/MetapsionicPowerComponent.cs | 21 ++ .../MindSwap/MindSwapPowerComponent.cs | 5 +- .../NoosphericZapPowerComponent.cs | 5 +- .../PsionicInvisibilityPowerComponent.cs | 8 +- .../PsionicInvisibilityUsedComponent.cs | 10 +- .../PsionicRegenerationPowerComponent.cs | 10 +- .../Pyrokinesis/PyrokinesisPowerComponent.cs | 18 ++ .../Telegnosis/TelegnosisPowerComponent.cs | 10 +- .../TelegnosticProjectionComponent.cs | 6 + .../ClothingGrantPsionicPowerComponent.cs | 2 +- .../Psionics/Items/HeadCageComponent.cs | 2 +- .../Psionics/Items/HeadCagedComponent.cs | 2 +- .../Psionics/Items/PsionicItemsSystem.cs | 2 +- .../Psionics/Items/TinfoilHatComponent.cs | 2 +- .../Abilities/Psionics/PsionicComponent.cs | 20 ++ .../Psionics/PsionicInsulationComponent.cs | 2 +- .../Psionics/PsionicsDisabledComponent.cs | 2 +- .../Psionics/SharedPsionicAbilitiesSystem.cs | 16 +- .../Events/MassSleepPowerActionEvent.cs | 2 + .../Events/MetapsionicPowerActionEvent.cs | 3 +- .../Events/PyrokinesisPowerActionEvent.cs | 5 +- .../RegenerativeStasisPowerActionEvent.cs | 2 - Content.Shared/Nyanotrasen/Psionics/Events.cs | 28 +++ .../Psionics/Glimmer/GlimmerSystem.cs | 65 +++++++ .../Glimmer/SharedGlimmerReactiveComponent.cs | 0 .../Glimmer/SharedGlimmerReactiveVisuals.cs | 0 .../Metapsionics/MetapsionicPowerComponent.cs | 38 ---- .../Pyrokinesis/PyrokinesisPowerComponent.cs | 45 ----- .../PyrokinesisPrechargeComponent.cs | 0 .../RegenerativeStasisPowerComponent.cs | 19 -- .../TelegnosticProjectionComponent.cs | 8 - Content.Shared/Psionics/Events.cs | 82 -------- .../Psionics/Glimmer/GlimmerSystem.cs | 183 ------------------ Content.Shared/Psionics/PsionicComponent.cs | 41 ---- .../Psionics/SharedPsionicSystem.Insulated.cs | 4 - .../Weapons/Ranged/Systems/SharedGunSystem.cs | 2 +- .../Audio/Nyanotrasen/heartbeat_fast.ogg | Bin 39983 -> 0 bytes .../deltav/cartridge-loader/secwatch.ftl | 5 - .../en-US/nyanotrasen/abilities/psionic.ftl | 24 ++- .../nyanotrasen/psionics/psychic-feedback.ftl | 53 ----- Resources/Locale/en-US/traits/categories.ftl | 1 - .../DeltaV/Body/Prototypes/harpy.yml | 5 +- .../DeltaV/Body/Prototypes/vulpkanin.yml | 6 +- .../DeltaV/Entities/Mobs/NPCs/familiars.yml | 7 +- .../Entities/Mobs/NPCs/glimmer_creatures.yml | 4 - .../DeltaV/Entities/Mobs/Player/vulpkanin.yml | 1 + .../Entities/Objects/Devices/cartridges.yml | 22 +-- .../DeltaV/Entities/Objects/Devices/pda.yml | 3 +- .../Entities/Mobs/NPCs/elemental.yml | 23 --- .../Prototypes/Entities/Mobs/NPCs/flesh.yml | 5 - .../Entities/Mobs/Player/arachnid.yml | 1 + .../Prototypes/Entities/Mobs/Player/diona.yml | 1 + .../Prototypes/Entities/Mobs/Player/dwarf.yml | 2 + .../Prototypes/Entities/Mobs/Player/harpy.yml | 1 + .../Prototypes/Entities/Mobs/Player/human.yml | 2 + .../Prototypes/Entities/Mobs/Player/moth.yml | 2 + .../Entities/Mobs/Player/reptilian.yml | 2 + .../Prototypes/Entities/Mobs/Player/slime.yml | 2 + .../Entities/Objects/Devices/pda.yml | 24 +-- .../Ammunition/Cartridges/base_cartridge.yml | 9 +- .../Structures/Specific/Anomaly/anomalies.yml | 62 +----- Resources/Prototypes/Guidebook/psionics.yml | 9 - .../Prototypes/Nyanotrasen/Actions/types.yml | 50 ++--- .../Entities/Body/Prototypes/felinid.yml | 4 +- .../Entities/Clothing/Head/hats.yml | 3 - .../Nyanotrasen/Entities/Mobs/Player/Oni.yml | 1 + .../Entities/Mobs/Player/felinid.yml | 2 + .../Entities/Objects/Devices/pda.yml | 3 +- .../Machines/metempsychoticMachine.yml | 3 - .../Structures/Research/glimmer_prober.yml | 10 - .../Structures/Research/sophicscribe.yml | 2 - .../Nyanotrasen/GameRules/events.yml | 2 +- .../Nyanotrasen/Guidebook/epistemics.yml | 10 + .../Nyanotrasen/Objectives/traitor.yml | 23 +++ .../Prototypes/Nyanotrasen/psionicPowers.yml | 6 +- .../Prototypes/Objectives/objectiveGroups.yml | 1 + .../Prototypes/Roles/Jobs/Civilian/mime.yml | 1 - .../Roles/Jobs/Science/research_director.yml | 22 +-- Resources/Prototypes/Traits/categories.yml | 3 - Resources/Prototypes/Traits/psionics.yml | 39 ---- Resources/ServerInfo/Guidebook/Psionics.xml | 108 ----------- .../Guidebook/Epistemics/Psionics.xml | 73 +++++++ 176 files changed, 1281 insertions(+), 2363 deletions(-) delete mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml delete mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs delete mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs delete mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml delete mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs rename Content.Client/{Psionics/GlimmerMonitor => Nyanotrasen/CartridgeLoader/Cartridges}/GlimmerMonitorUi.cs (92%) rename Content.Client/{Psionics/GlimmerMonitor => Nyanotrasen/CartridgeLoader/Cartridges}/GlimmerMonitorUiFragment.xaml (87%) rename Content.Client/{Psionics/GlimmerMonitor => Nyanotrasen/CartridgeLoader/Cartridges}/GlimmerMonitorUiFragment.xaml.cs (87%) rename Content.Client/{Psionics/Telepathy => Nyanotrasen/Chat}/PsionicChatUpdateSystem.cs (92%) rename Content.Client/{ => Nyanotrasen}/Psionics/Glimmer/GlimmerReactiveVisuals.cs (100%) rename Content.Client/{Psionics/UserInterface => Nyanotrasen/Psionics/UI}/AcceptPsionicsEUI.cs (100%) rename Content.Client/{Psionics/UserInterface => Nyanotrasen/Psionics/UI}/AcceptPsionicsWindow.cs (100%) rename Content.Client/{Psionics => Nyanotrasen}/UserInterface/GlimmerGraph.cs (97%) delete mode 100644 Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs delete mode 100644 Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs create mode 100644 Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeComponent.cs create mode 100644 Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeSystem.cs rename Content.Server/{ => Nyanotrasen/Abilities}/Psionics/Abilities/DispelPowerSystem.cs (80%) create mode 100644 Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/MetapsionicPowerSystem.cs rename Content.Server/{ => Nyanotrasen/Abilities}/Psionics/Abilities/MindSwapPowerSystem.cs (79%) rename Content.Server/{ => Nyanotrasen/Abilities}/Psionics/Abilities/MindSwappedComponent.cs (79%) rename Content.Server/{ => Nyanotrasen/Abilities}/Psionics/Abilities/NoosphericZapPowerSystem.cs (57%) rename {Content.Shared/Psionics/Abilities/PsionicInvisibility => Content.Server/Nyanotrasen/Abilities/Psionics/Abilities}/PsionicInvisibilityPowerSystem.cs (51%) rename Content.Server/{ => Nyanotrasen/Abilities}/Psionics/Abilities/PsionicRegenerationPowerSystem.cs (50%) create mode 100644 Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/PyrokinesisPowerSystem.cs create mode 100644 Content.Server/Nyanotrasen/Abilities/Psionics/Abilities/TelegnosisPowerSystem.cs create mode 100644 Content.Server/Nyanotrasen/Abilities/Psionics/PsionicAbilitiesSystem.cs rename Content.Server/{Psionics => Nyanotrasen}/Audio/GlimmerSoundComponent.cs (80%) rename Content.Server/{Psionics/Telepathy/TelepathyChatSystem.cs => Nyanotrasen/Chat/NyanoChatSystem.cs} (79%) rename Content.Server/{Psionics/Telepathy => Nyanotrasen/Chat}/TelepathicRepeaterComponent.cs (82%) create mode 100644 Content.Server/Nyanotrasen/Objectives/Components/BecomePsionicConditionComponent.cs create mode 100644 Content.Server/Nyanotrasen/Objectives/Systems/BecomePsionicConditionSystem.cs rename Content.Server/{ => Nyanotrasen}/Psionics/AcceptPsionicsEui.cs (95%) rename Content.Server/{ => Nyanotrasen}/Psionics/AntiPsychicWeaponComponent.cs (100%) rename Content.Server/{ => Nyanotrasen}/Psionics/Dreams/DreamSystem.cs (93%) rename Content.Server/{ => Nyanotrasen}/Psionics/Glimmer/GlimmerCommands.cs (94%) rename Content.Server/{ => Nyanotrasen}/Psionics/Glimmer/GlimmerReactiveSystem.cs (95%) create mode 100644 Content.Server/Nyanotrasen/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs rename Content.Server/{ => Nyanotrasen}/Psionics/Glimmer/Structures/GlimmerSourceComponent.cs (100%) rename Content.Server/{ => Nyanotrasen}/Psionics/Glimmer/Structures/GlimmerStructuresSystem.cs (69%) rename Content.Server/{ => Nyanotrasen}/Psionics/Invisibility/PsionicInvisibilitySystem.cs (87%) rename {Content.Shared/Psionics/Abilities/PsionicInvisibility => Content.Server/Nyanotrasen/Psionics/Invisibility}/PsionicInvisibleContactsComponent.cs (89%) rename {Content.Shared/Psionics/Abilities/PsionicInvisibility => Content.Server/Nyanotrasen/Psionics/Invisibility}/PsionicInvisibleContactsSystem.cs (94%) rename {Content.Shared/Psionics/Abilities/PsionicInvisibility => Content.Server/Nyanotrasen/Psionics/Invisibility}/PsionicallyInvisibleComponent.cs (76%) create mode 100644 Content.Server/Nyanotrasen/Psionics/PotentialPsionicComponent.cs rename Content.Server/{ => Nyanotrasen}/Psionics/PsionicAwaitingPlayerComponent.cs (100%) rename Content.Server/{ => Nyanotrasen}/Psionics/PsionicBonusChanceComponent.cs (100%) rename Content.Server/{ => Nyanotrasen}/Psionics/PsionicsCommands.cs (82%) rename Content.Server/{ => Nyanotrasen}/Psionics/PsionicsSystem.cs (89%) delete mode 100644 Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs delete mode 100644 Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs delete mode 100644 Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs delete mode 100644 Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs delete mode 100644 Content.Server/Psionics/Abilities/TelegnosisPowerSystem.cs delete mode 100644 Content.Server/Psionics/Glimmer/PassiveGlimmerReductionSystem.cs delete mode 100644 Content.Server/Psionics/PotentialPsionicComponent.cs delete mode 100644 Content.Server/Psionics/Telepathy/TSayCommand.cs create mode 100644 Content.Shared/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiState.cs delete mode 100644 Content.Shared/DeltaV/CartridgeLoader/Cartridges/SecWatchUiState.cs rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/AcceptPsionicsEuiMessage.cs (100%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/Dispel/DamageOnDispelComponent.cs (77%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/Dispel/DispelPowerComponent.cs (79%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/Dispel/DispellableComponent.cs (69%) create mode 100644 Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs create mode 100644 Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs create mode 100644 Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Metapsionics/MetapsionicPowerComponent.cs rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/MindSwap/MindSwapPowerComponent.cs (76%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/NoosphericZap/NoosphericZapPowerComponent.cs (77%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerComponent.cs (71%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs (68%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/PsionicRegeneration/PsionicRegenerationPowerComponent.cs (76%) create mode 100644 Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Abilities/Telegnosis/TelegnosisPowerComponent.cs (73%) create mode 100644 Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/Telegnosis/TelegnosticProjectionComponent.cs rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Items/ClothingGrantPsionicPowerComponent.cs (84%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Items/HeadCageComponent.cs (96%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Items/HeadCagedComponent.cs (81%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Items/PsionicItemsSystem.cs (98%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/Items/TinfoilHatComponent.cs (90%) create mode 100644 Content.Shared/Nyanotrasen/Abilities/Psionics/PsionicComponent.cs rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/PsionicInsulationComponent.cs (82%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/PsionicsDisabledComponent.cs (84%) rename Content.Shared/{ => Nyanotrasen/Abilities}/Psionics/SharedPsionicAbilitiesSystem.cs (82%) create mode 100644 Content.Shared/Nyanotrasen/Actions/Events/MassSleepPowerActionEvent.cs delete mode 100644 Content.Shared/Nyanotrasen/Actions/Events/RegenerativeStasisPowerActionEvent.cs create mode 100644 Content.Shared/Nyanotrasen/Psionics/Events.cs create mode 100644 Content.Shared/Nyanotrasen/Psionics/Glimmer/GlimmerSystem.cs rename Content.Shared/{ => Nyanotrasen}/Psionics/Glimmer/SharedGlimmerReactiveComponent.cs (100%) rename Content.Shared/{ => Nyanotrasen}/Psionics/Glimmer/SharedGlimmerReactiveVisuals.cs (100%) delete mode 100644 Content.Shared/Psionics/Abilities/Metapsionics/MetapsionicPowerComponent.cs delete mode 100644 Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPowerComponent.cs delete mode 100644 Content.Shared/Psionics/Abilities/Pyrokinesis/PyrokinesisPrechargeComponent.cs delete mode 100644 Content.Shared/Psionics/Abilities/RegenerativeStasis/RegenerativeStasisPowerComponent.cs delete mode 100644 Content.Shared/Psionics/Abilities/Telegnosis/TelegnosticProjectionComponent.cs delete mode 100644 Content.Shared/Psionics/Events.cs delete mode 100644 Content.Shared/Psionics/Glimmer/GlimmerSystem.cs delete mode 100644 Content.Shared/Psionics/PsionicComponent.cs delete mode 100644 Content.Shared/Psionics/SharedPsionicSystem.Insulated.cs delete mode 100644 Resources/Audio/Nyanotrasen/heartbeat_fast.ogg delete mode 100644 Resources/Locale/en-US/deltav/cartridge-loader/secwatch.ftl delete mode 100644 Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl delete mode 100644 Resources/Prototypes/Guidebook/psionics.yml delete mode 100644 Resources/Prototypes/Traits/psionics.yml delete mode 100644 Resources/ServerInfo/Guidebook/Psionics.xml create mode 100644 Resources/ServerInfo/Nyanotrasen/Guidebook/Epistemics/Psionics.xml diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs index 2dbe923b2a6..ea5aa3cf256 100644 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs @@ -18,6 +18,15 @@ public override Control GetUIFragmentRoot() public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner) { _fragment = new CrimeAssistUiFragment(); + + _fragment.OnSync += _ => SendSyncMessage(userInterface); + } + + private void SendSyncMessage(BoundUserInterface userInterface) + { + var syncMessage = new CrimeAssistSyncMessageEvent(); + var message = new CartridgeUiMessage(syncMessage); + userInterface.SendMessage(message); } public override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs index fb085a8a799..e3163975d12 100644 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs @@ -1,6 +1,7 @@ using Content.Client.Message; using Content.Shared.DeltaV.CartridgeLoader.Cartridges; using Robust.Client.AutoGenerated; +using Robust.Client.ResourceManagement; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; @@ -12,7 +13,9 @@ namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; public sealed partial class CrimeAssistUiFragment : BoxContainer { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IResourceCache _resourceCache = default!; + public event Action? OnSync; private CrimeAssistPage _currentPage; private List? _pages; diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml deleted file mode 100644 index 2de8a37ff77..00000000000 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs deleted file mode 100644 index e8dd4eea446..00000000000 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Content.Shared.CartridgeLoader.Cartridges; -using Robust.Client.AutoGenerated; -using Robust.Client.UserInterface; -using Robust.Client.UserInterface.Controls; -using Robust.Client.UserInterface.XAML; - -namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; - -[GenerateTypedNameReferences] -public sealed partial class SecWatchEntryControl : BoxContainer -{ - public SecWatchEntryControl(SecWatchEntry entry) - { - RobustXamlLoader.Load(this); - - Status.Text = Loc.GetString($"criminal-records-status-{entry.Status.ToString().ToLower()}"); - Title.Text = Loc.GetString("sec-watch-entry", ("name", entry.Name), ("job", entry.Job)); - - Reason.Text = entry.Reason ?? Loc.GetString("sec-watch-no-reason"); - } -} diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs deleted file mode 100644 index da5ff825b91..00000000000 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Content.Client.UserInterface.Fragments; -using Content.Shared.CartridgeLoader; -using Content.Shared.CartridgeLoader.Cartridges; -using Robust.Client.UserInterface; - -namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; - -public sealed partial class SecWatchUi : UIFragment -{ - private SecWatchUiFragment? _fragment; - - public override Control GetUIFragmentRoot() - { - return _fragment!; - } - - public override void Setup(BoundUserInterface ui, EntityUid? owner) - { - _fragment = new SecWatchUiFragment(); - } - - public override void UpdateState(BoundUserInterfaceState state) - { - if (state is SecWatchUiState cast) - _fragment?.UpdateState(cast); - } -} diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml deleted file mode 100644 index 7fb2c42debc..00000000000 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs deleted file mode 100644 index ad152840529..00000000000 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Content.Shared.CartridgeLoader.Cartridges; -using Robust.Client.AutoGenerated; -using Robust.Client.UserInterface.Controls; -using Robust.Client.UserInterface.XAML; - -namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; - -[GenerateTypedNameReferences] -public sealed partial class SecWatchUiFragment : BoxContainer -{ - public SecWatchUiFragment() - { - RobustXamlLoader.Load(this); - } - - public void UpdateState(SecWatchUiState state) - { - NoEntries.Visible = state.Entries.Count == 0; - Entries.RemoveAllChildren(); - foreach (var entry in state.Entries) - { - Entries.AddChild(new SecWatchEntryControl(entry)); - } - } -} diff --git a/Content.Client/Psionics/GlimmerMonitor/GlimmerMonitorUi.cs b/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs similarity index 92% rename from Content.Client/Psionics/GlimmerMonitor/GlimmerMonitorUi.cs rename to Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs index 0d8accb9f86..0b5fc7ad38c 100644 --- a/Content.Client/Psionics/GlimmerMonitor/GlimmerMonitorUi.cs +++ b/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUi.cs @@ -1,11 +1,10 @@ using Robust.Client.GameObjects; using Robust.Client.UserInterface; -using Content.Client.Psionics.UI; using Content.Client.UserInterface.Fragments; using Content.Shared.CartridgeLoader.Cartridges; using Content.Shared.CartridgeLoader; -namespace Content.Client.Psionics.GlimmerMonitor; +namespace Content.Client.Nyanotrasen.CartridgeLoader.Cartridges; public sealed partial class GlimmerMonitorUi : UIFragment { diff --git a/Content.Client/Psionics/GlimmerMonitor/GlimmerMonitorUiFragment.xaml b/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml similarity index 87% rename from Content.Client/Psionics/GlimmerMonitor/GlimmerMonitorUiFragment.xaml rename to Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml index ade0720696b..119a1831e6e 100644 --- a/Content.Client/Psionics/GlimmerMonitor/GlimmerMonitorUiFragment.xaml +++ b/Content.Client/Nyanotrasen/CartridgeLoader/Cartridges/GlimmerMonitorUiFragment.xaml @@ -1,9 +1,8 @@ -