From 5d347ebb94980a0661bfb7e02bf8245dafeccf17 Mon Sep 17 00:00:00 2001 From: Spatison <137375981+Spatison@users.noreply.github.com> Date: Sun, 9 Mar 2025 15:01:34 +0300 Subject: [PATCH] Upstream 08.03-09.03 (#299) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Grabbing Fixes / Table Slam (#1889) # Description Ports several fixes + Tabling from [/Goob-Station#1922](https://github.com/Goob-Station/Goob-Station/pull/1922) Tabling is pretty much 1:1 with how it is from SS13 ## This shit is so code Required before I can port [Martial Arts](https://github.com/Goob-Station/Goob-Station/pull/1868) # TODO * [ ] Await merge * [ ] Gaming # Media ![CQC](https://github.com/user-attachments/assets/dc202ce1-ec97-4448-b8bc-71b9a44a608f) # Changelog 🆑 Eagle * add: Table slamming. Harm a table when you have someone harm choked, see what happens. * tweak: Grab throw damage to other entities is now based on the thrown entities kinetic energy. No more mouse wrecking balls. * tweak: You can now escape from a soft grab by just walking away. * tweak: You can no longer grab someone else while your being grabbed. * tweak: Mass now effects grab release attempts. ## Summary by CodeRabbit - **New Features** - Introduced a table slam mechanic that brings dynamic combat interactions. Characters and objects can now be “tabled” with associated damage, stamina effects, and paralysis chance. - Added new interactive states for pullable entities, enriching environmental and combat engagements. - **Gameplay Improvements** - Refined pulling and throwing mechanics to enhance collision handling and damage calculations, resulting in more impactful throw actions and balanced kinetic responses. (cherry picked from commit 71147f8295c5c817b56d52c5d2a38acced2f14b9) * Automatic Changelog Update (#1889) (cherry picked from commit 434ce42a8a0739ff0873c4c02bfe83ed39c857e9) * Fix UI Crap (#1888) I have no idea if this fixes the issues, and I have not checked if it does. But this is the only thing we're missing that wasn't related to other unrelated stuff. ## Summary by CodeRabbit - **Bug Fixes** - Improved the initialization process for several in-game user interfaces, ensuring that all essential functionalities load consistently when accessed. - **New Features** - Enhanced the voice mask configuration panel to automatically present available speech verb options, streamlining the setup process for users. --------- Co-authored-by: Milon Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> (cherry picked from commit e2fbebba312a01d9fb92eaac64190df503607f6b) * Shuttle Spawner Airlocks (#1890) # Description This PR adds a variety of "Shuttle Spawning Airlocks" for certain ships in this game that mappers might wish to use. The most important of which are airlocks that cause a Cargo Shuttle and a Pathfinder to spawn already docked to the station. The fact that nobody did this before was fucking astounding to me. # Changelog :cl: - add: Added a variety of "Shuttle Spawning Airlocks" for mappers to use, which can make it so that shuttles like the Cargo Shuttle, Pathfinder, etc. Spawn already docked to the station. ## Summary by CodeRabbit - **New Features** - Introduced a refined docking and spawning system for shuttle operations, incorporating multiple shuttle types including cargo, dart, infiltrator, pathfinder, and SANDropship. - Added dedicated deployment entities to manage shuttle instantiation effectively. - Rolled out a new tagging framework to enhance the categorization and identification of dockable vehicles. (cherry picked from commit 2f9239f6b0918fbdca1f0c48a06c3b3b76a11ab8) * Automatic Changelog Update (#1890) (cherry picked from commit 39eb098ebe3fcf7f283f46fadfc76545c20e667c) * Update Credits (#1854) This is an automated Pull Request. This PR updates the GitHub contributors in the credits section. Co-authored-by: SimpleStation Changelogs (cherry picked from commit ad2ebc04093388d29db758fd7e632744e4d728d8) * Remove Outdated Description From Flash, Add One to the New Disabler A… (#1887) # Description Accidentally left an old ExtendDescription on a flash which is no longer accurate, and added extra descriptions to the rev manifesto and civilian disabler while I was at it. --- # Changelog :cl: - add: Added extra descriptions to the revolutionary manifesto and the civilian disabler - fix: Fixed extenddescription on flash ## Summary by CodeRabbit - **New Features** - Introduced extended, context-sensitive in-game descriptions for the revolutionary manifesto, offering nuanced details about its use across various roles. - Added enhanced descriptive information for the civilian disabler weapon, clarifying its legal ownership and accessory considerations. - **Chores** - Streamlined the flash item display by removing redundant extended descriptions to improve clarity. --------- Signed-off-by: Timfa (cherry picked from commit 3e3bee060cb7eee98ae3fde7c4f7b819f16bf840) * Automatic Changelog Update (#1887) (cherry picked from commit 4af6dc83bd2ebded1421dadea70b6a9586776fda) * NewMats Lathe Recipe Changes (#1873) # Description Removes wait times from Copper, Lead, and Aluminum and reduces the wait time for Tungsten to 0.13 (4 seconds over 30 ingots, too rare for it to have no completiontime but too much completiontime for just one ingot). It seems pretty ridiculous to make the former 3 recipes have a wait time of TWO SECONDS PER INDIVIDUAL INGOT (which presents a lot of problems in practice for salvagers) in comparison to the standard ore recipes which have 0 wait times at all. if the wait times are intentional then I would like you to consider reducing them to something similar to what I did with the Tungsten- with X seconds over 30 (or any other standard amount) ingots --- # Changelog :cl: - tweak: the Ore Processors now process Lead, Copper, and Aluminum instantly, and is much faster at processing Tungsten ## Summary by CodeRabbit - **Chores** - Adjusted lathe production times for several recipes, resulting in more accurate processing durations. - The tungsten-based recipe now completes significantly faster (0.13 seconds versus 4 seconds). - Three metal-based recipes have been updated to finish in shorter durations (0.01 to 0.016 seconds). (cherry picked from commit d295e2535f9aa21497460279d0bfe108920c445b) * Automatic Changelog Update (#1873) (cherry picked from commit 8deed0c3c9d16ff0cdb956fc0ee457a5bf14f5ed) * Revert "[Add] High-Risk Loadout Item For Warden: Power Gloves (#252)" This reverts commit 1f936feaa894d1b9efd3d3b554e77022f8ad785e. * Grab Intent Part 2: Martial Arts (#1891) # Description Finally, after 9 years in development, CQC is here. Traitors can buy a CQC manual in the uplink, giving them access to unarmed combos, and instant hardgrabs. Traitors can also buy a Sleeping Carp Scroll, giving them 3 different unarmed combos, and the ability to deflect all incoming projectiles, at the cost of no longer being able to use ranged weapons. The Chef can use Close-Quarters-Cooking while in the kitchen. Tiders beware. Security officers also have access to a Corporate Judo Belt as an alternative to the stun baton. The Warden starts with Krav Maga gloves in his locker, with 3 different attacks. ## This code is, not shit perhaps? Ports martial arts from [/Goob-Station#1868](https://github.com/Goob-Station/Goob-Station/pull/1868) All seems pretty well written, shouldn't be hard to add new ones in the future. There also exists a version of the CQC manual for the BSO. Might add to the BSO locker if requested. # TODO * [x] Await reviews * [x] Pain # Media Judo https://github.com/user-attachments/assets/b0aa4d24-f5cd-478e-8358-a095d46a4572 CQC https://youtu.be/c0EJfbwqil8 Sleeping Carp https://github.com/user-attachments/assets/a16ec334-9f9a-4820-b4f1-32a0cc598c67 https://github.com/user-attachments/assets/3e2bfc95-7c92-46f6-9b7c-b1e6596540c7 # Changelog 🆑 Eagle * add: Added Corporate Judo, CQC, Sleeping Carp, and Krav Maga martial arts with unique abilities. * add: The Chef has been given Close Quarters Cooking in the Kitchen and Bar. Tiders beware. --------- Signed-off-by: Eagle-0 <114363363+Eagle-0@users.noreply.github.com> (cherry picked from commit 68872f85c8b2227e871667caed2289042edd0d7b) * Automatic Changelog Update (#1891) (cherry picked from commit 9e3ad56873aedb7a7d0fff6037f9aaf0026897c0) * Bug Fix: Fix Roboticist Airlock Sprite Error (#1899) # Description Description. A fix for [this issue](https://github.com/Simple-Station/Einstein-Engines/issues/1872) Fixed bug of the painted roboticist airlock displaying the windowed counterpart instead of the standard one. # TODO - [ ] Task - [x] Completed Task ---

Media

https://github.com/user-attachments/assets/fbe4c85f-c876-4e29-9c8d-cf95314e737f
--- # Changelog :cl: - fix: Fixed bug of the painted roboticist airlock displaying the windowed counterpart instead of the standard one. (cherry picked from commit a3b823b0059a67767f0adf27ec65151d2f73a1fd) * Automatic Changelog Update (#1899) (cherry picked from commit ca839d18fbcdb85d4d1e60f2acad68fda02e1634) * Fixes SM Being Started on Round Start (#1901) # Description To stop the SM from getting activated without something being thrown into the SM or by having emitters hit the SM. --- # TODO - [x] Fix the SM by starting on its own. --- # Changelog :cl: - fix: SM no longer starts on round start. - fix: SM will no longer delam from spacing unless it's activated. --------- Co-authored-by: Nathaniel Adams <60526456+Nathaniel-Adams@users.noreply.github.com> (cherry picked from commit 234ac6119f999ff2bfaabee6b93b5fa75c61c0fa) * Automatic Changelog Update (#1901) (cherry picked from commit 3a0c67ba9c6aa8341e9bfd529bb58818164e20c8) * Tc rebalance --------- Co-authored-by: Eagle-0 <114363363+Eagle-0@users.noreply.github.com> Co-authored-by: SimpleStation Changelogs Co-authored-by: VMSolidus Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Timfa Co-authored-by: RadsammyT <32146976+RadsammyT@users.noreply.github.com> Co-authored-by: Paulo Artur Pinheiro Viana Villaça <112904295+AlgumCorrupto@users.noreply.github.com> Co-authored-by: Solaris <60526456+SolarisBirb@users.noreply.github.com> --- .../AtmosAlertsComputerBoundUserInterface.cs | 2 + .../UI/InstrumentBoundUserInterface.cs | 2 + .../Ui/NewsWriterBoundUserInterface.cs | 2 + .../CrewMonitoringBoundUserInterface.cs | 2 + Content.Client/Nuke/NukeBoundUserInterface.cs | 2 + ...owerMonitoringConsoleBoundUserInterface.cs | 2 + .../Store/Ui/StoreBoundUserInterface.cs | 2 + .../UI/SurveillanceCameraSetupBoundUi.cs | 2 + .../VoiceMaskNameChangeWindow.xaml.cs | 2 + .../SupermatterConsoleBoundUserInterface.cs | 2 + .../MartialArts/MartialArtsSystem.cs | 10 + .../Body/Systems/RespiratorSystem.cs | 7 +- .../Stunnable/Systems/StunbatonSystem.cs | 1 + .../Supermatter/Systems/SupermatterSystem.cs | 8 +- .../MartialArts/MartialArtsSystem.cs | 26 ++ .../Damage/Systems/StaminaSystem.cs | 9 + .../Pulling/Components/PullableComponent.cs | 27 +- .../Pulling/Components/PullerComponent.cs | 9 +- .../Pulling/Events/CheckGrabOverridesEvent.cs | 14 + .../Movement/Pulling/Systems/PullingSystem.cs | 243 +++++++-------- Content.Shared/Throwing/ThrowingSystem.cs | 1 + .../Weapons/Melee/SharedMeleeWeaponSystem.cs | 9 + .../Components/SupermatterComponent.cs | 2 +- .../{CCVars => CCVar}/CCVars.Goob.cs | 0 .../MartialArts/ComboPrototype.cs | 70 +++++ .../Components/CanPerformComboComponent.cs | 30 ++ .../Components/GrabStagesOverrideComponent.cs | 12 + .../GrantMartialArtKnowledgeComponent.cs | 44 +++ .../Components/KravMagaComponents.cs | 78 +++++ .../Components/MartialArtsComponents.cs | 61 ++++ .../MartialArts/Events/CQCEvents.cs | 18 ++ .../Events/ComboAttackPerformedEvent.cs | 30 ++ .../Events/ComboBeingPerformedEvent.cs | 10 + .../MartialArts/Events/JudoEvents.cs | 16 + .../MartialArts/Events/KravMagaActionEvent.cs | 10 + .../MartialArts/Events/SleepingCarpEvents.cs | 18 ++ .../MartialArts/MartialArtPrototype.cs | 36 +++ .../SharedMartialArtsSystem.CQC.cs | 186 +++++++++++ ...SharedMartialArtsSystem.CanPerformCombo.cs | 78 +++++ .../SharedMartialArtsSystem.CorporateJudo.cs | 134 ++++++++ .../SharedMartialArtsSystem.KravMaga.cs | 109 +++++++ .../SharedMartialArtsSystem.SleepingCarp.cs | 155 +++++++++ .../MartialArts/SharedMartialArtsSystem.cs | 287 +++++++++++++++++ .../TableSlam/PostTabledComponent.cs | 16 + .../_Goobstation/TableSlam/TableSlamSystem.cs | 157 ++++++++++ .../TableSlam/TableableComponent.cs | 32 ++ .../_White/Grab/GrabThrownComponent.cs | 2 - .../_White/Grab/GrabThrownSystem.cs | 40 +-- Resources/Changelog/Changelog.yml | 80 +++++ Resources/Credits/GitHub.txt | 2 +- .../martial-arts/martial-arts.ftl | 44 +++ .../_white/objectives/conditions/steal.ftl | 1 - .../items/revolutionarymanifesto.ftl | 4 + .../items/weapons/civiliandisabler.ftl | 1 + .../ru-RU/_white/object/clothes/gloves.ftl | 3 - .../_white/objectives/conditions/steal.ftl | 1 - .../Locale/ru-RU/loadouts/jobs/security.ftl | 1 - .../Catalog/Fills/Lockers/security.yml | 293 +++++++++--------- .../Objects/Specific/revolutionary.yml | 32 ++ .../Weapons/Guns/Battery/battery_guns.yml | 10 + .../Entities/Objects/Weapons/security.yml | 198 ++++++------ .../Structures/Doors/airlock_groups.yml | 2 +- .../Prototypes/Objectives/objectiveGroups.yml | 1 - Resources/Prototypes/Recipes/Lathes/sheet.yml | 32 +- .../Prototypes/Roles/Jobs/Civilian/chef.yml | 2 + .../Doors/Airlocks/shuttleAirlocks.yml | 81 +++++ Resources/Prototypes/_EE/Tags/tags.yml | 14 + .../_Goobstation/Catalog/uplink_catalog.yml | 33 ++ .../Entities/Clothing/Belt/belts.yml | 33 ++ .../Objects/Weapons/Melee/kravmagagloves.yml | 16 + .../_Goobstation/Entities/Specific/bso.yml | 15 + .../Entities/Specific/syndicate.yml | 32 ++ .../_Goobstation/MartialArts/carp.yml | 64 ++++ .../_Goobstation/MartialArts/cqc.yml | 69 +++++ .../_Goobstation/MartialArts/judo.yml | 45 +++ .../_Goobstation/MartialArts/kravmaga.yml | 50 +++ .../_Nuclear14/Recipes/Lathes/materials.yml | 6 +- .../_White/Entities/Clothing/Hands/gloves.yml | 28 -- .../_White/Objectives/stealTargerGroups.yml | 6 - .../Prototypes/_White/Objectives/traitor.yml | 11 - .../Hands/Gloves/inspection.rsi/meta.json | 2 +- .../Actions/kravmaga.rsi/legsweep.png | Bin 0 -> 552 bytes .../Actions/kravmaga.rsi/lungpunch.png | Bin 0 -> 639 bytes .../Actions/kravmaga.rsi/meta.json | 20 ++ .../Actions/kravmaga.rsi/neckchop.png | Bin 0 -> 615 bytes .../Belt/judobelt.rsi/equipped-BELT.png | Bin 0 -> 503 bytes .../Clothing/Belt/judobelt.rsi/icon.png | Bin 0 -> 518 bytes .../Clothing/Belt/judobelt.rsi/meta.json | 18 ++ .../Gloves/kravgloves.rsi/equipped-HAND.png | Bin 0 -> 530 bytes .../Hands/Gloves/kravgloves.rsi/icon.png | Bin 0 -> 486 bytes .../Hands/Gloves/kravgloves.rsi/meta.json | 18 ++ .../Objects/Misc/cqc_manual.rsi/icon-alt.png | Bin 0 -> 327 bytes .../Objects/Misc/cqc_manual.rsi/icon.png | Bin 0 -> 225 bytes .../Objects/Misc/cqc_manual.rsi/meta.json | 17 + .../Objects/scroll.rsi/equipped-BELT.png | Bin 0 -> 409 bytes .../Wizard/Objects/scroll.rsi/inhand-left.png | Bin 0 -> 308 bytes .../Objects/scroll.rsi/inhand-right.png | Bin 0 -> 295 bytes .../Wizard/Objects/scroll.rsi/meta.json | 29 ++ .../Wizard/Objects/scroll.rsi/scroll.png | Bin 0 -> 633 bytes .../Wizard/Objects/scroll.rsi/scroll2.png | Bin 0 -> 673 bytes 100 files changed, 2846 insertions(+), 483 deletions(-) create mode 100644 Content.Client/_Goobstation/MartialArts/MartialArtsSystem.cs create mode 100644 Content.Server/_Goobstation/MartialArts/MartialArtsSystem.cs create mode 100644 Content.Shared/Movement/Pulling/Events/CheckGrabOverridesEvent.cs rename Content.Shared/_Goobstation/{CCVars => CCVar}/CCVars.Goob.cs (100%) create mode 100644 Content.Shared/_Goobstation/MartialArts/ComboPrototype.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Components/CanPerformComboComponent.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Components/GrabStagesOverrideComponent.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Components/GrantMartialArtKnowledgeComponent.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Components/KravMagaComponents.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Components/MartialArtsComponents.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Events/CQCEvents.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Events/ComboAttackPerformedEvent.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Events/ComboBeingPerformedEvent.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Events/JudoEvents.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Events/KravMagaActionEvent.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/Events/SleepingCarpEvents.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/MartialArtPrototype.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CQC.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CanPerformCombo.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CorporateJudo.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.KravMaga.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.SleepingCarp.cs create mode 100644 Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.cs create mode 100644 Content.Shared/_Goobstation/TableSlam/PostTabledComponent.cs create mode 100644 Content.Shared/_Goobstation/TableSlam/TableSlamSystem.cs create mode 100644 Content.Shared/_Goobstation/TableSlam/TableableComponent.cs create mode 100644 Resources/Locale/en-US/_Goobstation/martial-arts/martial-arts.ftl delete mode 100644 Resources/Locale/en-US/_white/objectives/conditions/steal.ftl create mode 100644 Resources/Locale/en-US/extenddescriptions/items/revolutionarymanifesto.ftl create mode 100644 Resources/Locale/en-US/extenddescriptions/items/weapons/civiliandisabler.ftl delete mode 100644 Resources/Locale/ru-RU/_white/object/clothes/gloves.ftl delete mode 100644 Resources/Locale/ru-RU/_white/objectives/conditions/steal.ftl create mode 100644 Resources/Prototypes/_EE/Entities/Structures/Doors/Airlocks/shuttleAirlocks.yml create mode 100644 Resources/Prototypes/_EE/Tags/tags.yml create mode 100644 Resources/Prototypes/_Goobstation/Entities/Clothing/Belt/belts.yml create mode 100644 Resources/Prototypes/_Goobstation/Entities/Objects/Weapons/Melee/kravmagagloves.yml create mode 100644 Resources/Prototypes/_Goobstation/Entities/Specific/bso.yml create mode 100644 Resources/Prototypes/_Goobstation/Entities/Specific/syndicate.yml create mode 100644 Resources/Prototypes/_Goobstation/MartialArts/carp.yml create mode 100644 Resources/Prototypes/_Goobstation/MartialArts/cqc.yml create mode 100644 Resources/Prototypes/_Goobstation/MartialArts/judo.yml create mode 100644 Resources/Prototypes/_Goobstation/MartialArts/kravmaga.yml delete mode 100644 Resources/Prototypes/_White/Objectives/stealTargerGroups.yml delete mode 100644 Resources/Prototypes/_White/Objectives/traitor.yml create mode 100644 Resources/Textures/_Goobstation/Actions/kravmaga.rsi/legsweep.png create mode 100644 Resources/Textures/_Goobstation/Actions/kravmaga.rsi/lungpunch.png create mode 100644 Resources/Textures/_Goobstation/Actions/kravmaga.rsi/meta.json create mode 100644 Resources/Textures/_Goobstation/Actions/kravmaga.rsi/neckchop.png create mode 100644 Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/equipped-BELT.png create mode 100644 Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/icon.png create mode 100644 Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/meta.json create mode 100644 Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/equipped-HAND.png create mode 100644 Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/icon.png create mode 100644 Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/meta.json create mode 100644 Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/icon-alt.png create mode 100644 Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/icon.png create mode 100644 Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/meta.json create mode 100644 Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/equipped-BELT.png create mode 100644 Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/inhand-left.png create mode 100644 Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/inhand-right.png create mode 100644 Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/meta.json create mode 100644 Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/scroll.png create mode 100644 Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/scroll2.png diff --git a/Content.Client/Atmos/Consoles/AtmosAlertsComputerBoundUserInterface.cs b/Content.Client/Atmos/Consoles/AtmosAlertsComputerBoundUserInterface.cs index 08cae979b9..a31eb898fe 100644 --- a/Content.Client/Atmos/Consoles/AtmosAlertsComputerBoundUserInterface.cs +++ b/Content.Client/Atmos/Consoles/AtmosAlertsComputerBoundUserInterface.cs @@ -11,6 +11,8 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface protected override void Open() { + base.Open(); + _menu = new AtmosAlertsComputerWindow(this, Owner); _menu.OpenCentered(); _menu.OnClose += Close; diff --git a/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs b/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs index 4816ce8c36..b713959f5a 100644 --- a/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs +++ b/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs @@ -41,6 +41,8 @@ namespace Content.Client.Instruments.UI protected override void Open() { + base.Open(); + _instrumentMenu = this.CreateWindow(); _instrumentMenu.Title = EntMan.GetComponent(Owner).EntityName; diff --git a/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs b/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs index 22e5bc452a..2f5b485ba4 100644 --- a/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs +++ b/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs @@ -20,6 +20,8 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface protected override void Open() { + base.Open(); + _menu = this.CreateWindow(); _menu.ArticleEditorPanel.PublishButtonPressed += OnPublishButtonPressed; diff --git a/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs b/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs index b1f239cd78..550d0fcdfe 100644 --- a/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs +++ b/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs @@ -14,6 +14,8 @@ public sealed class CrewMonitoringBoundUserInterface : BoundUserInterface protected override void Open() { + base.Open(); + EntityUid? gridUid = null; var stationName = string.Empty; diff --git a/Content.Client/Nuke/NukeBoundUserInterface.cs b/Content.Client/Nuke/NukeBoundUserInterface.cs index 2e15042373..3cf6a28974 100644 --- a/Content.Client/Nuke/NukeBoundUserInterface.cs +++ b/Content.Client/Nuke/NukeBoundUserInterface.cs @@ -18,6 +18,8 @@ namespace Content.Client.Nuke protected override void Open() { + base.Open(); + _menu = this.CreateWindow(); _menu.OnKeypadButtonPressed += i => diff --git a/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs b/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs index cbc343c06c..2a7c24e96b 100644 --- a/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs +++ b/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs @@ -12,6 +12,8 @@ public sealed class PowerMonitoringConsoleBoundUserInterface : BoundUserInterfac protected override void Open() { + base.Open(); + _menu = this.CreateWindow(); _menu.SetEntity(Owner); _menu.SendPowerMonitoringConsoleMessageAction += SendPowerMonitoringConsoleMessage; diff --git a/Content.Client/Store/Ui/StoreBoundUserInterface.cs b/Content.Client/Store/Ui/StoreBoundUserInterface.cs index 8c48258de0..d8236604bf 100644 --- a/Content.Client/Store/Ui/StoreBoundUserInterface.cs +++ b/Content.Client/Store/Ui/StoreBoundUserInterface.cs @@ -27,6 +27,8 @@ public sealed class StoreBoundUserInterface : BoundUserInterface protected override void Open() { + base.Open(); + _menu = this.CreateWindow(); if (EntMan.TryGetComponent(Owner, out var store)) _menu.Title = Loc.GetString(store.Name); diff --git a/Content.Client/SurveillanceCamera/UI/SurveillanceCameraSetupBoundUi.cs b/Content.Client/SurveillanceCamera/UI/SurveillanceCameraSetupBoundUi.cs index 1880e431ee..cacb25b004 100644 --- a/Content.Client/SurveillanceCamera/UI/SurveillanceCameraSetupBoundUi.cs +++ b/Content.Client/SurveillanceCamera/UI/SurveillanceCameraSetupBoundUi.cs @@ -21,6 +21,8 @@ public sealed class SurveillanceCameraSetupBoundUi : BoundUserInterface protected override void Open() { + base.Open(); + _window = new(); if (_type == SurveillanceCameraSetupUiKey.Router) diff --git a/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs b/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs index 7ca4dd4b95..eddaaaf54e 100644 --- a/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs +++ b/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs @@ -31,6 +31,8 @@ public sealed partial class VoiceMaskNameChangeWindow : FancyWindow OnVerbChange?.Invoke((string?) args.Button.GetItemMetadata(args.Id)); SpeechVerbSelector.SelectId(args.Id); }; + + AddVerbs(); } public void ReloadVerbs(IPrototypeManager proto) diff --git a/Content.Client/_EE/Supermatter/Consoles/SupermatterConsoleBoundUserInterface.cs b/Content.Client/_EE/Supermatter/Consoles/SupermatterConsoleBoundUserInterface.cs index 80c0fc0276..56d2abf18c 100644 --- a/Content.Client/_EE/Supermatter/Consoles/SupermatterConsoleBoundUserInterface.cs +++ b/Content.Client/_EE/Supermatter/Consoles/SupermatterConsoleBoundUserInterface.cs @@ -11,6 +11,8 @@ public sealed class SupermatterConsoleBoundUserInterface : BoundUserInterface protected override void Open() { + base.Open(); + _menu = new SupermatterConsoleWindow(this, Owner); _menu.OpenCentered(); _menu.OnClose += Close; diff --git a/Content.Client/_Goobstation/MartialArts/MartialArtsSystem.cs b/Content.Client/_Goobstation/MartialArts/MartialArtsSystem.cs new file mode 100644 index 0000000000..049bc418cf --- /dev/null +++ b/Content.Client/_Goobstation/MartialArts/MartialArtsSystem.cs @@ -0,0 +1,10 @@ +using Content.Shared._Goobstation.MartialArts; + +namespace Content.Client._Goobstation.MartialArts; + +/// +/// This handles... +/// +public sealed class MartialArtsSystem : SharedMartialArtsSystem +{ +} diff --git a/Content.Server/Body/Systems/RespiratorSystem.cs b/Content.Server/Body/Systems/RespiratorSystem.cs index cd02b1d542..c2c6c47377 100644 --- a/Content.Server/Body/Systems/RespiratorSystem.cs +++ b/Content.Server/Body/Systems/RespiratorSystem.cs @@ -5,6 +5,7 @@ using Content.Server.Chat.Systems; using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.EntityEffects.EffectConditions; using Content.Server.EntityEffects.Effects; +using Content.Shared._Goobstation.MartialArts.Components; // Goobstation - Martial Arts using Content.Server.Popups; using Content.Shared.Alert; using Content.Shared.Atmos; @@ -61,7 +62,11 @@ public sealed class RespiratorSystem : EntitySystem { if(respirator.Saturation < respirator.SuffocationThreshold) return false; - return !TryComp(uid, out var pullable) || pullable.GrabStage != GrabStage.Suffocate; + if (TryComp(uid, out var pullable) + && pullable.GrabStage == GrabStage.Suffocate) + return false; + + return !HasComp(uid); } // Goobstation end private void OnMapInit(Entity ent, ref MapInitEvent args) diff --git a/Content.Server/Stunnable/Systems/StunbatonSystem.cs b/Content.Server/Stunnable/Systems/StunbatonSystem.cs index 43ad2bccd8..42376f53b0 100644 --- a/Content.Server/Stunnable/Systems/StunbatonSystem.cs +++ b/Content.Server/Stunnable/Systems/StunbatonSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.Power.Events; using Content.Server.Stunnable.Components; +using Content.Shared._Goobstation.MartialArts; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Damage.Events; using Content.Shared.Examine; diff --git a/Content.Server/_EE/Supermatter/Systems/SupermatterSystem.cs b/Content.Server/_EE/Supermatter/Systems/SupermatterSystem.cs index 5e9ec4c48a..a29b5049a5 100644 --- a/Content.Server/_EE/Supermatter/Systems/SupermatterSystem.cs +++ b/Content.Server/_EE/Supermatter/Systems/SupermatterSystem.cs @@ -78,6 +78,9 @@ public sealed partial class SupermatterSystem : EntitySystem foreach (var sm in EntityManager.EntityQuery()) { + if (!sm.Activated) + continue; + var uid = sm.Owner; AnnounceCoreDamage(uid, sm); } @@ -99,7 +102,10 @@ public sealed partial class SupermatterSystem : EntitySystem public void OnSupermatterUpdated(EntityUid uid, SupermatterComponent sm, AtmosDeviceUpdateEvent args) { ProcessAtmos(uid, sm, args.dt); - HandleDamage(uid, sm); + + // This prevents SM from delamming due to spacing without activating the SM. + if (sm.Activated) + HandleDamage(uid, sm); if (sm.Damage >= sm.DamageDelaminationPoint || sm.Delamming) HandleDelamination(uid, sm); diff --git a/Content.Server/_Goobstation/MartialArts/MartialArtsSystem.cs b/Content.Server/_Goobstation/MartialArts/MartialArtsSystem.cs new file mode 100644 index 0000000000..d559ff0822 --- /dev/null +++ b/Content.Server/_Goobstation/MartialArts/MartialArtsSystem.cs @@ -0,0 +1,26 @@ +using Content.Server.Chat.Systems; +using Content.Shared.Chat; +using Content.Shared._Goobstation.MartialArts; +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Goobstation.MartialArts.Events; + +namespace Content.Server._Goobstation.MartialArts; + +/// +/// Just handles carp sayings for now. +/// +public sealed class MartialArtsSystem : SharedMartialArtsSystem +{ + [Dependency] private readonly ChatSystem _chat = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnSleepingCarpSaying); + } + + private void OnSleepingCarpSaying(Entity ent, ref SleepingCarpSaying args) + { + _chat.TrySendInGameICMessage(ent, Loc.GetString(args.Saying), InGameICChatType.Speak, false); + } +} diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index d329f1a6bd..111e276376 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -1,4 +1,6 @@ using System.Linq; +using Content.Shared._Goobstation.MartialArts; +using Content.Shared._Goobstation.MartialArts.Components; using Content.Shared.Administration.Logs; using Content.Shared.Alert; using Content.Shared.CombatMode; @@ -152,6 +154,13 @@ public sealed partial class StaminaSystem : EntitySystem return; } + // Goobstation - Martial Arts + if (TryComp(args.User, out var knowledgeComp) + && TryComp(args.Weapon, out var blockedComp) + && knowledgeComp.MartialArtsForm == blockedComp.Form) + return; + // Goobstation + var ev = new StaminaDamageOnHitAttemptEvent(); RaiseLocalEvent(uid, ref ev); if (ev.Cancelled) diff --git a/Content.Shared/Movement/Pulling/Components/PullableComponent.cs b/Content.Shared/Movement/Pulling/Components/PullableComponent.cs index 95f3cfca7a..fd0f1c4b30 100644 --- a/Content.Shared/Movement/Pulling/Components/PullableComponent.cs +++ b/Content.Shared/Movement/Pulling/Components/PullableComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared._Goobstation.TableSlam; // Goobstation - Table SLam using Content.Shared.Alert; using Content.Shared.Movement.Pulling.Systems; // Goobstation using Robust.Shared.GameStates; @@ -9,7 +10,7 @@ namespace Content.Shared.Movement.Pulling.Components; /// Specifies an entity as being pullable by an entity with /// [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(Systems.PullingSystem))] +[Access(typeof(Systems.PullingSystem), typeof(TableSlamSystem))] public sealed partial class PullableComponent : Component { /// @@ -57,6 +58,30 @@ public sealed partial class PullableComponent : Component [AutoNetworkedField] public TimeSpan NextEscapeAttempt = TimeSpan.Zero; + + /// + /// If this pullable being tabled. + /// + [DataField, AutoNetworkedField] + public bool BeingTabled = false; + + /// + /// Constant for tabling throw math + /// + [DataField] + public float BasedTabledForceSpeed = 5f; + + /// + /// Stamina damage. taken on tabled + /// + [DataField] + public float TabledStaminaDamage = 40f; + + /// + /// Damage taken on being tabled. + /// + [DataField] + public float TabledDamage = 5f; // Goobstation end /// diff --git a/Content.Shared/Movement/Pulling/Components/PullerComponent.cs b/Content.Shared/Movement/Pulling/Components/PullerComponent.cs index 99c96f384f..fe207ff2ea 100644 --- a/Content.Shared/Movement/Pulling/Components/PullerComponent.cs +++ b/Content.Shared/Movement/Pulling/Components/PullerComponent.cs @@ -1,4 +1,5 @@ -using Content.Shared.Alert; +using Content.Shared._Goobstation.TableSlam; // Goobstation - Table Slam +using Content.Shared.Alert; using Content.Shared.Movement.Pulling.Systems; using Robust.Shared.GameStates; using Robust.Shared.Map; @@ -10,8 +11,8 @@ namespace Content.Shared.Movement.Pulling.Components; /// /// Specifies an entity as being able to pull another entity with /// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(PullingSystem))] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] +[Access(typeof(PullingSystem), typeof(TableSlamSystem))] // Goobstation - Table Slam public sealed partial class PullerComponent : Component { /// @@ -106,7 +107,7 @@ public sealed partial class PullerComponent : Component public float SuffocateGrabStaminaDamage = 10f; [DataField] - public float GrabThrowDamageModifier = 1f; + public float GrabThrowDamageModifier = 2f; [ViewVariables] public List GrabVirtualItems = new(); diff --git a/Content.Shared/Movement/Pulling/Events/CheckGrabOverridesEvent.cs b/Content.Shared/Movement/Pulling/Events/CheckGrabOverridesEvent.cs new file mode 100644 index 0000000000..faf3121eb6 --- /dev/null +++ b/Content.Shared/Movement/Pulling/Events/CheckGrabOverridesEvent.cs @@ -0,0 +1,14 @@ +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Pulling.Systems; + +namespace Content.Shared.Movement.Pulling.Events; + +public sealed class CheckGrabOverridesEvent : EntityEventArgs +{ + public CheckGrabOverridesEvent(GrabStage stage) + { + Stage = stage; + } + + public GrabStage Stage { get; set; } +} diff --git a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs index d71afe4c8d..7b957470ea 100644 --- a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs +++ b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs @@ -1,12 +1,13 @@ +using Content.Shared._Goobstation.MartialArts.Events; // Goobstation - Martial Arts +using Content.Shared.Contests; // Goobstation - Grab Intent using System.Diagnostics.CodeAnalysis; -using System.Numerics; +using System.Numerics; // Goobstation - Grab Intent using Content.Shared._White.Grab; // Goobstation using Content.Shared.ActionBlocker; using Content.Shared.Administration.Logs; using Content.Shared.Alert; using Content.Shared.Buckle.Components; using Content.Shared.CombatMode; // Goobstation -using Content.Shared.Cuffs; // Goobstation using Content.Shared.Cuffs.Components; // Goobstation using Content.Shared.Damage; // Goobstation using Content.Shared.Damage.Systems; // Goobstation @@ -77,11 +78,11 @@ public sealed class PullingSystem : EntitySystem [Dependency] private readonly SharedColorFlashEffectSystem _color = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly INetManager _netManager = default!; - [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly SharedVirtualItemSystem _virtualSystem = default!; [Dependency] private readonly GrabThrownSystem _grabThrown = default!; [Dependency] private readonly SharedCombatModeSystem _combatMode = default!; [Dependency] private readonly ThrowingSystem _throwing = default!; + [Dependency] private readonly ContestsSystem _contests = default!; // Goobstation - Grab Intent public override void Initialize() { @@ -106,7 +107,6 @@ public sealed class PullingSystem : EntitySystem SubscribeLocalEvent(OnRefreshMovespeed); SubscribeLocalEvent(OnDropHandItems); SubscribeLocalEvent(OnVirtualItemThrown); // Goobstation - Grab Intent - SubscribeLocalEvent(OnVirtualItemDropAttempt); // Goobstation - Grab Intent SubscribeLocalEvent(OnAddCuffDoAfterEvent); // Goobstation - Grab Intent SubscribeLocalEvent(OnBuckled); @@ -117,7 +117,6 @@ public sealed class PullingSystem : EntitySystem .Bind(ContentKeyFunctions.ReleasePulledObject, InputCmdHandler.FromDelegate(OnReleasePulledObject, handle: false)) .Register(); } - // Goobstation - Grab Intent private void OnAddCuffDoAfterEvent(Entity ent, ref AddCuffDoAfterEvent args) { @@ -129,7 +128,7 @@ public sealed class PullingSystem : EntitySystem && ent.Comp.Pulling != null) { if(_netManager.IsServer) - StopPulling((EntityUid) ent.Comp.Pulling, comp); + StopPulling(ent.Comp.Pulling.Value, comp); } } // Goobstation @@ -281,89 +280,62 @@ public sealed class PullingSystem : EntitySystem component.NextPushTargetChange += args.PausedTime; } - // Goobstation - Grab Intent - private void OnVirtualItemDropAttempt(EntityUid uid, PullerComponent component, VirtualItemDropAttemptEvent args) - { - if (component.Pulling == null) - return; - - if (component.Pulling != args.BlockingEntity) - return; - - if (_timing.CurTime < component.NextStageChange) - { - args.Cancel(); // VirtualItem is NOT being deleted - return; - } - - if (!args.Throw) - { - if (component.GrabStage > GrabStage.No - && TryComp(args.BlockingEntity, out PullableComponent? comp)) - { - TryLowerGrabStage(component.Pulling.Value, uid); - args.Cancel(); // VirtualItem is NOT being deleted - } - } - else - { - if (component.GrabStage <= GrabStage.Soft) - { - TryLowerGrabStage(component.Pulling.Value, uid); - args.Cancel(); // VirtualItem is NOT being deleted - } - } - } - // Goobstation - - private void OnVirtualItemDeleted(EntityUid uid, PullerComponent component, VirtualItemDeletedEvent args) + // Goobstation - Grab Intent Refactor + private void OnVirtualItemDeleted(Entity ent, ref VirtualItemDeletedEvent args) { // If client deletes the virtual hand then stop the pull. - if (component.Pulling == null) + if (ent.Comp.Pulling == null) return; - if (component.Pulling != args.BlockingEntity) - return; - - if (TryComp(args.BlockingEntity, out PullableComponent? comp)) // Goobstation - { - TryLowerGrabStage(component.Pulling.Value, uid);// Goobstation - } - } - - // Goobstation - Grab Intent - private void OnVirtualItemThrown(EntityUid uid, PullerComponent component, VirtualItemThrownEvent args) - { - if (!TryComp(uid, out PhysicsComponent? throwerPhysics) - || !TryComp(args.BlockingEntity, out PhysicsComponent? throweePhysics) - || component.Pulling == null - || component.Pulling != args.BlockingEntity) + if (ent.Comp.Pulling != args.BlockingEntity) return; if (TryComp(args.BlockingEntity, out PullableComponent? comp)) { - if (_combatMode.IsInCombatMode(uid) && - !HasComp(args.BlockingEntity) && - component.GrabStage > GrabStage.Soft) - { - var distanceToCursor = args.Direction.Length(); - var direction = args.Direction.Normalized() * MathF.Min(distanceToCursor, component.ThrowingDistance); - - var damage = new DamageSpecifier(); - damage.DamageDict.Add("Blunt", 5); - - TryStopPull(args.BlockingEntity, comp, uid, true); - _grabThrown.Throw(args.BlockingEntity, uid, direction, - component.GrabThrownSpeed, - component.StaminaDamageOnThrown, - damage * component.GrabThrowDamageModifier, - damage * component.GrabThrowDamageModifier); // Throwing the grabbed person - - _throwing.TryThrow(uid, -direction * throwerPhysics.InvMass); // Throws back the grabber - _audio.PlayPvs(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), uid); - component.NextStageChange.Add(TimeSpan.FromSeconds(2f)); // To avoid grab and throw spamming - } + TryStopPull(ent.Comp.Pulling.Value, comp, ent); } + + foreach (var item in ent.Comp.GrabVirtualItems) + { + if(TryComp(ent, out var virtualItemComponent)) + _virtualSystem.DeleteVirtualItem((item,virtualItemComponent), ent); + } + ent.Comp.GrabVirtualItems.Clear(); + } + // Goobstation - Grab Intent Refactor + + // Goobstation - Grab Intent + private void OnVirtualItemThrown(EntityUid uid, PullerComponent component, VirtualItemThrownEvent args) + { + if (!TryComp(uid, out var throwerPhysics) + || component.Pulling == null + || component.Pulling != args.BlockingEntity) + return; + + if (!TryComp(args.BlockingEntity, out PullableComponent? comp)) + return; + + if (!_combatMode.IsInCombatMode(uid) + || HasComp(args.BlockingEntity) + || component.GrabStage <= GrabStage.Soft) + return; + + var distanceToCursor = args.Direction.Length(); + var direction = args.Direction.Normalized() * MathF.Min(distanceToCursor, component.ThrowingDistance); + + var damage = new DamageSpecifier(); + damage.DamageDict.Add("Blunt", 5); + + TryStopPull(args.BlockingEntity, comp, uid, true); + _grabThrown.Throw(args.BlockingEntity, + uid, + direction, + component.GrabThrownSpeed, + component.StaminaDamageOnThrown, + damage * component.GrabThrowDamageModifier); // Throwing the grabbed person + _throwing.TryThrow(uid, -direction * throwerPhysics.InvMass); // Throws back the grabber + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), uid); + component.NextStageChange.Add(TimeSpan.FromSeconds(4f)); // To avoid grab and throw spamming } // Goobstation @@ -419,12 +391,12 @@ public sealed class PullingSystem : EntitySystem args.ModifySpeed(walkMod, sprintMod); break; case GrabStage.Soft: - var softSpeedMod = component.SoftGrabSpeedModifier; - args.ModifySpeed(walkMod * softSpeedMod, sprintMod * softSpeedMod); + var softGrabSpeedMod = component.SoftGrabSpeedModifier; + args.ModifySpeed(walkMod * softGrabSpeedMod, sprintMod * softGrabSpeedMod); break; case GrabStage.Hard: - var hardSpeedMod = component.HardGrabSpeedModifier; - args.ModifySpeed(walkMod * hardSpeedMod, sprintMod * hardSpeedMod); + var hardGrabSpeedModifier = component.HardGrabSpeedModifier; + args.ModifySpeed(walkMod * hardGrabSpeedModifier, sprintMod * hardGrabSpeedModifier); break; case GrabStage.Suffocate: var chokeSpeedMod = component.ChokeGrabSpeedModifier; @@ -443,12 +415,12 @@ public sealed class PullingSystem : EntitySystem args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier); break; case GrabStage.Soft: - var softSpeedMod = component.SoftGrabSpeedModifier; - args.ModifySpeed(component.WalkSpeedModifier * softSpeedMod, component.SprintSpeedModifier * softSpeedMod); + var softGrabSpeedMod = component.SoftGrabSpeedModifier; + args.ModifySpeed(component.WalkSpeedModifier * softGrabSpeedMod, component.SprintSpeedModifier * softGrabSpeedMod); break; case GrabStage.Hard: - var hardSpeedMod = component.HardGrabSpeedModifier; - args.ModifySpeed(component.WalkSpeedModifier * hardSpeedMod, component.SprintSpeedModifier * hardSpeedMod); + var hardGrabSpeedModifier = component.HardGrabSpeedModifier; + args.ModifySpeed(component.WalkSpeedModifier * hardGrabSpeedModifier, component.SprintSpeedModifier * hardGrabSpeedModifier); break; case GrabStage.Suffocate: var chokeSpeedMod = component.ChokeGrabSpeedModifier; @@ -460,19 +432,24 @@ public sealed class PullingSystem : EntitySystem } } - private void OnPullableMoveInput(EntityUid uid, PullableComponent component, ref MoveInputEvent args) + // Goobstation - Grab Intent + private void OnPullableMoveInput(Entity ent, ref MoveInputEvent args) { // If someone moves then break their pulling. - if (!component.BeingPulled) + if (!ent.Comp.BeingPulled) return; var entity = args.Entity; + if (ent.Comp.GrabStage == GrabStage.Soft) + TryStopPull(ent, ent, ent); + if (!_blocker.CanMove(entity)) return; - TryStopPull(uid, component, user: uid); + TryStopPull(ent, ent, user: ent); } + // Goobstation private void OnPullableCollisionChange(EntityUid uid, PullableComponent component, ref CollisionChangeEvent args) { @@ -899,6 +876,10 @@ public sealed class PullingSystem : EntitySystem if (!Resolve(puller.Owner, ref puller.Comp)) return false; + // prevent you from grabbing someone else while being grabbed + if (TryComp(puller.Owner, out var pullerAsPullable) && pullerAsPullable.Puller != null) + return false; + if (pullable.Comp.Puller != puller.Owner || puller.Comp.Pulling != pullable.Owner) return false; @@ -919,7 +900,6 @@ public sealed class PullingSystem : EntitySystem if (!_combatMode.IsInCombatMode(puller.Owner)) return false; - // It's blocking stage update, maybe better UX? if (puller.Comp.GrabStage == GrabStage.Suffocate) { @@ -940,6 +920,9 @@ public sealed class PullingSystem : EntitySystem }; var newStage = puller.Comp.GrabStage + nextStageAddition; + var ev = new CheckGrabOverridesEvent(newStage); // guh + RaiseLocalEvent(puller, ev); + newStage = ev.Stage; if (!TrySetGrabStages((puller.Owner, puller.Comp), (pullable.Owner, pullable.Comp), newStage)) return false; @@ -970,7 +953,8 @@ public sealed class PullingSystem : EntitySystem _ => throw new ArgumentOutOfRangeException() }; - pullable.Comp.GrabEscapeChance = puller.Comp.EscapeChances[stage]; + var massModifier = _contests.MassContest(puller, pullable); + pullable.Comp.GrabEscapeChance = Math.Clamp(puller.Comp.EscapeChances[stage] / massModifier, 0f, 1f); _alertsSystem.ShowAlert(puller, puller.Comp.PullingAlert, puller.Comp.PullingAlertSeverity[stage]); _alertsSystem.ShowAlert(pullable, pullable.Comp.PulledAlert, pullable.Comp.PulledAlertAlertSeverity[stage]); @@ -988,6 +972,9 @@ public sealed class PullingSystem : EntitySystem _audio.PlayPvs(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), pullable); + var comboEv = new ComboAttackPerformedEvent(puller.Owner, pullable.Owner, puller.Owner, ComboAttackType.Grab); + RaiseLocalEvent(puller.Owner, comboEv); + Dirty(pullable); Dirty(puller); @@ -1003,51 +990,50 @@ public sealed class PullingSystem : EntitySystem if (puller.Comp.GrabVirtualItemStageCount.TryGetValue(puller.Comp.GrabStage, out var count)) newVirtualItemsCount += count; - if (virtualItemsCount != newVirtualItemsCount) + if (virtualItemsCount == newVirtualItemsCount) + return true; + var delta = newVirtualItemsCount - virtualItemsCount; + + // Adding new virtual items + if (delta > 0) { - var delta = newVirtualItemsCount - virtualItemsCount; - - // Adding new virtual items - if (delta > 0) + for (var i = 0; i < delta; i++) { - for (var i = 0; i < delta; i++) + var emptyHand = _handsSystem.TryGetEmptyHand(puller, out _); + if (!emptyHand) { - var emptyHand = _handsSystem.TryGetEmptyHand(puller, out _); - if (!emptyHand) - { - if (_netManager.IsServer) - _popup.PopupEntity(Loc.GetString("popup-grab-need-hand"), puller, puller, PopupType.Medium); + if (_netManager.IsServer) + _popup.PopupEntity(Loc.GetString("popup-grab-need-hand"), puller, puller, PopupType.Medium); - return false; - } - - if (!_virtualSystem.TrySpawnVirtualItemInHand(pullable, puller.Owner, out var item, true)) - { - // I'm lazy write client code - if (_netManager.IsServer) - _popup.PopupEntity(Loc.GetString("popup-grab-need-hand"), puller, puller, PopupType.Medium); - - return false; - } - - puller.Comp.GrabVirtualItems.Add(item.Value); + return false; } - } - if (delta < 0) - { - for (var i = 0; i < Math.Abs(delta); i++) + if (!_virtualSystem.TrySpawnVirtualItemInHand(pullable, puller.Owner, out var item, true)) { - if (i >= puller.Comp.GrabVirtualItems.Count) - break; + // I'm lazy write client code + if (_netManager.IsServer) + _popup.PopupEntity(Loc.GetString("popup-grab-need-hand"), puller, puller, PopupType.Medium); - var item = puller.Comp.GrabVirtualItems[i]; - puller.Comp.GrabVirtualItems.Remove(item); - QueueDel(item); + return false; } + + puller.Comp.GrabVirtualItems.Add(item.Value); } } + if (delta >= 0) + return true; + for (var i = 0; i < Math.Abs(delta); i++) + { + if (i >= puller.Comp.GrabVirtualItems.Count) + break; + + var item = puller.Comp.GrabVirtualItems[i]; + puller.Comp.GrabVirtualItems.Remove(item); + if(TryComp(item, out var virtualItemComponent)) + _virtualSystem.DeleteVirtualItem((item,virtualItemComponent), puller); + } + return true; } @@ -1067,7 +1053,7 @@ public sealed class PullingSystem : EntitySystem if (_random.Prob(pullable.Comp.GrabEscapeChance)) return true; - pullable.Comp.NextEscapeAttempt = _timing.CurTime.Add(TimeSpan.FromSeconds(1)); + pullable.Comp.NextEscapeAttempt = _timing.CurTime.Add(TimeSpan.FromSeconds(3)); Dirty(pullable.Owner, pullable.Comp); return false; } @@ -1115,6 +1101,7 @@ public sealed class PullingSystem : EntitySystem pullable.Comp.NextEscapeAttempt = _timing.CurTime.Add(TimeSpan.FromSeconds(1f)); Dirty(pullable); + Dirty(puller); if (!ignoreCombatMode && _combatMode.IsInCombatMode(puller.Owner)) { @@ -1148,6 +1135,4 @@ public enum GrabStageDirection Decrease, } -// Goobstation - Grab Intent - // Goobstation diff --git a/Content.Shared/Throwing/ThrowingSystem.cs b/Content.Shared/Throwing/ThrowingSystem.cs index 56bbf4c2bf..aaa902eb44 100644 --- a/Content.Shared/Throwing/ThrowingSystem.cs +++ b/Content.Shared/Throwing/ThrowingSystem.cs @@ -155,6 +155,7 @@ public sealed class ThrowingSystem : EntitySystem { Thrower = user, Animate = animated, + }; // if not given, get the default friction value for distance calculation diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs index b4cb220841..7a6f563cb1 100644 --- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs +++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs @@ -1,6 +1,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; +using Content.Shared._Goobstation.MartialArts.Events; // Goobstation - Martial Arts using Content.Shared._White; using Content.Shared.ActionBlocker; using Content.Shared.Administration.Logs; @@ -524,6 +525,8 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem var modifiedDamage = DamageSpecifier.ApplyModifierSets(damage + hitEvent.BonusDamage + attackedEvent.BonusDamage, hitEvent.ModifiersList); var damageResult = Damageable.TryChangeDamage(target, modifiedDamage, origin:user, ignoreResistances: resistanceBypass, partMultiplier: component.ClickPartDamageMultiplier); + var comboEv = new ComboAttackPerformedEvent(user, target.Value, meleeUid, ComboAttackType.Harm); + RaiseLocalEvent(user, comboEv); if (damageResult is {Empty: false}) { @@ -691,6 +694,9 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem var damageResult = Damageable.TryChangeDamage(entity, modifiedDamage, origin: user, partMultiplier: component.HeavyPartDamageMultiplier); + var comboEv = new ComboAttackPerformedEvent(user, entity, meleeUid, ComboAttackType.HarmLight); + RaiseLocalEvent(user, comboEv); + if (damageResult != null && damageResult.GetTotal() > FixedPoint2.Zero) { // If the target has stamina and is taking blunt damage, they should also take stamina damage based on their blunt to stamina factor @@ -809,6 +815,9 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem return false; } + var comboEv = new ComboAttackPerformedEvent(user, target.Value, meleeUid, ComboAttackType.Disarm); + RaiseLocalEvent(user, comboEv); + if (!TryComp(user, out var combatMode) || combatMode.CanDisarm == false) // WWDP { diff --git a/Content.Shared/_EE/Supermatter/Components/SupermatterComponent.cs b/Content.Shared/_EE/Supermatter/Components/SupermatterComponent.cs index e40fe87ba5..5db4e6da42 100644 --- a/Content.Shared/_EE/Supermatter/Components/SupermatterComponent.cs +++ b/Content.Shared/_EE/Supermatter/Components/SupermatterComponent.cs @@ -19,7 +19,7 @@ public sealed partial class SupermatterComponent : Component /// The SM will only cycle if activated. /// [DataField] - public bool Activated = true; + public bool Activated = false; /// /// The current status of the singularity, used for alert sounds and the monitoring console diff --git a/Content.Shared/_Goobstation/CCVars/CCVars.Goob.cs b/Content.Shared/_Goobstation/CCVar/CCVars.Goob.cs similarity index 100% rename from Content.Shared/_Goobstation/CCVars/CCVars.Goob.cs rename to Content.Shared/_Goobstation/CCVar/CCVars.Goob.cs diff --git a/Content.Shared/_Goobstation/MartialArts/ComboPrototype.cs b/Content.Shared/_Goobstation/MartialArts/ComboPrototype.cs new file mode 100644 index 0000000000..9f1b4e6b8a --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/ComboPrototype.cs @@ -0,0 +1,70 @@ +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Goobstation.MartialArts.Events; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._Goobstation.MartialArts; + +[Prototype("combo")] +[Serializable, NetSerializable, DataDefinition] +public sealed partial class ComboPrototype : IPrototype +{ + [IdDataField] public string ID { get; private set; } = default!; + + [DataField(required: true)] + public MartialArtsForms MartialArtsForm; + + [DataField("attacks", required: true)] + public List AttackTypes = new(); + + //[DataField("weapon")] // Will be done later + //public string? WeaponProtoId; + [DataField("event", required: true)] + public object? ResultEvent; + + /// + /// How much extra damage should this move do on perform? + /// + [DataField] + public int ExtraDamage; + + /// + /// Stun time in seconds + /// + [DataField] + public int ParalyzeTime; + + /// + /// How much stamina damage should this move do on perform. + /// + [DataField] + public float StaminaDamage; + + /// + /// Blunt, Slash, etc. + /// + [DataField] + public string DamageType = "Blunt"; + + /// + /// How fast people are thrown on combo + /// + [DataField] + public float ThrownSpeed = 7f; + + /// + /// Name of the move + /// + [DataField(required: true)] + public string Name = string.Empty; + +} + +[Prototype("comboList")] +public sealed partial class ComboListPrototype : IPrototype +{ + [IdDataField] public string ID { get; private init; } = default!; + + [DataField( required: true)] + public List> Combos = new(); +} diff --git a/Content.Shared/_Goobstation/MartialArts/Components/CanPerformComboComponent.cs b/Content.Shared/_Goobstation/MartialArts/Components/CanPerformComboComponent.cs new file mode 100644 index 0000000000..0d9e74e896 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Components/CanPerformComboComponent.cs @@ -0,0 +1,30 @@ +using Content.Shared._Goobstation.MartialArts.Events; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._Goobstation.MartialArts.Components; +[RegisterComponent] +[NetworkedComponent] +public sealed partial class CanPerformComboComponent : Component +{ + [DataField] + public EntityUid? CurrentTarget; + + [DataField] + public ProtoId BeingPerformed; + + [DataField] + public List LastAttacks = new(); + + [DataField] + public List AllowedCombos = new(); + + [DataField] + public List> RoundstartCombos = new(); + + [DataField] + public TimeSpan ResetTime = TimeSpan.Zero; + + [DataField] + public int ConsecutiveGnashes = 0; +} diff --git a/Content.Shared/_Goobstation/MartialArts/Components/GrabStagesOverrideComponent.cs b/Content.Shared/_Goobstation/MartialArts/Components/GrabStagesOverrideComponent.cs new file mode 100644 index 0000000000..5874c3a611 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Components/GrabStagesOverrideComponent.cs @@ -0,0 +1,12 @@ +using Content.Shared.Movement.Pulling.Systems; + +namespace Content.Shared._Goobstation.MartialArts.Components; + +/// +/// Base component for martial arts that override the normal grab stages. +/// Allows martial arts to start at more advanced grab stages like Hard grabs. +/// +public abstract partial class GrabStagesOverrideComponent : Component +{ + public GrabStage StartingStage = GrabStage.Hard; +} diff --git a/Content.Shared/_Goobstation/MartialArts/Components/GrantMartialArtKnowledgeComponent.cs b/Content.Shared/_Goobstation/MartialArts/Components/GrantMartialArtKnowledgeComponent.cs new file mode 100644 index 0000000000..271dea730a --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Components/GrantMartialArtKnowledgeComponent.cs @@ -0,0 +1,44 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._Goobstation.MartialArts.Components; + +public abstract partial class GrantMartialArtKnowledgeComponent : Component +{ + [DataField] + public bool Used; + + [DataField] + public virtual MartialArtsForms MartialArtsForm { get; set; } = MartialArtsForms.CloseQuartersCombat; +} + +[RegisterComponent] +public sealed partial class GrantCqcComponent : GrantMartialArtKnowledgeComponent +{ + [DataField] + public bool IsBlocked; +} + +[RegisterComponent] +public sealed partial class GrantCorporateJudoComponent : GrantMartialArtKnowledgeComponent +{ + [DataField] + public override MartialArtsForms MartialArtsForm { get; set; } = MartialArtsForms.CorporateJudo; +} + +[RegisterComponent] +public sealed partial class GrantSleepingCarpComponent : GrantMartialArtKnowledgeComponent +{ + [DataField] + public override MartialArtsForms MartialArtsForm { get; set; } = MartialArtsForms.SleepingCarp; + + [DataField] + public int Stage = 1; + + public TimeSpan UseAgainTime = TimeSpan.Zero; + + [DataField] + public int MaxUseDelay = 90; + + [DataField] + public int MinUseDelay = 30; +} diff --git a/Content.Shared/_Goobstation/MartialArts/Components/KravMagaComponents.cs b/Content.Shared/_Goobstation/MartialArts/Components/KravMagaComponents.cs new file mode 100644 index 0000000000..a4e1465475 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Components/KravMagaComponents.cs @@ -0,0 +1,78 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._Goobstation.MartialArts.Components; + +/// +/// This is used for... +/// +[RegisterComponent] +public sealed partial class KravMagaActionComponent : Component +{ + [DataField] + public KravMagaMoves Configuration; + + [DataField] + public string Name; + + [DataField] + public float StaminaDamage; + + [DataField] + public int EffectTime; +} + +[RegisterComponent] +public sealed partial class KravMagaComponent : GrabStagesOverrideComponent +{ + [DataField] + public KravMagaMoves? SelectedMove; + + [DataField] + public KravMagaActionComponent? SelectedMoveComp; + + public readonly List BaseKravMagaMoves = new() + { + "ActionLegSweep", + "ActionNeckChop", + "ActionLungPunch", + }; + + public readonly List KravMagaMoveEntities = new() + { + }; + + [DataField] + public int BaseDamage = 5; + + [DataField] + public int DownedDamageModifier = 2; +} +/// +/// Tracks when an entity is silenced through Krav Maga techniques. +/// Prevents the affected entity from using voice-activated abilities or speaking. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class KravMagaSilencedComponent : Component +{ + [DataField] + public TimeSpan SilencedTime = TimeSpan.Zero; +} + +/// +/// Tracks when an entity's breathing is blocked through Krav Maga techniques. +/// May cause suffocation damage over time when integrated with respiration systems. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class KravMagaBlockedBreathingComponent : Component +{ + [DataField] + public TimeSpan BlockedTime = TimeSpan.Zero; +} + +public enum KravMagaMoves +{ + LegSweep, + NeckChop, + LungPunch, +} diff --git a/Content.Shared/_Goobstation/MartialArts/Components/MartialArtsComponents.cs b/Content.Shared/_Goobstation/MartialArts/Components/MartialArtsComponents.cs new file mode 100644 index 0000000000..d15dd16815 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Components/MartialArtsComponents.cs @@ -0,0 +1,61 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._Goobstation.MartialArts.Components; + +[RegisterComponent] +public sealed partial class MartialArtBlockedComponent : Component +{ + [DataField] + public MartialArtsForms Form; +} + +[RegisterComponent] +[NetworkedComponent] +[AutoGenerateComponentState] +public sealed partial class MartialArtsKnowledgeComponent : GrabStagesOverrideComponent +{ + [DataField] + [AutoNetworkedField] + public MartialArtsForms MartialArtsForm = MartialArtsForms.CloseQuartersCombat; + + [DataField] + [AutoNetworkedField] + public int MinRandomDamageModifier; + + [DataField] + [AutoNetworkedField] + public int MaxRandomDamageModifier = 5; + + [DataField] + [AutoNetworkedField] + public FixedPoint2 BaseDamageModifier; + + [DataField] + [AutoNetworkedField] + public bool RandomDamageModifier; + + [DataField] + [AutoNetworkedField] + public ProtoId RoundstartCombos = "CQCMoves"; + + [DataField] + [AutoNetworkedField] + public bool Blocked = false; + + [DataField] + [AutoNetworkedField] + public List RandomSayings = []; + + [DataField] + [AutoNetworkedField] + public List RandomSayingsDowned = []; +} + +public enum MartialArtsForms +{ + CorporateJudo, + CloseQuartersCombat, + SleepingCarp, +} diff --git a/Content.Shared/_Goobstation/MartialArts/Events/CQCEvents.cs b/Content.Shared/_Goobstation/MartialArts/Events/CQCEvents.cs new file mode 100644 index 0000000000..d4af6bbc18 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Events/CQCEvents.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Goobstation.MartialArts.Events; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class CqcSlamPerformedEvent : EntityEventArgs; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class CqcKickPerformedEvent : EntityEventArgs; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class CqcRestrainPerformedEvent : EntityEventArgs; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class CqcPressurePerformedEvent : EntityEventArgs; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class CqcConsecutivePerformedEvent : EntityEventArgs; diff --git a/Content.Shared/_Goobstation/MartialArts/Events/ComboAttackPerformedEvent.cs b/Content.Shared/_Goobstation/MartialArts/Events/ComboAttackPerformedEvent.cs new file mode 100644 index 0000000000..435180c5dc --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Events/ComboAttackPerformedEvent.cs @@ -0,0 +1,30 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Goobstation.MartialArts.Events; + +/// +/// Raised when a martial arts combo attack is performed. Contains information about +/// the performer, target, weapon used, and the type of combo attack. +/// +public sealed class ComboAttackPerformedEvent( + EntityUid performer, + EntityUid target, + EntityUid weapon, + ComboAttackType type) + : CancellableEntityEventArgs +{ + public EntityUid Performer { get; } = performer; + public EntityUid Target { get; } = target; + public EntityUid Weapon { get; } = weapon; + public ComboAttackType Type { get; } = type; +} + +[Serializable,NetSerializable] +public enum ComboAttackType : byte +{ + Harm, + HarmLight, + Disarm, + Grab, + Hug, +} diff --git a/Content.Shared/_Goobstation/MartialArts/Events/ComboBeingPerformedEvent.cs b/Content.Shared/_Goobstation/MartialArts/Events/ComboBeingPerformedEvent.cs new file mode 100644 index 0000000000..10f1033d05 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Events/ComboBeingPerformedEvent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._Goobstation.MartialArts.Events; + +[Serializable,NetSerializable] +public sealed class ComboBeingPerformedEvent(ProtoId protoId) : EntityEventArgs +{ + public ProtoId ProtoId = protoId; +} diff --git a/Content.Shared/_Goobstation/MartialArts/Events/JudoEvents.cs b/Content.Shared/_Goobstation/MartialArts/Events/JudoEvents.cs new file mode 100644 index 0000000000..e41ad52835 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Events/JudoEvents.cs @@ -0,0 +1,16 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Goobstation.MartialArts.Events; +[Serializable, NetSerializable, DataDefinition] +public sealed partial class JudoThrowPerformedEvent : EntityEventArgs; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class JudoEyePokePerformedEvent : EntityEventArgs; + + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class JudoArmbarPerformedEvent : EntityEventArgs; + + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class JudoGoldenBlastPerformedEvent : EntityEventArgs; diff --git a/Content.Shared/_Goobstation/MartialArts/Events/KravMagaActionEvent.cs b/Content.Shared/_Goobstation/MartialArts/Events/KravMagaActionEvent.cs new file mode 100644 index 0000000000..4c3c20a094 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Events/KravMagaActionEvent.cs @@ -0,0 +1,10 @@ +using Content.Shared.Actions; + +namespace Content.Shared._Goobstation.MartialArts.Events; + +/// +/// This handles selecting your krav maga action +/// +public sealed partial class KravMagaActionEvent : InstantActionEvent +{ +} diff --git a/Content.Shared/_Goobstation/MartialArts/Events/SleepingCarpEvents.cs b/Content.Shared/_Goobstation/MartialArts/Events/SleepingCarpEvents.cs new file mode 100644 index 0000000000..3b89c210aa --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/Events/SleepingCarpEvents.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Goobstation.MartialArts.Events; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class SleepingCarpGnashingTeethPerformedEvent : EntityEventArgs; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class SleepingCarpKneeHaulPerformedEvent : EntityEventArgs; + +[Serializable, NetSerializable, DataDefinition] +public sealed partial class SleepingCarpCrashingWavesPerformedEvent : EntityEventArgs; + +[Serializable,NetSerializable] +public sealed class SleepingCarpSaying(LocId saying) : EntityEventArgs +{ + public LocId Saying = saying; +}; diff --git a/Content.Shared/_Goobstation/MartialArts/MartialArtPrototype.cs b/Content.Shared/_Goobstation/MartialArts/MartialArtPrototype.cs new file mode 100644 index 0000000000..2500452d6e --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/MartialArtPrototype.cs @@ -0,0 +1,36 @@ +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; + +namespace Content.Shared._Goobstation.MartialArts; + +[Prototype("martialArt")] +public sealed class MartialArtPrototype : IPrototype +{ + [IdDataField] + public string ID { get; private init; } = default!; + + [DataField] + public MartialArtsForms MartialArtsForm = MartialArtsForms.CloseQuartersCombat; + + [DataField] + public int MinRandomDamageModifier; + + [DataField] + public int MaxRandomDamageModifier = 5; + + [DataField] + public FixedPoint2 BaseDamageModifier; + + [DataField] + public bool RandomDamageModifier; + + [DataField] + public ProtoId RoundstartCombos = "CQCMoves"; + + [DataField] + public List RandomSayings = []; + + [DataField] + public List RandomSayingsDowned = []; +} diff --git a/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CQC.cs b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CQC.cs new file mode 100644 index 0000000000..8cfe8f7a1b --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CQC.cs @@ -0,0 +1,186 @@ +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Goobstation.MartialArts.Events; +using Content.Shared._Shitmed.Targeting; +using Content.Shared.Bed.Sleep; +using Content.Shared.Damage.Components; +using Content.Shared.Examine; +using Content.Shared.IdentityManagement; +using Content.Shared.Interaction.Events; +using Content.Shared.Mobs.Components; +using Content.Shared.Movement.Pulling.Components; +using Robust.Shared.Audio; + +namespace Content.Shared._Goobstation.MartialArts; + +public partial class SharedMartialArtsSystem +{ + private void InitializeCqc() + { + SubscribeLocalEvent(OnCQCSlam); + SubscribeLocalEvent(OnCQCKick); + SubscribeLocalEvent(OnCQCRestrain); + SubscribeLocalEvent(OnCQCPressure); + SubscribeLocalEvent(OnCQCConsecutive); + SubscribeLocalEvent(OnCQCAttackPerformed); + + SubscribeLocalEvent(OnGrantCQCUse); + SubscribeLocalEvent(OnMapInitEvent); + SubscribeLocalEvent(OnGrantCQCExamine); + } + + + #region Generic Methods + + private void OnMapInitEvent(Entity ent, ref MapInitEvent args) + { + if (!HasComp(ent)) + return; + + if (!TryGrant(ent.Comp, ent)) + return; + + if (TryComp(ent, out var knowledge)) + knowledge.Blocked = true; + } + + private void OnGrantCQCUse(Entity ent, ref UseInHandEvent args) + { + if (!_netManager.IsServer) + return; + + if (ent.Comp.Used) + { + _popupSystem.PopupEntity(Loc.GetString("cqc-fail-used", ("manual", Identity.Entity(ent, EntityManager))), + args.User, + args.User); + return; + } + + if (!TryGrant(ent.Comp, args.User)) + return; + _popupSystem.PopupEntity(Loc.GetString("cqc-success-learned"), args.User, args.User); + ent.Comp.Used = true; + } + + private void OnGrantCQCExamine(Entity ent, ref ExaminedEvent args) + { + if (ent.Comp.Used) + args.PushMarkup(Loc.GetString("cqc-manual-used", ("manual", Identity.Entity(ent, EntityManager)))); + } + + private void OnCQCAttackPerformed(Entity ent, ref ComboAttackPerformedEvent args) + { + if (!TryComp(ent, out var knowledgeComponent)) + return; + + if (knowledgeComponent.MartialArtsForm != MartialArtsForms.CloseQuartersCombat) + return; + + if(knowledgeComponent.Blocked) + return; + + switch (args.Type) + { + case ComboAttackType.Disarm: + _stamina.TakeStaminaDamage(args.Target, 25f); + break; + case ComboAttackType.Harm: + if (!TryComp(ent, out var standing) + || !standing.Active) + return; + _stun.TryKnockdown(args.Target, TimeSpan.FromSeconds(5), true); + _standingState.Stand(ent); + break; + } + + + } + + #endregion + + #region Combo Methods + + private void OnCQCSlam(Entity ent, ref CqcSlamPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out var downed) + || downed) + return; + + DoDamage(ent, target, proto.DamageType, proto.ExtraDamage, out _); + _stun.TryKnockdown(target, TimeSpan.FromSeconds(proto.ParalyzeTime), true); + if (TryComp(target, out var pullable)) + _pulling.TryStopPull(target, pullable, ent, true); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit3.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + private void OnCQCKick(Entity ent, ref CqcKickPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out var downed) + || !downed) + return; + + if (TryComp(target, out var stamina) && stamina.Critical) + { + _status.TryAddStatusEffect(target, "ForcedSleep", TimeSpan.FromSeconds(10), true); + } + + DoDamage(ent, target, proto.DamageType, proto.ExtraDamage, out var damage, TargetBodyPart.Head); + _stamina.TakeStaminaDamage(target, proto.StaminaDamage, source: ent); + + var mapPos = _transform.GetMapCoordinates(ent).Position; + var hitPos = _transform.GetMapCoordinates(target).Position; + var dir = hitPos - mapPos; + dir *= 1f / dir.Length(); + if (TryComp(target, out var pullable)) + _pulling.TryStopPull(target, pullable, ent, true); + _grabThrowing.Throw(target, ent, dir, proto.ThrownSpeed, proto.StaminaDamage / 2, damage); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit2.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + private void OnCQCRestrain(Entity ent, ref CqcRestrainPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out _)) + return; + + _stun.TryKnockdown(target, TimeSpan.FromSeconds(proto.ParalyzeTime), true); + _stamina.TakeStaminaDamage(target, proto.StaminaDamage, source: ent); + } + + private void OnCQCPressure(Entity ent, ref CqcPressurePerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out _)) + return; + + _stamina.TakeStaminaDamage(target, proto.StaminaDamage, source: ent); + if (!_hands.TryGetActiveItem(target, out var activeItem)) + return; + if(!_hands.TryDrop(target, activeItem.Value)) + return; + if (!_hands.TryGetEmptyHand(target, out var emptyHand)) + return; + if(!_hands.TryPickupAnyHand(ent, activeItem.Value)) + return; + _hands.SetActiveHand(ent, emptyHand); + ComboPopup(ent, target, proto.Name); + } + + private void OnCQCConsecutive(Entity ent, ref CqcConsecutivePerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out _)) + return; + + DoDamage(ent, target, proto.DamageType, proto.ExtraDamage, out _); + _stamina.TakeStaminaDamage(target, proto.StaminaDamage, source: ent); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit1.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + #endregion +} diff --git a/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CanPerformCombo.cs b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CanPerformCombo.cs new file mode 100644 index 0000000000..313a61a116 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CanPerformCombo.cs @@ -0,0 +1,78 @@ +using System.Linq; +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Goobstation.MartialArts.Events; +using Content.Shared.Mobs.Components; +using Robust.Shared.Prototypes; + +namespace Content.Shared._Goobstation.MartialArts; + +/// +/// This handles determining if a combo was performed. +/// +public partial class SharedMartialArtsSystem +{ + private void InitializeCanPerformCombo() + { + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnAttackPerformed); + SubscribeLocalEvent(OnComboBeingPerformed); + } + + private void OnMapInit(EntityUid uid, CanPerformComboComponent component, MapInitEvent args) + { + foreach (var item in component.RoundstartCombos) + { + component.AllowedCombos.Add(_proto.Index(item)); + } + } + + private void OnAttackPerformed(EntityUid uid, CanPerformComboComponent component, ComboAttackPerformedEvent args) + { + if (!HasComp(args.Target)) + return; + + if (component.CurrentTarget != null && args.Target != component.CurrentTarget.Value) + { + component.LastAttacks.Clear(); + } + + if (args.Weapon != uid) + { + component.LastAttacks.Clear(); + return; + } + + component.CurrentTarget = args.Target; + component.ResetTime = _timing.CurTime + TimeSpan.FromSeconds(4); + component.LastAttacks.Add(args.Type); + CheckCombo(uid, component); + } + + private void CheckCombo(EntityUid uid, CanPerformComboComponent comp) + { + + foreach (var proto in comp.AllowedCombos) + { + var sum = comp.LastAttacks.Count - proto.AttackTypes.Count; + if (sum < 0) + continue; + + var list = comp.LastAttacks.GetRange(sum, proto.AttackTypes.Count).AsEnumerable(); + var attackList = proto.AttackTypes.AsEnumerable(); + + if (!list.SequenceEqual(attackList) || proto.ResultEvent == null) + continue; + var beingPerformedEv = new ComboBeingPerformedEvent(proto.ID); + var ev = proto.ResultEvent; + RaiseLocalEvent(uid, beingPerformedEv); + RaiseLocalEvent(uid, ev); + comp.LastAttacks.Clear(); + break; + } + } + private void OnComboBeingPerformed(Entity ent, ref ComboBeingPerformedEvent args) + { + ent.Comp.BeingPerformed = args.ProtoId; + Dirty(ent, ent.Comp); + } +} diff --git a/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CorporateJudo.cs b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CorporateJudo.cs new file mode 100644 index 0000000000..15c7c0e4ec --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.CorporateJudo.cs @@ -0,0 +1,134 @@ +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Goobstation.MartialArts.Events; +using Content.Shared.Clothing; +using Content.Shared.Damage; +using Content.Shared.Eye.Blinding.Components; +using Content.Shared.Movement.Pulling.Components; +using Content.Shared.StatusEffect; +using Robust.Shared.Audio; + +namespace Content.Shared._Goobstation.MartialArts; + +public partial class SharedMartialArtsSystem +{ + private void InitializeCorporateJudo() + { + SubscribeLocalEvent(OnJudoThrow); + SubscribeLocalEvent(OnJudoEyepoke); + SubscribeLocalEvent(OnJudoArmbar); + + SubscribeLocalEvent(OnGrantCorporateJudo); + SubscribeLocalEvent(OnRemoveCorporateJudo); + //SubscribeLocalEvent(OnJudoGoldenBlast); -- rework + // Wheel throw + // Discombobulate + } + + #region Generic Methods + + private void OnGrantCorporateJudo(Entity ent, ref ClothingGotEquippedEvent args) + { + if (!_netManager.IsServer) + return; + + var user = args.Wearer; + TryGrant(ent.Comp, user); + } + + private void OnRemoveCorporateJudo(Entity ent, ref ClothingGotUnequippedEvent args) + { + var user = args.Wearer; + if (!TryComp(user, out var martialArtsKnowledge)) + return; + + if (martialArtsKnowledge.MartialArtsForm != MartialArtsForms.CorporateJudo) + return; + + RemComp(user); + RemComp(user); + } + + #endregion + + #region Combo Methods + + private void OnJudoThrow(Entity ent, ref JudoThrowPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out var downed) + || downed) + return; + + _stun.TryKnockdown(target, TimeSpan.FromSeconds(proto.ParalyzeTime), false); + _stamina.TakeStaminaDamage(target, proto.StaminaDamage); + if (TryComp(target, out var pullable)) + _pulling.TryStopPull(target, pullable, ent, true); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit3.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + private void OnJudoEyepoke(Entity ent, ref JudoEyePokePerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out _)) + return; + + if (!TryComp(target, out StatusEffectsComponent? status)) + return; + + _status.TryAddStatusEffect(target, + "TemporaryBlindness", + TimeSpan.FromSeconds(2), + true, + status); + _status.TryAddStatusEffect(target, + "BlurryVision", + TimeSpan.FromSeconds(5), + false, + status); + DoDamage(ent, target, proto.DamageType, proto.ExtraDamage, out _); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit3.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + private void OnJudoArmbar(Entity ent, ref JudoArmbarPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out var downed)) + return; + + switch (downed) + { + case false: + var item = _hands.GetActiveItem(target); + if (item != null) + _hands.TryDrop(target, item.Value); + break; + case true: + _stamina.TakeStaminaDamage(target, proto.StaminaDamage); + _stun.TryKnockdown(target, TimeSpan.FromSeconds(proto.ParalyzeTime), false); + break; + } + + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit3.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + /* Pending Implement + private void OnJudoGoldenBlast(Entity ent, ref JudoGoldenBlastPerformedEvent args) + { + if (!TryUseMartialArt(ent, MartialArtsForms.CorporateJudo, out var target, out var downed)) + return; + + if (downed) + return; + + _stun.TryParalyze(target, TimeSpan.FromSeconds(30), false); + if (TryComp(target, out var pullable)) + _pulling.TryStopPull(target, pullable, ent, true); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit3.ogg"), target); + } + */ + + #endregion +} diff --git a/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.KravMaga.cs b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.KravMaga.cs new file mode 100644 index 0000000000..148ac30737 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.KravMaga.cs @@ -0,0 +1,109 @@ +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Goobstation.MartialArts.Events; +using Content.Shared.Damage; +using Content.Shared.Damage.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Weapons.Melee.Events; + +namespace Content.Shared._Goobstation.MartialArts; + +/// +/// This handles... +/// +public abstract partial class SharedMartialArtsSystem +{ + private void InitializeKravMaga() + { + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnKravMagaAction); + SubscribeLocalEvent(OnMeleeHitEvent); + SubscribeLocalEvent(OnKravMagaShutdown); + } + + private void OnMeleeHitEvent(Entity ent, ref MeleeHitEvent args) + { + if (args.HitEntities.Count <= 0) + return; + + foreach (var hitEntity in args.HitEntities) + { + if (!HasComp(hitEntity)) + continue; + if (!TryComp(hitEntity, out var isDowned)) + continue; + + DoKravMaga(ent, hitEntity, isDowned); + } + } + + private void DoKravMaga(Entity ent, EntityUid hitEntity, RequireProjectileTargetComponent requireProjectileTargetComponent) + { + if (ent.Comp.SelectedMoveComp == null) + return; + var moveComp = ent.Comp.SelectedMoveComp; + + switch (ent.Comp.SelectedMove) + { + case KravMagaMoves.LegSweep: + if(_netManager.IsClient) + return; + _stun.TryParalyze(hitEntity, TimeSpan.FromSeconds(4), true); + break; + case KravMagaMoves.NeckChop: + var comp = EnsureComp(hitEntity); + comp.SilencedTime = _timing.CurTime + TimeSpan.FromSeconds(moveComp.EffectTime); + break; + case KravMagaMoves.LungPunch: + _stamina.TakeStaminaDamage(hitEntity, moveComp.StaminaDamage); + var blockedBreathingComponent = EnsureComp(hitEntity); + blockedBreathingComponent.BlockedTime = _timing.CurTime + TimeSpan.FromSeconds(moveComp.EffectTime); + break; + case null: + var damage = ent.Comp.BaseDamage; + if (requireProjectileTargetComponent.Active) + damage *= ent.Comp.DownedDamageModifier; + + DoDamage(ent.Owner, hitEntity, "Blunt", damage, out _); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + ent.Comp.SelectedMove = null; + ent.Comp.SelectedMoveComp = null; + } + + private void OnKravMagaAction(Entity ent, ref KravMagaActionEvent args) + { + var actionEnt = args.Action.Owner; + if (!TryComp(actionEnt, out var kravActionComp)) + return; + + _popupSystem.PopupClient(Loc.GetString("krav-maga-ready", ("action", kravActionComp.Name)), ent, ent); + ent.Comp.SelectedMove = kravActionComp.Configuration; + ent.Comp.SelectedMoveComp = kravActionComp; + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + if (HasComp(ent)) + return; + foreach (var actionId in ent.Comp.BaseKravMagaMoves) + { + var actions = _actions.AddAction(ent, actionId); + if (actions != null) + ent.Comp.KravMagaMoveEntities.Add(actions.Value); + } + } + + private void OnKravMagaShutdown(Entity ent, ref ComponentShutdown args) + { + if (!TryComp(ent, out var kravMaga)) + return; + + foreach (var action in ent.Comp.KravMagaMoveEntities) + { + _actions.RemoveAction(action); + } + } +} diff --git a/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.SleepingCarp.cs b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.SleepingCarp.cs new file mode 100644 index 0000000000..ea17daa5bd --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.SleepingCarp.cs @@ -0,0 +1,155 @@ +using System.Linq; +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Goobstation.MartialArts.Events; +using Content.Shared.Damage; +using Content.Shared.Damage.Components; +using Content.Shared.Interaction.Events; +using Content.Shared.Movement.Pulling.Components; +using Content.Shared.Popups; +using Content.Shared.Weapons.Reflect; +using Robust.Shared.Audio; + +namespace Content.Shared._Goobstation.MartialArts; + +public partial class SharedMartialArtsSystem +{ + private void InitializeSleepingCarp() + { + SubscribeLocalEvent(OnSleepingCarpGnashing); + SubscribeLocalEvent(OnSleepingCarpKneeHaul); + SubscribeLocalEvent(OnSleepingCarpCrashingWaves); + + SubscribeLocalEvent(OnGrantSleepingCarp); + } + + #region Generic Methods + + private void OnGrantSleepingCarp(Entity ent, ref UseInHandEvent args) + { + if (!_netManager.IsServer) + return; + + if (ent.Comp.Used) + return; + if (ent.Comp.UseAgainTime == TimeSpan.Zero) + { + CarpScrollDelay(ent, args.User); + return; + } + + if (_timing.CurTime < ent.Comp.UseAgainTime) + { + _popupSystem.PopupEntity( + Loc.GetString("carp-scroll-waiting"), + ent, + args.User, + PopupType.MediumCaution); + return; + } + + switch (ent.Comp.Stage) + { + case < 3: + CarpScrollDelay(ent, args.User); + break; + case >= 3: + if (!TryGrant(ent.Comp, args.User)) + return; + var userReflect = EnsureComp(args.User); + userReflect.ReflectProb = 1; + userReflect.Spread = 60; + ent.Comp.Used = true; + _popupSystem.PopupEntity( + Loc.GetString("carp-scroll-complete"), + ent, + args.User, + PopupType.LargeCaution); + return; + } + } + + private void CarpScrollDelay(Entity ent, EntityUid user) + { + var time = _random.Next(ent.Comp.MinUseDelay, ent.Comp.MaxUseDelay); + ent.Comp.UseAgainTime = _timing.CurTime + TimeSpan.FromSeconds(time); + ent.Comp.Stage++; + _popupSystem.PopupEntity( + Loc.GetString("carp-scroll-advance"), + ent, + user, + PopupType.Medium); + } + + #endregion + + #region Combo Methods + + private void OnSleepingCarpGnashing(Entity ent, + ref SleepingCarpGnashingTeethPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out _)) + return; + + if (!TryComp(ent.Owner, out var knowledgeComponent)) + return; + DoDamage(ent, target, proto.DamageType, proto.ExtraDamage + ent.Comp.ConsecutiveGnashes * 5, out _); + ent.Comp.ConsecutiveGnashes++; + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit1.ogg"), target); + if (TryComp(target, out var standing) + && !standing.Active) + { + var saying = + knowledgeComponent.RandomSayings.ElementAt( + _random.Next(knowledgeComponent.RandomSayings.Count)); + var ev = new SleepingCarpSaying(saying); + RaiseLocalEvent(ent, ev); + } + else + { + var saying = + knowledgeComponent.RandomSayingsDowned.ElementAt( + _random.Next(knowledgeComponent.RandomSayingsDowned.Count)); + var ev = new SleepingCarpSaying(saying); + RaiseLocalEvent(ent, ev); + } + } + + private void OnSleepingCarpKneeHaul(Entity ent, + ref SleepingCarpKneeHaulPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out var downed) + || downed) + return; + + DoDamage(ent, target, proto.DamageType, proto.ExtraDamage, out _); + _stamina.TakeStaminaDamage(target, proto.StaminaDamage); + _stun.TryParalyze(target, TimeSpan.FromSeconds(proto.ParalyzeTime), true); + if (TryComp(target, out var pullable)) + _pulling.TryStopPull(target, pullable, ent, true); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit3.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + private void OnSleepingCarpCrashingWaves(Entity ent, + ref SleepingCarpCrashingWavesPerformedEvent args) + { + if (!_proto.TryIndex(ent.Comp.BeingPerformed, out var proto) + || !TryUseMartialArt(ent, proto.MartialArtsForm, out var target, out var downed) + || downed) + return; + + DoDamage(ent, target, proto.DamageType, proto.ExtraDamage, out var damage); + var mapPos = _transform.GetMapCoordinates(ent).Position; + var hitPos = _transform.GetMapCoordinates(target).Position; + var dir = hitPos - mapPos; + if (TryComp(target, out var pullable)) + _pulling.TryStopPull(target, pullable, ent, true); + _grabThrowing.Throw(target, ent, dir, proto.ThrownSpeed, proto.StaminaDamage / 2, damage); + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/genhit2.ogg"), target); + ComboPopup(ent, target, proto.Name); + } + + #endregion +} diff --git a/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.cs b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.cs new file mode 100644 index 0000000000..46a8a7a737 --- /dev/null +++ b/Content.Shared/_Goobstation/MartialArts/SharedMartialArtsSystem.cs @@ -0,0 +1,287 @@ +using Content.Shared._Goobstation.MartialArts.Components; +using Content.Shared._Shitmed.Targeting; +using Content.Shared._White.Grab; +using Content.Shared.Actions; +using Content.Shared.Damage; +using Content.Shared.Damage.Components; +using Content.Shared.Damage.Systems; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.IdentityManagement; +using Content.Shared.Movement.Pulling.Events; +using Content.Shared.Movement.Pulling.Systems; +using Content.Shared.Popups; +using Content.Shared.Speech; +using Content.Shared.Standing; +using Content.Shared.StatusEffect; +using Content.Shared.Stunnable; +using Content.Shared.Weapons.Melee; +using Content.Shared.Weapons.Melee.Events; +using Content.Shared.Weapons.Ranged.Events; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared._Goobstation.MartialArts; + +/// +/// Handles most of Martial Arts Systems. +/// +public abstract partial class SharedMartialArtsSystem : EntitySystem +{ + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly PullingSystem _pulling = default!; + [Dependency] private readonly StatusEffectsSystem _status = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly StaminaSystem _stamina = default!; + [Dependency] private readonly GrabThrownSystem _grabThrowing = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly SharedActionsSystem _actions = default!; + [Dependency] private readonly INetManager _netManager = default!; + [Dependency] private readonly StandingStateSystem _standingState = default!; + + public override void Initialize() + { + base.Initialize(); + InitializeKravMaga(); + InitializeSleepingCarp(); + InitializeCqc(); + InitializeCorporateJudo(); + InitializeCanPerformCombo(); + + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(CheckGrabStageOverride); + SubscribeLocalEvent(OnMeleeHit); + SubscribeLocalEvent(OnShotAttempt); + SubscribeLocalEvent(OnSilencedSpeakAttempt); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out _, out var comp)) + { + if (_timing.CurTime < comp.ResetTime || comp.LastAttacks.Count <= 0) + continue; + comp.LastAttacks.Clear(); + comp.ConsecutiveGnashes = 0; + } + + var kravSilencedQuery = EntityQueryEnumerator(); + while (kravSilencedQuery.MoveNext(out var ent, out var comp)) + { + if (_timing.CurTime < comp.SilencedTime) + continue; + RemComp(ent); + } + + var kravBlockedQuery = EntityQueryEnumerator(); + while (kravBlockedQuery.MoveNext(out var ent, out var comp)) + { + if (_timing.CurTime < comp.BlockedTime) + continue; + RemComp(ent); + } + } + + #region Event Methods + + private void OnMeleeHit(Entity ent, ref MeleeHitEvent args) + { + if (args.Handled) + return; + + if (!ent.Comp.RandomDamageModifier) + return; + + var randomDamage = _random.Next(ent.Comp.MinRandomDamageModifier, ent.Comp.MaxRandomDamageModifier); + var bonusDamageSpec = new DamageSpecifier(); + bonusDamageSpec.DamageDict.Add("Blunt", randomDamage); + args.BonusDamage += bonusDamageSpec; + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + if(TryComp(ent, out var comboComponent)) + comboComponent.AllowedCombos.Clear(); + } + + private void CheckGrabStageOverride(EntityUid uid, T component, CheckGrabOverridesEvent args) + where T : GrabStagesOverrideComponent + { + if (args.Stage == GrabStage.Soft) + args.Stage = component.StartingStage; + } + + private void OnSilencedSpeakAttempt(Entity ent, ref SpeakAttemptEvent args) + { + _popupSystem.PopupEntity(Loc.GetString("popup-grabbed-cant-speak"), + ent, + ent); // You cant speak while someone is choking you + args.Cancel(); + } + + private void OnShotAttempt(Entity ent, ref ShotAttemptedEvent args) + { + if (ent.Comp.MartialArtsForm != MartialArtsForms.SleepingCarp) + return; + _popupSystem.PopupClient(Loc.GetString("gun-disabled"), ent, ent); + args.Cancel(); + } + + private void ComboPopup(EntityUid user, EntityUid target, string comboName) + { + if (!_netManager.IsServer) + return; + var userName = Identity.Entity(user, EntityManager); + var targetName = Identity.Entity(target, EntityManager); + _popupSystem.PopupEntity(Loc.GetString("martial-arts-action-sender", + ("name", targetName), + ("move", comboName)), + user, + user); + _popupSystem.PopupEntity(Loc.GetString("martial-arts-action-reciever", + ("name", userName), + ("move", comboName)), + target, + target); + } + + #endregion + + #region Helper Methods + + private bool TryGrant(GrantMartialArtKnowledgeComponent comp, EntityUid user) + { + if (!_netManager.IsServer || MetaData(user).EntityLifeStage >= EntityLifeStage.Terminating) + return false; + + if (HasComp(user)) + { + _popupSystem.PopupEntity(Loc.GetString("cqc-fail-knowanother"), user, user); + return false; + } + + if (!HasComp(user)) + { + var canPerformComboComponent = EnsureComp(user); + var martialArtsKnowledgeComponent = EnsureComp(user); + LoadPrototype(user, martialArtsKnowledgeComponent, comp.MartialArtsForm); + martialArtsKnowledgeComponent.Blocked = false; + if (TryComp(user, out var meleeWeaponComponent)) + { + var newDamage = new DamageSpecifier(); + newDamage.DamageDict.Add("Blunt", martialArtsKnowledgeComponent.BaseDamageModifier); + meleeWeaponComponent.Damage += newDamage; + } + Dirty(user, canPerformComboComponent); + return true; + } + + if (!TryComp(user, out var cqc)) + { + _popupSystem.PopupEntity(Loc.GetString("cqc-fail-knowanother"), user, user); + return false; + } + + if (cqc.Blocked && comp.MartialArtsForm == MartialArtsForms.CloseQuartersCombat) + { + _popupSystem.PopupEntity(Loc.GetString("cqc-success-unblocked"), user, user); + cqc.Blocked = false; + comp.Used = true; + return false; + } + + _popupSystem.PopupEntity(Loc.GetString("cqc-fail-already"), user, user); + return false; + } + + private void LoadCombos(ProtoId list, CanPerformComboComponent combo) + { + combo.AllowedCombos.Clear(); + if (!_proto.TryIndex(list, out var comboListPrototype)) + return; + foreach (var item in comboListPrototype.Combos) + { + combo.AllowedCombos.Add(_proto.Index(item)); + } + } + + private void LoadPrototype(EntityUid uid, MartialArtsKnowledgeComponent component, MartialArtsForms name) + { + // just know i hate this and i probably could grab info from the prototype directly from protomanager i was being stupid + // when i originally wrote the code for this clearly. + var combo = EnsureComp(uid); + if (!_proto.TryIndex(name.ToString(), out var martialArtsPrototype)) + return; + component.MartialArtsForm = martialArtsPrototype.MartialArtsForm; + component.RoundstartCombos = martialArtsPrototype.RoundstartCombos; + component.MinRandomDamageModifier = martialArtsPrototype.MinRandomDamageModifier; + component.MaxRandomDamageModifier = martialArtsPrototype.MaxRandomDamageModifier; + component.RandomDamageModifier = martialArtsPrototype.RandomDamageModifier; + component.RandomSayings = martialArtsPrototype.RandomSayings; + component.RandomSayingsDowned = martialArtsPrototype.RandomSayingsDowned; + LoadCombos(martialArtsPrototype.RoundstartCombos, combo); + } + + private bool TryUseMartialArt(Entity ent, + MartialArtsForms form, + out EntityUid target, + out bool downed) + { + target = EntityUid.Invalid; + downed = false; + + if (ent.Comp.CurrentTarget == null) + return false; + + if (!TryComp(ent, out var knowledgeComponent)) + return false; + + if (!TryComp(ent.Comp.CurrentTarget, out var isDowned)) + return false; + + downed = isDowned.Active; + target = ent.Comp.CurrentTarget.Value; + + if (knowledgeComponent.MartialArtsForm == form && !knowledgeComponent.Blocked) + { + return true; + } + + foreach (var entInRange in _lookup.GetEntitiesInRange(ent, 8f)) + { + if (!TryPrototype(entInRange, out var proto) || proto.ID != "DefaultStationBeaconKitchen" || !knowledgeComponent.Blocked) + continue; + return true; + } + + return false; + } + + private void DoDamage(EntityUid ent, + EntityUid target, + string damageType, + int damageAmount, + out DamageSpecifier damage, + TargetBodyPart? targetBodyPart = null) + { + damage = new DamageSpecifier(); + if(!TryComp(ent, out var targetingComponent)) + return; + damage.DamageDict.Add(damageType, damageAmount); + _damageable.TryChangeDamage(target, damage, origin: ent, targetPart: targetBodyPart ?? targetingComponent.Target); + } + + #endregion +} diff --git a/Content.Shared/_Goobstation/TableSlam/PostTabledComponent.cs b/Content.Shared/_Goobstation/TableSlam/PostTabledComponent.cs new file mode 100644 index 0000000000..97cd0ca9ae --- /dev/null +++ b/Content.Shared/_Goobstation/TableSlam/PostTabledComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._Goobstation.TableSlam; + +/// +/// This is used for... +/// +[RegisterComponent] +public sealed partial class PostTabledComponent : Component +{ + [DataField] + public TimeSpan PostTabledShovableTime = TimeSpan.Zero; + + [DataField] + public float ParalyzeChance = 0.35f; +} diff --git a/Content.Shared/_Goobstation/TableSlam/TableSlamSystem.cs b/Content.Shared/_Goobstation/TableSlam/TableSlamSystem.cs new file mode 100644 index 0000000000..a262233517 --- /dev/null +++ b/Content.Shared/_Goobstation/TableSlam/TableSlamSystem.cs @@ -0,0 +1,157 @@ +using System.Linq; +using Content.Shared.Contests; +using Content.Shared._Shitmed.Targeting; +using Content.Shared.Actions.Events; +using Content.Shared.Climbing.Components; +using Content.Shared.CombatMode; +using Content.Shared.Coordinates; +using Content.Shared.Damage; +using Content.Shared.Damage.Events; +using Content.Shared.Damage.Systems; +using Content.Shared.FixedPoint; +using Content.Shared.Interaction; +using Content.Shared.Movement.Pulling.Components; +using Content.Shared.Movement.Pulling.Systems; +using Content.Shared.Standing; +using Content.Shared.StatusEffect; +using Content.Shared.Stunnable; +using Content.Shared.Throwing; +using Content.Shared.Weapons.Melee; +using Content.Shared.Weapons.Melee.Events; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Events; +using Robust.Shared.Physics.Systems; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared._Goobstation.TableSlam; + +/// +/// This handles... +/// +public sealed class TableSlamSystem : EntitySystem +{ + [Dependency] private readonly PullingSystem _pullingSystem = default!; + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly StandingStateSystem _standing = default!; + [Dependency] private readonly ThrowingSystem _throwingSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly StaminaSystem _staminaSystem = default!; + [Dependency] private readonly SharedStunSystem _stunSystem = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly ContestsSystem _contestsSystem = default!; + [Dependency] private readonly IRobustRandom _random = default!; + /// + public override void Initialize() + { + SubscribeLocalEvent(OnMeleeHit); + SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnDisarmAttemptEvent); + } + + private void OnDisarmAttemptEvent(Entity ent, ref DisarmAttemptEvent args) + { + if(!_random.Prob(ent.Comp.ParalyzeChance)) + return; + + _stunSystem.TryParalyze(ent, TimeSpan.FromSeconds(3), false); + RemComp(ent); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + var tabledQuery = EntityQueryEnumerator(); + while (tabledQuery.MoveNext(out var uid, out var comp)) + { + if (_gameTiming.CurTime >= comp.PostTabledShovableTime) + RemComp(uid); + } + } + + private void OnMeleeHit(Entity ent, ref MeleeHitEvent args) + { + if (ent.Comp.GrabStage < GrabStage.Suffocate + || ent.Comp.Pulling == null) + return; + + if(!TryComp(ent.Comp.Pulling, out var pullableComponent)) + return; + + if (args.Direction != null) + return; + if (args.HitEntities.Count is > 1 or 0) + return; + + var target = args.HitEntities.ElementAt(0); + if (!HasComp(target)) // checks if its a table. + return; + + var massContest = _contestsSystem.MassContest(ent, ent.Comp.Pulling.Value); + var attemptChance = Math.Clamp(1 * massContest, 0, 1); + var attemptRoundedToNearestQuarter = Math.Round(attemptChance * 4, MidpointRounding.ToEven) / 4; + if(_random.Prob((float) attemptRoundedToNearestQuarter)) // base chance to table slam someone is 1 if your mass ratio is less than 1 then your going to have a harder time slamming somebody. + TryTableSlam((ent.Comp.Pulling.Value, pullableComponent), ent, target); + } + + public void TryTableSlam(Entity ent, Entity pullerEnt, EntityUid tableUid) + { + if(!_transformSystem.InRange(ent.Owner.ToCoordinates(), tableUid.ToCoordinates(), 2f )) + return; + + _standing.Down(ent); + + _pullingSystem.TryStopPull(ent, ent.Comp, pullerEnt, ignoreGrab: true); + _throwingSystem.TryThrow(ent, tableUid.ToCoordinates() , ent.Comp.BasedTabledForceSpeed, animated: false, doSpin: false); + pullerEnt.Comp.NextStageChange = _gameTiming.CurTime.Add(TimeSpan.FromSeconds(3)); // prevent table slamming spam + + if (TryComp(ent, out var tableableComp)) // Checks that the entity being tabled has the TableableComponent + { + tableableComp.BeingTabled = true; + } + else + { + tableableComp = EnsureComp(ent); // Adds the Tableable Component if it doesn't exist + tableableComp.BeingTabled = true; // This shit is so code :skull: + } + } + + private void OnStartCollide(Entity ent, ref StartCollideEvent args) + { + if(!ent.Comp.BeingTabled) + return; + + if (!HasComp(args.OtherEntity)) + return; + + var modifierOnGlassBreak = 1; + if (TryComp(args.OtherEntity, out var glassTableComponent)) + { + _damageableSystem.TryChangeDamage(args.OtherEntity, glassTableComponent.TableDamage, origin: ent, targetPart: TargetBodyPart.Torso); + _damageableSystem.TryChangeDamage(args.OtherEntity, glassTableComponent.ClimberDamage, origin: ent); + modifierOnGlassBreak = 2; + } + else + { + _damageableSystem.TryChangeDamage(ent, + new DamageSpecifier() + { + DamageDict = new Dictionary { { "Blunt", ent.Comp.TabledDamage } }, + }, + targetPart: TargetBodyPart.Torso); + _damageableSystem.TryChangeDamage(ent, + new DamageSpecifier() + { + DamageDict = new Dictionary { { "Blunt", ent.Comp.TabledDamage } }, + }); + } + + _staminaSystem.TakeStaminaDamage(ent, ent.Comp.TabledStaminaDamage); + _stunSystem.TryKnockdown(ent, TimeSpan.FromSeconds(3 * modifierOnGlassBreak), false); + var postTabledComponent = EnsureComp(ent); + postTabledComponent.PostTabledShovableTime = _gameTiming.CurTime.Add(TimeSpan.FromSeconds(3)); + ent.Comp.BeingTabled = false; + + //_audioSystem.PlayPvs("/Audio/Effects/thudswoosh.ogg", uid); + } +} diff --git a/Content.Shared/_Goobstation/TableSlam/TableableComponent.cs b/Content.Shared/_Goobstation/TableSlam/TableableComponent.cs new file mode 100644 index 0000000000..4692c1e60f --- /dev/null +++ b/Content.Shared/_Goobstation/TableSlam/TableableComponent.cs @@ -0,0 +1,32 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._Goobstation.TableSlam; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class TableableComponent : Component +{ + /// + /// If this pullable being tabled. + /// + [DataField, AutoNetworkedField] + public bool BeingTabled = false; + + /// + /// Constant for tabling throw math + /// + [DataField] + public float BasedTabledForceSpeed = 5f; + + /// + /// Stamina damage. taken on tabled + /// + [DataField] + public float TabledStaminaDamage = 40f; + + /// + /// Damage taken on being tabled. + /// + [DataField] + public float TabledDamage = 5f; + // Goobstation end +} \ No newline at end of file diff --git a/Content.Shared/_White/Grab/GrabThrownComponent.cs b/Content.Shared/_White/Grab/GrabThrownComponent.cs index a7eadf7e92..d3dbe6c588 100644 --- a/Content.Shared/_White/Grab/GrabThrownComponent.cs +++ b/Content.Shared/_White/Grab/GrabThrownComponent.cs @@ -8,8 +8,6 @@ public sealed partial class GrabThrownComponent : Component { public DamageSpecifier? DamageOnCollide; - public DamageSpecifier? WallDamageOnCollide; - public float? StaminaDamageOnCollide; public List IgnoreEntity = new(); diff --git a/Content.Shared/_White/Grab/GrabThrownSystem.cs b/Content.Shared/_White/Grab/GrabThrownSystem.cs index 1dbce9db2d..b64ff85899 100644 --- a/Content.Shared/_White/Grab/GrabThrownSystem.cs +++ b/Content.Shared/_White/Grab/GrabThrownSystem.cs @@ -8,6 +8,7 @@ using Robust.Shared.Player; using System.Numerics; using Content.Shared._White; using Content.Shared.Standing; +using Robust.Shared.Physics.Components; namespace Content.Shared._White.Grab; @@ -33,33 +34,39 @@ public sealed class GrabThrownSystem : EntitySystem if (_netMan.IsClient) // To avoid effect spam return; - if (!HasComp(ent.Owner)) + if (!HasComp(ent)) { - RemComp(ent.Owner); + RemComp(ent); return; } if (ent.Comp.IgnoreEntity.Contains(args.OtherEntity)) return; - if (!HasComp(ent.Owner)) - RemComp(ent.Owner); + if (!HasComp(ent)) + RemComp(ent); + + if(!TryComp(ent, out var physicsComponent)) + return; ent.Comp.IgnoreEntity.Add(args.OtherEntity); - var speed = args.OurBody.LinearVelocity.Length(); + var velocity = args.OurBody.LinearVelocity.Length(); + var velocitySquared = args.OurBody.LinearVelocity.LengthSquared(); + var mass = physicsComponent.Mass; + var kineticEnergy = 0.5f * mass * velocitySquared; if (ent.Comp.StaminaDamageOnCollide != null) - _stamina.TakeStaminaDamage(ent.Owner, ent.Comp.StaminaDamageOnCollide.Value); + _stamina.TakeStaminaDamage(ent, ent.Comp.StaminaDamageOnCollide.Value); - var damageScale = speed; - - if (ent.Comp.WallDamageOnCollide != null) - _damageable.TryChangeDamage(args.OtherEntity, ent.Comp.WallDamageOnCollide * damageScale); + var kineticEnergyDamage = new DamageSpecifier(); + kineticEnergyDamage.DamageDict.Add("Blunt", 1); + kineticEnergyDamage *= Math.Floor(kineticEnergy / 100) / 2 + 3; + _damageable.TryChangeDamage(args.OtherEntity, kineticEnergyDamage); _layingDown.TryLieDown(args.OtherEntity, behavior: DropHeldItemsBehavior.AlwaysDrop); - _color.RaiseEffect(Color.Red, new List() { ent.Owner }, Filter.Pvs(ent.Owner, entityManager: EntityManager)); + _color.RaiseEffect(Color.Red, new List() { ent }, Filter.Pvs(ent, entityManager: EntityManager)); } private void OnStopThrow(EntityUid uid, GrabThrownComponent comp, StopThrowEvent args) @@ -77,26 +84,23 @@ public sealed class GrabThrownSystem : EntitySystem /// Entity to throw /// Entity that throws /// Direction + /// How fast you fly when thrown /// Stamina damage on collide /// Damage to entity on collide - /// Damage to wall or anything that was hit by entity public void Throw( EntityUid uid, EntityUid thrower, Vector2 vector, float grabThrownSpeed, float? staminaDamage = null, - DamageSpecifier? damageToUid = null, - DamageSpecifier? damageToWall = null) + DamageSpecifier? damageToUid = null) { - _layingDown.TryLieDown(uid, behavior: DropHeldItemsBehavior.AlwaysDrop); - var comp = EnsureComp(uid); comp.StaminaDamageOnCollide = staminaDamage; - comp.DamageOnCollide = damageToUid; - comp.WallDamageOnCollide = damageToWall; comp.IgnoreEntity.Add(thrower); + comp.DamageOnCollide = damageToUid; + _layingDown.TryLieDown(uid, behavior: DropHeldItemsBehavior.AlwaysDrop); _throwing.TryThrow(uid, vector, grabThrownSpeed, animated: false); } } diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b600909ef4..35e8de6f1c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -12402,3 +12402,83 @@ Entries: id: 6911 time: '2025-03-07T22:45:53.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/1885 +- author: Eagle + changes: + - type: Add + message: >- + Table slamming. Harm a table when you have someone harm choked, see what + happens. + - type: Tweak + message: >- + Grab throw damage to other entities is now based on the thrown entities + kinetic energy. No more mouse wrecking balls. + - type: Tweak + message: You can now escape from a soft grab by just walking away. + - type: Tweak + message: You can no longer grab someone else while your being grabbed. + - type: Tweak + message: Mass now effects grab release attempts. + id: 6912 + time: '2025-03-08T19:49:02.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1889 +- author: VMSolidus + changes: + - type: Add + message: >- + Added a variety of "Shuttle Spawning Airlocks" for mappers to use, which + can make it so that shuttles like the Cargo Shuttle, Pathfinder, etc. + Spawn already docked to the station. + id: 6913 + time: '2025-03-08T20:11:39.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1890 +- author: Timfa2112 + changes: + - type: Add + message: >- + Added extra descriptions to the revolutionary manifesto and the civilian + disabler + - type: Fix + message: Fixed extenddescription on flash + id: 6914 + time: '2025-03-08T21:08:39.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1887 +- author: RadsammyT + changes: + - type: Tweak + message: >- + the Ore Processors now process Lead, Copper, and Aluminum instantly, and + is much faster at processing Tungsten + id: 6915 + time: '2025-03-08T21:11:30.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1873 +- author: Eagle + changes: + - type: Add + message: >- + Added Corporate Judo, CQC, Sleeping Carp, and Krav Maga martial arts + with unique abilities. + - type: Add + message: >- + The Chef has been given Close Quarters Cooking in the Kitchen and Bar. + Tiders beware. + id: 6916 + time: '2025-03-09T00:31:51.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1891 +- author: AlgumCorrupto + changes: + - type: Fix + message: >- + Fixed bug of the painted roboticist airlock displaying the windowed + counterpart instead of the standard one. + id: 6917 + time: '2025-03-09T03:19:17.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1899 +- author: SolarisBirb + changes: + - type: Fix + message: SM no longer starts on round start. + - type: Fix + message: SM will no longer delam from spacing unless it's activated. + id: 6918 + time: '2025-03-09T04:45:00.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1901 diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index a7c4702877..037939d486 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 2digitman, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, Acruid, actioninja, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Aerocrux, Aexolott, Aexxie, africalimedrop, afrokada, Agoichi, Ahion, Aidenkrz, Aikakakah, aitorlogedo, ajcm, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, ALMv1, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, angelofallars, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, as334, AsikKEsel, asperger-sind, aspiringlich, aspiringLich, astriloqua, avalon, avghdev, AzzyIsNotHere, BananaFlambe, BasedPugilist, BasedUser, beck-thompson, benev0, BGare, bhespiritu, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blitzthesquishy, bloodrizer, Bloody2372, blueDev2, BlueHNT, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, boogiebogus, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, byondfuckery, c0rigin, c4llv07e, CaasGit, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, CatTheSystem, Centronias, CerberusWolfie, chairbender, Charlese2, chavonadelal, Cheackraze, cheesePizza2, Chief-Engineer, christhirtle, chromiumboy, Chronophylos, Chubbygummibear, CilliePaint, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, CodedCrow, Cohnway, cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, CormosLemming, CrafterKolyan, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, DarkenedSynergy, Darkenson, DawBla, Daxxi3, dch-GH, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DeltaV-Bot, DerbyX, derek, dersheppard, dexlerxd, dffdff2423, dge21, diggy0, digitalic, DinoWattz, DisposableCrewmember42, DJB1gYAPPA, DjfjdfofdjfjD, DocNITE, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, dootythefrooty, Dorragon, Doru991, DoubleRiceEddiedd, DoutorWhite, drakewill-CRL, Drayff, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, Dutch-VanDerLinde, dvir001, dylanstrategie, Dynexust, Easypoller, eclips_e, EctoplasmIsGood, eden077, EEASAS, Efruit, efzapa, ElectroSR, elsie, elthundercloud, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, Erisfiregamer1, ERORR404V1, Errant-4, esguard, estacaoespacialpirata, eugene, Evgencheg, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, Fansana, Feluk6174, fenndragon, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, FirinMaLazors, Fishfish458, fl-oz, Flareguy, FluffiestFloof, FluffMe, FluidRock, flybik, flyingkarii, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, FoxxoTrystan, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FryOfDestiny, FungiFellow, GalacticChimp, gamer3107, Gaxeer, gbasood, gcoremans, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, ghost581x, Git-Nivrak, gituhabu, GlassEclipse, gluesniffler, GNF54, GNUtopia, Golinth, GoodWheatley, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, greggthefather, GreyMario, GTRsound, Guess-My-Name, gusxyz, h3half, Haltell, Hanzdegloker, Hardly3D, harikattar, Hebi, Henry, HerCoyote23, hiucko, Hmeister-fake, Hmeister-real, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, i-justuser-i, iacore, IamVelcroboy, icekot8, icesickleone, Ichaie, iczero, iglov, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, Intoxicating-Innocence, IProduceWidgets, ItsMeThom, Itzbenz, Jackal298, Jackrost, jacksonzck, Jackw2As, jamessimo, janekvap, Jark255, Jaskanbe, JasperJRoth, jerryimmouse, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, JohnGinnane, johnku1, joshepvodka, Jrpl, jukereise, juliangiebel, juniwoofs, justart1m, JustCone14, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, komunre, KonstantinAngelov, koteq, Kr8art, Krunklehorn, Kukutis96513, Kupie, kxvvv, Kyoth25f, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonsfriedrich, lettern, LetterN, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, lizelive, lleftTheDragon, localcc, Lomcastar, lonoferars, LordCarve, LordEclipse, LovelyLophi, luckyshotpictures, LudwigVonChesterfield, Lukasz825700516, Lumminal, lunarcomets, luringens, lvvova1, Lyndomen, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, Mervill, metalgearsloth, mhamsterr, michaelcu, micheel665, Mike32oz, MilenVolf, milon, MilonPL, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, MjrLandWhale, MLGTASTICa, Mnemotechnician, moderatelyaware, mokiros, Moneyl, Monotheonist, Moomoobeef, moony, Morb0, mr-bo-jangles, Mr0maks, MrFippik, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, namespace-Memory, Nannek, NeLepus, neuPanda, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, nok-ko, NonchalantNoob, NoobyLegion, not-gavnaed, notafet, notquitehadouken, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OCOtheOmega, OctoRocket, OldDanceJacket, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Phantom-Lily, PHCodes, Phill101, phunnyguy, pigeonpeas, PilgrimViis, Pill-U, Piras314, Pireax, pissdemon, PixelTheKermit, PJB3005, Plasmaguy, PlasmaRaptor, plinyvic, Plykiya, plyushsune, pofitlo, pointer-to-null, poklj, PolterTzi, PoorMansDreams, potato1234x, PotentiallyTom, ProfanedBane, PROG-MohamedDwidar, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QuietlyWhisper, qwerltaz, Radezolid, RadioMull, Radosvik, Radrark, RadsammyT, Rainbeon, Rainfey, Raitononai, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, Redfire1331, RedFoxIV, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, Remuchi, rene-descartes2021, Renlou, retequizzle, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, Rinkashikachi, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Rosycup, router, RumiTiger, S1ss3l, Saakra, saga3152, Salex08, sam, Samsterious, SaphireLattice, SapphicOverload, sapphirescript, sarahon, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, ShadowCommander, shadowtheprotogen546, shadowwailker, shaeone, shampunj, shariathotpatrol, ShatteredSwords, SignalWalker, siigiil, SimpleStation14, Simyon264, sirdragooon, Sirionaut, SixplyDev, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, SleepyScarecrow, sleepyyapril, Slyfox333, snebl, sniperchance, Snowni, snowsignal, SonicHDC, Sornarok, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, sowelipililimute, SpaceManiac, SpaceRox1244, SpaceyLady, spartak, SpartanKadence, Spatison, SpeltIncorrectyl, spess-empyrean, SphiraI, SplinterGP, spoogemonster, sporekto, Squishy77, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, Stop-Signs, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, suraru, SweptWasTaken, SX-7, Sybil, SYNCHRONIC, Szunti, TadJohnson00, takemysoult, TaralGit, Taran, Tayrtahn, tday93, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGRCdev, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, TherapyGoth, TheShuEd, thevinter, ThunderBear2006, Timemaster99, Timfa2112, timothyteakettle, TimrodDX, tin-man-tim, Tirochora, Titian3, tk-a369, tkdrg, Tmanzxd, tmtmtl30, toasterpm87, Toby222, TokenStyle, Tollhouse, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, tornado-technology, Tornado-Technology, tosatur, TotallyLemon, trashalice, truepaintgit, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, twoducksonnaplane, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, v0idRift, Vaaankas, valentfingerov, Varen, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, VerinSenpai, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, vlados1408, VMSolidus, volotomite, volundr-, Voomra, Vordenburg, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, waylon531, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, WTCWR68, xkreksx, xqzpop7, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, yunii, YuriyKiss, yuriykiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, zelezniciar1, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, Zymem, zzylex +0x6273, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 2digitman, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, Acruid, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Aerocrux, Aexolott, Aexxie, africalimedrop, afrokada, Agoichi, Ahion, Aidenkrz, Aikakakah, aitorlogedo, ajcm, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, alliephante, ALMv1, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, angelofallars, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, as334, AsikKEsel, asperger-sind, aspiringlich, aspiringLich, astriloqua, avalon, avghdev, AzzyIsNotHere, BananaFlambe, BasedPugilist, BasedUser, beck-thompson, benev0, BGare, bhespiritu, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blitzthesquishy, bloodrizer, Bloody2372, blueDev2, BlueHNT, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, boogiebogus, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, byondfuckery, c0rigin, c4llv07e, CaasGit, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, CatTheSystem, Centronias, CerberusWolfie, chairbender, Charlese2, chavonadelal, Cheackraze, cheesePizza2, Chief-Engineer, christhirtle, chromiumboy, Chronophylos, Chubbygummibear, CilliePaint, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, CodedCrow, Cohnway, cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, CormosLemming, CrafterKolyan, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, dan, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, DarkenedSynergy, Darkenson, DawBla, Daxxi3, dch-GH, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DeltaV-Bot, DerbyX, derek, dersheppard, dexlerxd, dffdff2423, dge21, Diggy0, digitalic, DinoWattz, DisposableCrewmember42, DJB1gYAPPA, DjfjdfofdjfjD, DocNITE, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, dootythefrooty, Dorragon, Doru991, DoubleRiceEddiedd, DoutorWhite, drakewill-CRL, Drayff, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, Dutch-VanDerLinde, dvir001, dylanstrategie, Dynexust, Easypoller, eclips_e, EctoplasmIsGood, eden077, EEASAS, Efruit, efzapa, ElectroSR, elsie, elthundercloud, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, Erisfiregamer1, ERORR404V1, Errant-4, esguard, estacaoespacialpirata, eugene, Evgencheg, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, Fansana, Feluk6174, fenndragon, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, FirinMaLazors, Fishfish458, fl-oz, Flareguy, FluffiestFloof, FluffMe, FluidRock, flybik, flyingkarii, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, FoxxoTrystan, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FryOfDestiny, FungiFellow, GalacticChimp, gamer3107, Gaxeer, gbasood, gcoremans, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, ghost581x, Git-Nivrak, gituhabu, GlassEclipse, gluesniffler, GNF54, GNUtopia, Golinth, GoodWheatley, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, greggthefather, GreyMario, GTRsound, Guess-My-Name, gusxyz, h3half, Haltell, Hanzdegloker, Hardly3D, harikattar, Hebi, Henry, HerCoyote23, hiucko, Hmeister-fake, Hmeister-real, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, i-justuser-i, iacore, IamVelcroboy, icekot8, icesickleone, Ichaie, iczero, iglov, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, Intoxicating-Innocence, IProduceWidgets, ItsMeThom, Itzbenz, Jackal298, Jackrost, jacksonzck, Jackw2As, jamessimo, janekvap, Jark255, Jaskanbe, JasperJRoth, jerryimmouse, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, JohnGinnane, johnku1, joshepvodka, Jrpl, jukereise, juliangiebel, juniwoofs, justart1m, JustCone14, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, komunre, KonstantinAngelov, koteq, Kr8art, Krunklehorn, Kukutis96513, Kupie, kxvvv, Kyoth25f, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, larynevespr, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonsfriedrich, LetterN, lettern, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, lizelive, lleftTheDragon, localcc, Lomcastar, lonoferars, LordCarve, LordEclipse, LovelyLophi, luckyshotpictures, LudwigVonChesterfield, Lukasz825700516, Lumminal, lunarcomets, luringens, lvvova1, Lyndomen, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, Mervill, metalgearsloth, mhamsterr, michaelcu, micheel665, Mike32oz, MilenVolf, milon, MilonPL, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, MjrLandWhale, MLGTASTICa, Mnemotechnician, moderatelyaware, mokiros, Moneyl, Monotheonist, Moomoobeef, moony, Morb0, mr-bo-jangles, Mr0maks, MrFippik, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, namespace-Memory, Nannek, NeLepus, neuPanda, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, nok-ko, NonchalantNoob, NoobyLegion, not-gavnaed, notafet, notquitehadouken, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OCOtheOmega, OctoRocket, OldDanceJacket, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Phantom-Lily, PHCodes, Phill101, phunnyguy, pigeonpeas, PilgrimViis, Pill-U, Piras314, Pireax, pissdemon, PixelTheKermit, PJB3005, Plasmaguy, PlasmaRaptor, plinyvic, Plykiya, plyushsune, pofitlo, pointer-to-null, poklj, PolterTzi, PoorMansDreams, potato1234x, PotentiallyTom, ProfanedBane, PROG-MohamedDwidar, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QuietlyWhisper, qwerltaz, Radezolid, RadioMull, Radosvik, Radrark, RadsammyT, Raikyr0, Rainbeon, Rainfey, Raitononai, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, Redfire1331, RedFoxIV, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, Remuchi, rene-descartes2021, Renlou, retequizzle, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, Rinkashikachi, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Rosycup, router, RumiTiger, S1ss3l, Saakra, saga3152, Salex08, sam, Samsterious, SaphireLattice, SapphicOverload, sapphirescript, sarahon, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, ShadowCommander, shadowtheprotogen546, shadowwailker, shaeone, shampunj, shariathotpatrol, ShatteredSwords, SignalWalker, siigiil, SimpleStation14, Simyon264, sirdragooon, Sirionaut, SixplyDev, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, SleepyScarecrow, sleepyyapril, Slyfox333, snebl, sniperchance, Snowni, snowsignal, SonicHDC, Sornarok, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, sowelipililimute, SpaceManiac, SpaceRox1244, SpaceyLady, spartak, SpartanKadence, Spatison, SpeltIncorrectyl, spess-empyrean, SphiraI, SplinterGP, spoogemonster, sporekto, Squishy77, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, Stop-Signs, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, suraru, SweptWasTaken, SX-7, Sybil, SYNCHRONIC, Szunti, TadJohnson00, takemysoult, TaralGit, Taran, Tayrtahn, tday93, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGRCdev, tgrkzus, thatrandomcanadianguy, TheArturZh, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, TherapyGoth, TheShuEd, thevinter, ThunderBear2006, Timemaster99, Timfa2112, timothyteakettle, TimrodDX, tin-man-tim, Tirochora, Titian3, tk-a369, tkdrg, Tmanzxd, tmtmtl30, toasterpm87, Toby222, TokenStyle, Tollhouse, tom-leys, tomasalves8, Tomeno, Tonk-GCR, Tonydatguy, topy, Tornado-Technology, tornado-technology, tosatur, TotallyLemon, trashalice, truepaintgit, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, twoducksonnaplane, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, v0idRift, Vaaankas, valentfingerov, Varen, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, VerinSenpai, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, vlados1408, VMSolidus, volotomite, volundr-, Voomra, Vordenburg, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, waylon531, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, WTCWR68, xkreksx, xqzpop7, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, yunii, yuriykiss, YuriyKiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, zelezniciar1, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, Zymem, zzylex diff --git a/Resources/Locale/en-US/_Goobstation/martial-arts/martial-arts.ftl b/Resources/Locale/en-US/_Goobstation/martial-arts/martial-arts.ftl new file mode 100644 index 0000000000..d898cf23ff --- /dev/null +++ b/Resources/Locale/en-US/_Goobstation/martial-arts/martial-arts.ftl @@ -0,0 +1,44 @@ +cqc-fail-used = {CAPITALIZE(THE($manual))} is already used. +cqc-fail-notself = You can't teach anyone with {CAPITALIZE(THE($manual))}. + +cqc-fail-knowanother = You already know another martial art. +cqc-fail-already = You already know everything about a Martial art. +cqc-success-unblocked = Your CQC skills are not bound to kitchen anymore. +cqc-success-learned = You have learned CQC. + +cqc-manual-used = [color=white]{CAPITALIZE(THE($manual))} looks to be already used.[/color] + +ent-CQCManual = CQC manual + .desc = Looks like a usual book, but contains some secrets inside. + +carp-scroll-waiting = The journey of a thousand miles begins with one step, and the path of wisdom is traveled slowly, one lesson at a time. +carp-scroll-advance = You have taken one step closer to becoming a master of the Way of the Sleeping Carp. +carp-scroll-complete = You are now a master of the Way of the Sleeping Carp. + +carp-saying-huah = HUAH! +carv-saying-hya = HYA! +carp-saying-choo = CHOO! +carp-saying-wuo = WUO! +carp-saying-kya = KYA! +carp-saying-huh = HUH! +carp-saying-hiyoh = HIYOH! +carp-saying-strike = CARP STRIKE! +carp-saying-bite = CARP BITE! + +carp-saying-banzai = BANZAIII! +carp-saying-kiya = KIYAAAA! +carp-saying-omae = OMAE WA MOU SHINDEIRU! +carp-saying-see = YOU CAN'T SEE ME! +carp-saying-time = MY TIME IS NOW!! +carp-saying-cowabunga = COWABUNGA! + +krav-maga-ready = You ready a {$action} + +martial-arts-action-sender = You hit {$name} with {$move} +martial-arts-action-receiver = {$name} hit you with {$move} + +uplink-cqc-name = CQC Manual +uplink-cqc-desc = A manual that teaches a single user tactical Close-Quarters Combat before self-destructing. Does not restrict weapon usage. Your disarms will inflict some stamina damage while making people temporarily slur their words, your grabs will immobilize for a second making it easier to reinforce them, your harm attacks will deal moderate stamina damage, and you will get a set of combos that allow you to efficiently knockdown, disarm or stun your opponent. You can find more information on CQC and its combos here. + +uplink-sleeping-carp-name = Martial Arts Scroll +uplink-sleeping-carp-desc = This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, deflecting ranged weapon fire. Learning this art means you will also refuse to use dishonorable ranged weaponry. Unable to be understood by vampire and changeling agents. diff --git a/Resources/Locale/en-US/_white/objectives/conditions/steal.ftl b/Resources/Locale/en-US/_white/objectives/conditions/steal.ftl deleted file mode 100644 index 5f3bb96986..0000000000 --- a/Resources/Locale/en-US/_white/objectives/conditions/steal.ftl +++ /dev/null @@ -1 +0,0 @@ -steal-target-power-gloves = power gloves diff --git a/Resources/Locale/en-US/extenddescriptions/items/revolutionarymanifesto.ftl b/Resources/Locale/en-US/extenddescriptions/items/revolutionarymanifesto.ftl new file mode 100644 index 0000000000..4d3182f725 --- /dev/null +++ b/Resources/Locale/en-US/extenddescriptions/items/revolutionarymanifesto.ftl @@ -0,0 +1,4 @@ +revolutionarymanifesto-extenddescription-headrevolutionary = I can use this item to convert others to my cause. +revolutionarymanifesto-extenddescription-revolutionary = My revolutionary leader can use this item to convert others to our cause. +revolutionarymanifesto-extenddescription-security = Despite its dangerous ideology, this book is not illegal to possess. +revolutionarymanifesto-extenddescription-mindshield = An affront to all values a righteous Nanotrasen employee should stand for! diff --git a/Resources/Locale/en-US/extenddescriptions/items/weapons/civiliandisabler.ftl b/Resources/Locale/en-US/extenddescriptions/items/weapons/civiliandisabler.ftl new file mode 100644 index 0000000000..95f0e08620 --- /dev/null +++ b/Resources/Locale/en-US/extenddescriptions/items/weapons/civiliandisabler.ftl @@ -0,0 +1 @@ +civiliandisabler-extenddescription-security = This weapon is legal to own and carry without a license on NanoTrasen stations, but may be considered as an accessory equivalent to a weapon if used in a crime. diff --git a/Resources/Locale/ru-RU/_white/object/clothes/gloves.ftl b/Resources/Locale/ru-RU/_white/object/clothes/gloves.ftl deleted file mode 100644 index 22fa1077a9..0000000000 --- a/Resources/Locale/ru-RU/_white/object/clothes/gloves.ftl +++ /dev/null @@ -1,3 +0,0 @@ -ent-ClothingHandsGlovesPowergloveReal = силовые перчатки - .desc = Помни основы CQC. - .suffix = { "Смотритель" } diff --git a/Resources/Locale/ru-RU/_white/objectives/conditions/steal.ftl b/Resources/Locale/ru-RU/_white/objectives/conditions/steal.ftl deleted file mode 100644 index 9414d7035b..0000000000 --- a/Resources/Locale/ru-RU/_white/objectives/conditions/steal.ftl +++ /dev/null @@ -1 +0,0 @@ -steal-target-power-gloves = силовые перчатки diff --git a/Resources/Locale/ru-RU/loadouts/jobs/security.ftl b/Resources/Locale/ru-RU/loadouts/jobs/security.ftl index fe3e4bfc7e..8dced373c8 100644 --- a/Resources/Locale/ru-RU/loadouts/jobs/security.ftl +++ b/Resources/Locale/ru-RU/loadouts/jobs/security.ftl @@ -1,7 +1,6 @@ loadout-description-LoadoutSecurityUniformJumpskirtSenior = A skirt fit for the best of the best. loadout-description-LoadoutSecurityUniformJumpsuitSenior = A suit fit for the best of the best. loadout-description-LoadoutSecurityShoesJackboots = A really nice, heavy, pair of black boots. - # Equipment loadout-name-LoadoutMagazinePistolSpare = pistol magazine (.35 auto, spare) loadout-name-LoadoutSpeedLoaderMagnumSpare = speed loader (.45 magnum, spare) diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml index 5b5e1dde4b..5f2c2e95c2 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml @@ -5,31 +5,31 @@ components: - type: StorageFill contents: - - id: ClothingHandsGlovesPowergloveReal # WWDP, traitor steal objective, to do replace with krav-magas - - id: FlashlightSeclite - - id: WeaponDisabler - prob: 0.3 - - id: ClothingBeltSecurityFilled - - id: Flash - - id: ClothingEyesGlassesSunglasses - - id: ClothingHeadsetAltSecurity - # - id: ClothingHandsGlovesCombat # WWDP, replaced by powergloves - - id: ClothingShoesBootsJack - - id: ClothingOuterCoatWarden - - id: ClothingOuterWinterWarden - - id: RubberStampWarden - - id: DoorRemoteArmory - - id: ClothingOuterHardsuitWarden # WWDP edit - - id: OxygenTankFilled # WWDP edit - - id: HoloprojectorSecurity - - id: ClothingEyesHudSecurity - - id: BoxPDAPrisoner # Delta-V - - id: ClothingShoesBootsWinterWarden #Delta V: Add departmental winter boots - - id: BoxEncryptionKeyPrisoner #Delta-V - - id: BoxPrisonerHeadset - - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! - prob: 0.3 - - id: BoxBodyBagPrisoner # WD + - id: FlashlightSeclite + - id: WeaponDisabler + prob: 0.3 + - id: ClothingBeltSecurityFilled + - id: ClothingHandsGlovesKravMaga # Goobstation - Martial Arts + - id: Flash + - id: ClothingEyesGlassesSunglasses + - id: ClothingHeadsetAltSecurity + - id: ClothingHandsGlovesCombat + - id: ClothingShoesBootsJack + - id: ClothingOuterCoatWarden + - id: ClothingOuterWinterWarden + - id: RubberStampWarden + - id: DoorRemoteArmory + - id: ClothingOuterHardsuitWarden # WWDP edit + - id: OxygenTankFilled # WWDP edit + - id: HoloprojectorSecurity + - id: ClothingEyesHudSecurity + - id: BoxPDAPrisoner # Delta-V + - id: ClothingShoesBootsWinterWarden #Delta V: Add departmental winter boots + - id: BoxEncryptionKeyPrisoner #Delta-V + - id: BoxPrisonerHeadset + - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! + prob: 0.3 + - id: BoxBodyBagPrisoner # WD - type: entity id: LockerWardenFilled @@ -38,29 +38,29 @@ components: - type: StorageFill contents: - - id: ClothingHandsGlovesPowergloveReal # WWDP, traitor steal objective, to do replace with krav-magas - - id: FlashlightSeclite - - id: WeaponDisabler - prob: 0.3 - - id: ClothingBeltSecurityFilled - - id: Flash - - id: ClothingEyesGlassesSunglasses - - id: ClothingHeadsetAltSecurity - # - id: ClothingHandsGlovesCombat # WWDP, replaced by powergloves - - id: ClothingShoesBootsJack - - id: ClothingOuterCoatWarden - - id: ClothingOuterWinterWarden - - id: RubberStampWarden - - id: DoorRemoteArmory - - id: HoloprojectorSecurity - - id: ClothingEyesHudSecurity - - id: BoxPDAPrisoner # Delta-V - - id: ClothingShoesBootsWinterWarden #Delta V: Add departmental winter boots - - id: BoxEncryptionKeyPrisoner #Delta-V - - id: BoxPrisonerHeadset - - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! - prob: 0.3 - - id: BoxBodyBagPrisoner # WD + - id: FlashlightSeclite + - id: WeaponDisabler + prob: 0.3 + - id: ClothingBeltSecurityFilled + - id: ClothingHandsGlovesKravMaga # Goobstation - Martial Arts + - id: Flash + - id: ClothingEyesGlassesSunglasses + - id: ClothingHeadsetAltSecurity + - id: ClothingHandsGlovesCombat + - id: ClothingShoesBootsJack + - id: ClothingOuterCoatWarden + - id: ClothingOuterWinterWarden + - id: RubberStampWarden + - id: DoorRemoteArmory + - id: HoloprojectorSecurity + - id: ClothingEyesHudSecurity + - id: BoxPDAPrisoner # Delta-V + - id: ClothingShoesBootsWinterWarden #Delta V: Add departmental winter boots + - id: BoxEncryptionKeyPrisoner #Delta-V + - id: BoxPrisonerHeadset + - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! + prob: 0.3 + - id: BoxBodyBagPrisoner # WD - type: entity id: LockerSecurityFilled @@ -69,21 +69,24 @@ components: - type: StorageFill contents: - - id: FlashlightSeclite - - id: ClothingUniformJumpsuitSec # WD - Less random bloat - - id: ClothingHeadHelmetBasic - # - id: ClothingHeadHelmetInsulated # Nyanotrasen - Insulative headgear # WWDP - all sec helmets are insulated now - - id: ClothingOuterArmorBasic # WD - plate carrier and stabproof vest replaced back to regular bodyarmor - - id: ClothingBeltSecurityFilled - - id: ClothingEyesGlassesSecurity # WD - SecHuds - - id: ClothingHeadsetSecurity - - id: ClothingHandsGlovesColorBlack - - id: ClothingShoesBootsJack - - id: WeaponDisabler # WD - - id: WeaponMeleeNeedle - prob: 0.1 - - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! - prob: 0.3 + - id: FlashlightSeclite + - id: ClothingUniformJumpsuitSec # WD - Less random bloat + - id: ClothingHeadHelmetBasic + # - id: ClothingHeadHelmetInsulated # Nyanotrasen - Insulative headgear # WWDP - all sec helmets are insulated now + - id: ClothingOuterArmorBasic # WD - plate carrier and stabproof vest replaced back to regular bodyarmor + - id: ClothingBeltSecurityFilled + - id: ClothingBeltCorporateJudo # Goobstation - Martial Arts + - id: Flash + prob: 0.5 + - id: ClothingEyesGlassesSecurity # WD - SecHuds + - id: ClothingHeadsetSecurity + - id: ClothingHandsGlovesColorBlack + - id: ClothingShoesBootsJack + - id: WeaponDisabler # WD + - id: WeaponMeleeNeedle + prob: 0.1 + - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! + prob: 0.3 - type: entity id: LockerBrigmedicFilled @@ -92,37 +95,37 @@ components: - type: StorageFill contents: - - id: ClothingEyesGlassesCorpsman # DeltaV - Corpsman Glasses - - id: WeaponDisabler - - id: TrackingImplanter - amount: 2 -## - id: ClothingOuterHardsuitCombatCorpsman # DeltaV - ClothingOuterHardsuitBrigmedic replaced in favour of corpsman's combat hardsuit; removing from standard filled locker to place in hardsuit filled locker. - - id: BoxSterileMask - - id: ClothingHeadHatBeretCorpsman # DeltaV - ClothingHeadHatBeretBrigmedic replaced in favour of corpsman beret. -## - id: ClothingOuterCoatAMG # DeltaV - removed until I can resprite it or replace it. - - id: ClothingUniformJumpsuitBrigmedic - - id: ClothingUniformJumpskirtBrigmedic -## - id: ClothingUniformJumpskirtOfLife # DeltaV - nah -## prob: 0.1 - - id: HandheldGPSBasic # Delta V - added it for tracking the implant tracker pop up. - - id: MedkitFilled - - id: MedkitCombatFilled - prob: 0.6 - - id: MedkitAdvancedFilled - prob: 0.4 - - id: MedkitOxygenFilled - prob: 0.3 - - id: MedkitBruteFilled - prob: 0.3 - - id: MedkitToxinFilled - prob: 0.3 - - id: MedkitBurnFilled - prob: 0.7 -## - id: ClothingNeckCloakMoth #bzzz Moth-pocalypse # DeltaV - why -## prob: 0.15 - - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! - prob: 0.3 - - id: BoxBodyBagPrisoner # WD + - id: ClothingEyesGlassesCorpsman # DeltaV - Corpsman Glasses + - id: WeaponDisabler + - id: TrackingImplanter + amount: 2 + ## - id: ClothingOuterHardsuitCombatCorpsman # DeltaV - ClothingOuterHardsuitBrigmedic replaced in favour of corpsman's combat hardsuit; removing from standard filled locker to place in hardsuit filled locker. + - id: BoxSterileMask + - id: ClothingHeadHatBeretCorpsman # DeltaV - ClothingHeadHatBeretBrigmedic replaced in favour of corpsman beret. + ## - id: ClothingOuterCoatAMG # DeltaV - removed until I can resprite it or replace it. + - id: ClothingUniformJumpsuitBrigmedic + - id: ClothingUniformJumpskirtBrigmedic + ## - id: ClothingUniformJumpskirtOfLife # DeltaV - nah + ## prob: 0.1 + - id: HandheldGPSBasic # Delta V - added it for tracking the implant tracker pop up. + - id: MedkitFilled + - id: MedkitCombatFilled + prob: 0.6 + - id: MedkitAdvancedFilled + prob: 0.4 + - id: MedkitOxygenFilled + prob: 0.3 + - id: MedkitBruteFilled + prob: 0.3 + - id: MedkitToxinFilled + prob: 0.3 + - id: MedkitBurnFilled + prob: 0.7 + ## - id: ClothingNeckCloakMoth #bzzz Moth-pocalypse # DeltaV - why + ## prob: 0.15 + - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! + prob: 0.3 + - id: BoxBodyBagPrisoner # WD # DeltaV - adding corpsman locker w/ hardsuit @@ -133,31 +136,31 @@ components: - type: StorageFill contents: - - id: ClothingEyesGlassesCorpsman # DeltaV - Corpsman Glasses - - id: WeaponDisabler - - id: TrackingImplanter - amount: 2 - - id: ClothingOuterHardsuitBrigmedic # WWDP edit - - id: OxygenTankFilled # WWDP edit - - id: ClothingUniformJumpsuitBrigmedic - - id: ClothingUniformJumpskirtBrigmedic - - id: HandheldGPSBasic # Added GPS because I just think it should be there tbh. - - id: MedkitFilled - - id: MedkitCombatFilled - prob: 0.6 - - id: MedkitAdvancedFilled - prob: 0.4 - - id: MedkitOxygenFilled - prob: 0.3 - - id: MedkitBruteFilled - prob: 0.3 - - id: MedkitToxinFilled - prob: 0.3 - - id: MedkitBurnFilled - prob: 0.7 - - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! - prob: 0.3 - - id: BoxBodyBagPrisoner # WD + - id: ClothingEyesGlassesCorpsman # DeltaV - Corpsman Glasses + - id: WeaponDisabler + - id: TrackingImplanter + amount: 2 + - id: ClothingOuterHardsuitBrigmedic # WWDP edit + - id: OxygenTankFilled # WWDP edit + - id: ClothingUniformJumpsuitBrigmedic + - id: ClothingUniformJumpskirtBrigmedic + - id: HandheldGPSBasic # Added GPS because I just think it should be there tbh. + - id: MedkitFilled + - id: MedkitCombatFilled + prob: 0.6 + - id: MedkitAdvancedFilled + prob: 0.4 + - id: MedkitOxygenFilled + prob: 0.3 + - id: MedkitBruteFilled + prob: 0.3 + - id: MedkitToxinFilled + prob: 0.3 + - id: MedkitBurnFilled + prob: 0.7 + - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! + prob: 0.3 + - id: BoxBodyBagPrisoner # WD # DeltaV - end addition @@ -168,23 +171,23 @@ components: - type: StorageFill contents: - - id: ClothingEyesHudSecurity - prob: 0.3 - - id: ClothingHeadHatFedoraBrown - - id: ClothingNeckTieDet - - id: ClothingOuterVestDetective - - id: ClothingOuterCoatDetective - - id: FlashlightSeclite - - id: ForensicScanner - - id: LogProbeCartridge - - id: BoxForensicPad - - id: DrinkDetFlask - - id: ClothingHandsGlovesForensic - - id: RubberStampDetective - - id: HoloprojectorSecurity - - id: BoxEvidenceMarkers - - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! - prob: 0.3 + - id: ClothingEyesHudSecurity + prob: 0.3 + - id: ClothingHeadHatFedoraBrown + - id: ClothingNeckTieDet + - id: ClothingOuterVestDetective + - id: ClothingOuterCoatDetective + - id: FlashlightSeclite + - id: ForensicScanner + - id: LogProbeCartridge + - id: BoxForensicPad + - id: DrinkDetFlask + - id: ClothingHandsGlovesForensic + - id: RubberStampDetective + - id: HoloprojectorSecurity + - id: BoxEvidenceMarkers + - id: LunchboxSecurityFilledRandom # Delta-v Lunchboxes! + prob: 0.3 - type: entity id: ClosetBombFilled @@ -193,15 +196,15 @@ components: - type: StorageFill contents: - - id: ClothingHeadHelmetBombSuit - - id: ClothingOuterSuitBomb - # NT is cheap, what can you do... - - id: Wirecutter - prob: 0.9 - - id: Screwdriver - prob: 0.9 - - id: Multitool - prob: 0.5 + - id: ClothingHeadHelmetBombSuit + - id: ClothingOuterSuitBomb + # NT is cheap, what can you do... + - id: Wirecutter + prob: 0.9 + - id: Screwdriver + prob: 0.9 + - id: Multitool + prob: 0.5 - type: entity parent: GunSafe diff --git a/Resources/Prototypes/Entities/Objects/Specific/revolutionary.yml b/Resources/Prototypes/Entities/Objects/Specific/revolutionary.yml index 51b3d631fb..96f6505a2b 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/revolutionary.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/revolutionary.yml @@ -22,6 +22,38 @@ sound: /Audio/SimpleStation14/Items/Handling/book_drop.ogg - type: EmitSoundOnLand sound: /Audio/SimpleStation14/Items/Handling/book_drop.ogg + - type: ExtendDescription + descriptionList: + - description: "revolutionarymanifesto-extenddescription-headrevolutionary" + fontSize: 12 + color: "#880000" + requireDetailRange: false + requirements: + - !type:CharacterAntagonistRequirement + antagonists: + - HeadRev + - description: "revolutionarymanifesto-extenddescription-revolutionary" + fontSize: 12 + color: "#880000" + requireDetailRange: false + requirements: + - !type:CharacterAntagonistRequirement + antagonists: + - Rev + - description: "revolutionarymanifesto-extenddescription-security" + fontSize: 12 + color: "#ff0000" + requireDetailRange: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security + - description: "revolutionarymanifesto-extenddescription-mindshield" + fontSize: 12 + color: "#11aaff" + requireDetailRange: true + requirements: + - !type:CharacterMindshieldRequirement - type: GuideHelp guides: - Revolutionaries diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml index c5d8c3d014..1e9bd4e429 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml @@ -603,6 +603,16 @@ steps: 5 zeroVisible: true - type: Appearance + - type: ExtendDescription + descriptionList: + - description: "civiliandisabler-extenddescription-security" + fontSize: 12 + color: "#ff0000" + requireDetailRange: true + requirements: + - !type:CharacterDepartmentRequirement + departments: + - Security - type: MeleeWeapon damage: types: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/security.yml b/Resources/Prototypes/Entities/Objects/Weapons/security.yml index e0aba41a4b..57dba8e676 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/security.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/security.yml @@ -13,7 +13,7 @@ tags: - Stunbaton - type: Stunbaton - energyPerUse: 50 # WD EDIT + energyPerUse: 50 - type: ItemToggle predictable: false soundActivate: @@ -64,7 +64,7 @@ - type: Appearance - type: GenericVisualizer visuals: - enum.ToggleVisuals.Toggled: + enum.ToggleVisuals.Toggled: enum.ToggleVisuals.Layer: True: {state: stunbaton_on} False: {state: stunbaton_off} @@ -90,6 +90,8 @@ - type: GuideHelp guides: - Security + - type: MartialArtBlocked # Goobstation - Martial Arts + form: CorporateJudo # Goobstation - Martial Arts - type: KnockdownOnHit # WD EDIT - type: entity @@ -139,67 +141,49 @@ id: Flash description: An ultrabright flashbulb with a trigger, which causes the victim to be dazed and lose their eyesight for a moment. Useless when burnt out. components: - - type: Sprite - sprite: Objects/Weapons/Melee/flash.rsi - layers: - - state: flash - map: [ "enum.FlashVisuals.BaseLayer" ] - - state: flashing - map: [ "enum.FlashVisuals.LightLayer" ] - visible: false - shader: unshaded - - type: Flash - - type: ExtendDescription - descriptionList: - - description: "flash-extenddescription-headrevolutionary" - fontSize: 12 - color: "#880000" - requireDetailRange: false - requirements: - - !type:CharacterAntagonistRequirement - antagonists: - - HeadRev - - description: "flash-extenddescription-revolutionary" - fontSize: 12 - color: "#880000" - requireDetailRange: false - requirements: - - !type:CharacterAntagonistRequirement - antagonists: - - Rev - - type: LimitedCharges - maxCharges: 5 - charges: 5 - - type: MeleeWeapon - canBeBlocked: false # WD EDIT - wideAnimationRotation: 180 - damage: - types: - Blunt: 0 # melee weapon to allow flashing individual targets - angle: 10 - - type: Item - size: Small - sprite: Objects/Weapons/Melee/flash.rsi -# - type: DynamicPrice -# price: 40 - - type: ReverseEngineering # Nyano - recipes: - - Flash - - type: StaticPrice - price: 40 - - type: Appearance - - type: GenericVisualizer - visuals: - enum.FlashVisuals.Burnt: - enum.FlashVisuals.BaseLayer: - True: {state: burnt} - enum.FlashVisuals.Flashing: - enum.FlashVisuals.LightLayer: - True: {visible: true} - False: {visible: false} - - type: GuideHelp - guides: - - Security + - type: Sprite + sprite: Objects/Weapons/Melee/flash.rsi + layers: + - state: flash + map: [ "enum.FlashVisuals.BaseLayer" ] + - state: flashing + map: [ "enum.FlashVisuals.LightLayer" ] + visible: false + shader: unshaded + - type: Flash + - type: LimitedCharges + maxCharges: 5 + charges: 5 + - type: MeleeWeapon + canBeBlocked: false # WD EDIT + wideAnimationRotation: 180 + damage: + types: + Blunt: 0 # melee weapon to allow flashing individual targets + angle: 10 + - type: Item + size: Small + sprite: Objects/Weapons/Melee/flash.rsi + # - type: DynamicPrice + # price: 40 + - type: ReverseEngineering # Nyano + recipes: + - Flash + - type: StaticPrice + price: 40 + - type: Appearance + - type: GenericVisualizer + visuals: + enum.FlashVisuals.Burnt: + enum.FlashVisuals.BaseLayer: + True: {state: burnt} + enum.FlashVisuals.Flashing: + enum.FlashVisuals.LightLayer: + True: {visible: true} + False: {visible: false} + - type: GuideHelp + guides: + - Security - type: entity name: flash @@ -207,9 +191,9 @@ suffix: 2 charges id: SciFlash components: - - type: LimitedCharges - maxCharges: 2 - charges: 2 + - type: LimitedCharges + maxCharges: 2 + charges: 2 - type: entity name: portable flasher @@ -217,44 +201,44 @@ id: PortableFlasher description: An ultrabright flashbulb with a proximity trigger, useful for making an area security-only. components: - - type: EmitSoundOnTrigger - sound: - path: /Audio/Weapons/flash.ogg - - type: FlashOnTrigger - range: 3 - - type: TriggerOnProximity - enabled: true - cooldown: 5 - shape: - !type:PhysShapeCircle - radius: 2 - repeating: true - - type: Anchorable - - type: Sprite - sprite: Objects/Weapons/pflash.rsi - layers: - - state: "off" - map: ["enum.ProximityTriggerVisualLayers.Base"] - - type: InteractionOutline - - type: Physics - - type: Fixtures - fixtures: - fix1: - shape: - !type:PhysShapeAabb - bounds: "-0.15,-0.3,0.15,0.3" - mask: - - MachineMask - layer: - - MachineLayer - density: 380 - - type: Appearance - - type: AnimationPlayer - - type: PointLight - energy: 2.0 - radius: 0 - softness: 0 - enabled: true - - type: GuideHelp - guides: - - Security + - type: EmitSoundOnTrigger + sound: + path: /Audio/Weapons/flash.ogg + - type: FlashOnTrigger + range: 3 + - type: TriggerOnProximity + enabled: true + cooldown: 5 + shape: + !type:PhysShapeCircle + radius: 2 + repeating: true + - type: Anchorable + - type: Sprite + sprite: Objects/Weapons/pflash.rsi + layers: + - state: "off" + map: ["enum.ProximityTriggerVisualLayers.Base"] + - type: InteractionOutline + - type: Physics + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.15,-0.3,0.15,0.3" + mask: + - MachineMask + layer: + - MachineLayer + density: 380 + - type: Appearance + - type: AnimationPlayer + - type: PointLight + energy: 2.0 + radius: 0 + softness: 0 + enabled: true + - type: GuideHelp + guides: + - Security diff --git a/Resources/Prototypes/Entities/Structures/Doors/airlock_groups.yml b/Resources/Prototypes/Entities/Structures/Doors/airlock_groups.yml index 9ca751b55d..cf9c04b818 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/airlock_groups.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/airlock_groups.yml @@ -14,7 +14,7 @@ security: Structures/Doors/Airlocks/Standard/security.rsi virology: Structures/Doors/Airlocks/Standard/virology.rsi justice: DeltaV/Structures/Doors/Airlocks/Standard/justice.rsi # Delta V - Add Justice Dept - roboticist: DeltaV/Structures/Doors/Airlocks/Glass/roboticist.rsi #Added Roboticist Role + roboticist: DeltaV/Structures/Doors/Airlocks/Standard/roboticist.rsi # Added Roboticist Role - type: AirlockGroup id: Glass diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index 195070eb22..aadab6e424 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -12,7 +12,6 @@ weights: CaptainIDStealObjective: 1 CMOHyposprayStealObjective: 1 - PowerGlovesStealObjective: 1 # WWDP warden's CQC gloves CMOCrewMonitorStealObjective: 1 RDHardsuitStealObjective: 1 NukeDiskStealObjective: 1 diff --git a/Resources/Prototypes/Recipes/Lathes/sheet.yml b/Resources/Prototypes/Recipes/Lathes/sheet.yml index 7088b84cae..343ec1d01f 100644 --- a/Resources/Prototypes/Recipes/Lathes/sheet.yml +++ b/Resources/Prototypes/Recipes/Lathes/sheet.yml @@ -3,7 +3,7 @@ result: SheetSteel1 applyMaterialDiscount: false miningPoints: 1 - completetime: 0 + completetime: 0.0083 # 0.25 per 30 materials: RawIron: 100 Coal: 30 @@ -20,8 +20,8 @@ id: SheetGlass1 result: SheetGlass1 applyMaterialDiscount: false - miningPoints: 1 - completetime: 0 + miningPoints: 1 # 0.25 per 30 + completetime: 0.0083 materials: RawQuartz: 100 @@ -37,7 +37,7 @@ result: SheetRGlass1 applyMaterialDiscount: false miningPoints: 1 - completetime: 0 + completetime: 0.025 # 0.75 per 30 materials: Glass: 100 Steel: 50 @@ -55,7 +55,7 @@ - type: latheRecipe id: SheetPGlass1 result: SheetPGlass1 - completetime: 0 + completetime: 0.0083 # 0.75 per 30 miningPoints: 16 materials: RawQuartz: 100 @@ -72,7 +72,7 @@ - type: latheRecipe id: SheetRPGlass1 result: SheetRPGlass1 - completetime: 0 + completetime: 0.025 # 0.75 per 30 miningPoints: 16 materials: RawQuartz: 100 @@ -93,7 +93,7 @@ - type: latheRecipe id: SheetPlasma1 result: SheetPlasma1 - completetime: 0 + completetime: 0.0116 # 0.35 per 30 miningPoints: 15 materials: RawPlasma: 100 @@ -108,7 +108,7 @@ - type: latheRecipe id: SheetPlasteel1 result: SheetPlasteel1 - completetime: 0 + completetime: 0.025 # 0.75 per 30 miningPoints: 17 materials: RawPlasma: 100 @@ -134,7 +134,7 @@ - type: latheRecipe id: SheetUGlass1 result: SheetUGlass1 - completetime: 0 + completetime: 0.0083 # 0.25 per 30 miningPoints: 31 materials: RawUranium: 100 @@ -151,7 +151,7 @@ - type: latheRecipe id: SheetRUGlass1 result: SheetRUGlass1 - completetime: 0 + completetime: 0.025 # 0.75 per 30 miningPoints: 31 materials: RawUranium: 100 @@ -193,7 +193,7 @@ - type: latheRecipe id: MaterialDiamond result: MaterialDiamond1 - completetime: 0 + completetime: 0.026 # 0.8 over 30 miningPoints: 50 materials: RawDiamond: 100 @@ -201,7 +201,7 @@ - type: latheRecipe id: SheetUranium1 result: SheetUranium1 - completetime: 0 + completetime: 0.02 # 0.6 seconds for 30 miningPoints: 30 materials: RawUranium: 100 @@ -209,7 +209,7 @@ - type: latheRecipe id: IngotGold1 result: IngotGold1 - completetime: 0 + completetime: 0.016 # 0.5 over 30 miningPoints: 18 materials: RawGold: 100 @@ -217,7 +217,7 @@ - type: latheRecipe id: IngotSilver1 result: IngotSilver1 - completetime: 0 + completetime: 0.013 # 0.4 over 30 miningPoints: 16 materials: RawSilver: 100 @@ -233,7 +233,7 @@ - type: latheRecipe id: MaterialBananium1 result: MaterialBananium1 - completetime: 0 + completetime: 0.1 # 1 over 10 miningPoints: 60 materials: RawBananium: 100 @@ -291,7 +291,7 @@ result: IngotTungsten1 applyMaterialDiscount: false miningPoints: 5 - completetime: 4 + completetime: 0.13 # Or, 4 seconds over 30 ingots. materials: RawTungsten: 100 RawIron: 100 diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml index f4e44be33e..bc3253cd2b 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml @@ -21,6 +21,8 @@ - !type:AddComponentSpecial components: - type: ProfessionalChef #Nyano - End Summary. + - type: GrantCqc # Goobstation - Martial Arts + isBlocked: true # Goobstation - Martial Arts - type: startingGear id: ChefGear diff --git a/Resources/Prototypes/_EE/Entities/Structures/Doors/Airlocks/shuttleAirlocks.yml b/Resources/Prototypes/_EE/Entities/Structures/Doors/Airlocks/shuttleAirlocks.yml new file mode 100644 index 0000000000..981dd814bd --- /dev/null +++ b/Resources/Prototypes/_EE/Entities/Structures/Doors/Airlocks/shuttleAirlocks.yml @@ -0,0 +1,81 @@ +# Unlimited, these are targets for shuttles to dock to. +- type: entity + parent: AirlockGlassShuttle + id: AirlockExternalGlassShuttleCargoShuttle + suffix: External, Cargo, Glass, Docking + components: + - type: PriorityDock + tag: DockCargoShuttle + +- type: entity + parent: AirlockGlassShuttle + id: AirlockExternalGlassShuttleDart + suffix: External, ERT, Glass, Docking + components: + - type: PriorityDock + tag: DockDart + +- type: entity + parent: AirlockSyndicateGlass + id: AirlockSyndicateGlassShuttleInfiltrator + suffix: External, Infiltrator, Glass, Docking + components: + - type: PriorityDock + tag: DockInfiltrator + +- type: entity + parent: AirlockGlassShuttle + id: AirlockExternalGlassShuttlePathfinder + suffix: External, Salvage, Glass, Docking + components: + - type: PriorityDock + tag: DockPathfinder + +- type: entity + parent: AirlockSyndicateGlass + id: AirlockSyndicateGlassShuttleSANDropship + suffix: External, SAN Dropship, Glass, Docking + components: + - type: PriorityDock + tag: DockSANDropship + +# 1 per map, these spawn a shuttle. +- type: entity + parent: AirlockExternalGlassShuttleCargoShuttle + id: AirlockExternalGlassShuttleCargoShuttleFilled + suffix: Cargo Shuttle Spawner, MAX ONE PER MAP + components: + - type: GridFill + path: /Maps/Shuttles/cargo.yml + +- type: entity + parent: AirlockExternalGlassShuttleDart + id: AirlockExternalGlassShuttleDartFilled + suffix: ERT Ship Spawner, MAX ONE PER MAP + components: + - type: GridFill + path: /Maps/Shuttles/dart.yml + +- type: entity + parent: AirlockSyndicateGlassShuttleInfiltrator + id: AirlockSyndicateGlassShuttleInfiltratorFilled + suffix: Infiltrator Ship Spawner, MAX ONE PER MAP + components: + - type: GridFill + path: /Maps/Shuttles/infiltrator.yml + +- type: entity + parent: AirlockExternalGlassShuttlePathfinder + id: AirlockExternalGlassShuttlePathfinderFilled + suffix: Salvage Ship Spawner, MAX ONE PER MAP + components: + - type: GridFill + path: /Maps/Shuttles/pathfinder.yml + +- type: entity + parent: AirlockSyndicateGlassShuttleSANDropship + id: AirlockSyndicateGlassShuttleSANDropshipFilled + suffix: SAN Dropship Spawner, MAX ONE PER MAP + components: + - type: GridFill + path: /Maps/Shuttles/ShuttleEvent/SANDropship.yml diff --git a/Resources/Prototypes/_EE/Tags/tags.yml b/Resources/Prototypes/_EE/Tags/tags.yml new file mode 100644 index 0000000000..54e0ed6186 --- /dev/null +++ b/Resources/Prototypes/_EE/Tags/tags.yml @@ -0,0 +1,14 @@ +- type: Tag + id: DockCargoShuttle + +- type: Tag + id: DockDart + +- type: Tag + id: DockInfiltrator + +- type: Tag + id: DockPathfinder + +- type: Tag + id: DockSANDropship diff --git a/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml b/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml index c8c420f392..3dfb1ce9f4 100644 --- a/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml @@ -37,6 +37,39 @@ tags: - NukeOpsUplink +# Martial Arts +- type: listing + id: UplinkCQCManual + name: uplink-cqc-name + description: uplink-cqc-desc + productEntity: CQCManual + # WD EDIT START + discountCategory: veryRareDiscounts + discountDownTo: + Telecrystal: 3 + cost: + Telecrystal: 12 + # WD EDIT END + categories: + - UplinkDeception + +- type: listing + id: UplinkMysteriousScroll + name: uplink-sleeping-carp-name + description: uplink-sleeping-carp-desc + productEntity: SleepingCarpScroll + # WD EDIT START + discountCategory: veryRareDiscounts + discountDownTo: + Telecrystal: 3 + cost: + Telecrystal: 14 + # WD EDIT END + categories: + - UplinkWeaponry + + +# Misc - type: listing id: UplinkHardsuitCybersunStealth name: uplink-hardsuit-cybersun-stealth-name diff --git a/Resources/Prototypes/_Goobstation/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/_Goobstation/Entities/Clothing/Belt/belts.yml new file mode 100644 index 0000000000..773e9863e9 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Clothing/Belt/belts.yml @@ -0,0 +1,33 @@ +- type: entity + parent: ClothingBeltSecurity + id: ClothingBeltCorporateJudo + name: Corporate Judo Belt + description: Teaches the wearer NT Corporate Judo. + components: + - type: Sprite + sprite: _Goobstation/Clothing/Belt/judobelt.rsi + - type: Clothing + sprite: _Goobstation/Clothing/Belt/judobelt.rsi + - type: GrantCorporateJudo + - type: Storage + whitelist: + tags: + - CigPack + - Taser + - SecBeltEquip + - Radio + - Sidearm + - MagazinePistol + - MagazineMagnum + - CombatKnife + - Truncheon + components: + - FlashOnTrigger + - SmokeOnTrigger + - Flash + - Handcuff + - BallisticAmmoProvider + - CartridgeAmmo + - DoorRemote + - Whistle + - BalloonPopper diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Weapons/Melee/kravmagagloves.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Weapons/Melee/kravmagagloves.yml new file mode 100644 index 0000000000..bebe1b0aa9 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Weapons/Melee/kravmagagloves.yml @@ -0,0 +1,16 @@ +- type: entity + parent: ClothingHandsBase + id: ClothingHandsGlovesKravMaga + name: Krav Maga gloves + description: These gloves can teach you to perform Krav Maga using nanochips for as long as you're wearing them. + components: + - type: Sprite + sprite: _Goobstation/Clothing/Hands/Gloves/kravgloves.rsi + - type: Item + - type: Clothing + - type: Fiber + fiberMaterial: fibers-leather + fiberColor: fibers-red + - type: ClothingGrantComponent + component: + - type: KravMaga diff --git a/Resources/Prototypes/_Goobstation/Entities/Specific/bso.yml b/Resources/Prototypes/_Goobstation/Entities/Specific/bso.yml new file mode 100644 index 0000000000..d06fd232ff --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Specific/bso.yml @@ -0,0 +1,15 @@ +- type: entity + parent: BaseItem + id: BSOManual + name: Nanotrasen CQC Manual + description: A small, blue manual. There are drawn instructions of tactical hand-to-hand combat. + components: + - type: Sprite + sprite: _Goobstation/Objects/Misc/cqc_manual.rsi + layers: + - state: icon-alt + - type: Item + size: Small + - type: StaticPrice + price: 3000 + - type: GrantCqc diff --git a/Resources/Prototypes/_Goobstation/Entities/Specific/syndicate.yml b/Resources/Prototypes/_Goobstation/Entities/Specific/syndicate.yml new file mode 100644 index 0000000000..051a109c72 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Specific/syndicate.yml @@ -0,0 +1,32 @@ +- type: entity + parent: BaseItem + id: CQCManual + name: old manual + description: A small, black manual. There are drawn instructions of tactical hand-to-hand combat. + components: + - type: Sprite + sprite: _Goobstation/Objects/Misc/cqc_manual.rsi + layers: + - state: icon + - type: Item + size: Small + - type: StaticPrice + price: 3000 + - type: GrantCqc + +- type: entity + parent: BaseItem + id: SleepingCarpScroll + name: mysterious scroll + description: A scroll filled with strange markings. It seems to be drawings of some sort of martial art. + components: + - type: Sprite + sprite: _Goobstation/Wizard/Objects/scroll.rsi + layers: + - state: scroll2 + - type: Item + sprite: _Goobstation/Wizard/Objects/scroll.rsi + size: Small + - type: StaticPrice + price: 3000 + - type: GrantSleepingCarp diff --git a/Resources/Prototypes/_Goobstation/MartialArts/carp.yml b/Resources/Prototypes/_Goobstation/MartialArts/carp.yml new file mode 100644 index 0000000000..67c3c66dad --- /dev/null +++ b/Resources/Prototypes/_Goobstation/MartialArts/carp.yml @@ -0,0 +1,64 @@ +- type: martialArt + id: SleepingCarp + martialArtsForm: SleepingCarp + roundstartCombos: SleepingCarpMoves + randomDamageModifier: True + baseDamageModifier: 5 + randomSayings: + - carp-saying-huah + - carv-saying-hya + - carp-saying-choo + - carp-saying-wuo + - carp-saying-kya + - carp-saying-huh + - carp-saying-hiyoh + - carp-saying-strike + - carp-saying-bite + randomSayingsDowned: + - carp-saying-banzai + - carp-saying-kiya + - carp-saying-omae + - carp-saying-see + - carp-saying-time + - carp-saying-cowabunga + +- type: comboList + id: SleepingCarpMoves + combos: + - SleepingCarpGnashingTeeth + - SleepingCarpKneeHaul + - SleepingCarpCrashingWaves + +- type: combo + id: SleepingCarpGnashingTeeth + name: Gnashing Teeth + martialArtsForm: SleepingCarp + attacks: + - Harm + - Harm + event: !type:SleepingCarpGnashingTeethPerformedEvent + damageType: Slash + extraDamage: 20 + +- type: combo + id: SleepingCarpKneeHaul + name: Knee Haul + martialArtsForm: SleepingCarp + attacks: + - Harm + - Grab + event: !type:SleepingCarpKneeHaulPerformedEvent + extraDamage: 10 + paralyzeTime: 6 + staminaDamage: 60 + +- type: combo + id: SleepingCarpCrashingWaves + name: Crashing Waves + martialArtsForm: SleepingCarp + attacks: + - Harm + - Disarm + event: !type:SleepingCarpCrashingWavesPerformedEvent + staminaDamage: 25 + diff --git a/Resources/Prototypes/_Goobstation/MartialArts/cqc.yml b/Resources/Prototypes/_Goobstation/MartialArts/cqc.yml new file mode 100644 index 0000000000..35edf58eb2 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/MartialArts/cqc.yml @@ -0,0 +1,69 @@ +- type: martialArt + id: CloseQuartersCombat + martialArtsForm: CloseQuartersCombat + roundstartCombos: CQCMoves + +- type: comboList + id: CQCMoves + combos: + - CQCConsecutive + - CQCPressure + - CQCRestrain + - CQCKick + - CQCSlam + +- type: combo + id: CQCSlam + name: Slam + martialArtsForm: CloseQuartersCombat + attacks: + - Grab + - Harm + event: !type:CqcSlamPerformedEvent { } + extraDamage: 10 # + paralyzeTime: 12 # in seconds + + +- type: combo + id: CQCKick + name: Kick + martialArtsForm: CloseQuartersCombat + attacks: + - Harm + - Harm + event: !type:CqcKickPerformedEvent + extraDamage: 10 + staminaDamage: 55 + +- type: combo + id: CQCRestrain + name: Restrain + martialArtsForm: CloseQuartersCombat + attacks: + - Grab + - Grab + event: !type:CqcRestrainPerformedEvent + paralyzeTime: 10 + staminaDamage: 30 + +- type: combo + id: CQCPressure + name: Pressure + martialArtsForm: CloseQuartersCombat + attacks: + - Disarm + - Grab + event: !type:CqcPressurePerformedEvent + staminaDamage: 65 + +- type: combo + id: CQCConsecutive + name: Consecutive + martialArtsForm: CloseQuartersCombat + attacks: + - Disarm + - Disarm + - Harm + event: !type:CqcConsecutivePerformedEvent + extraDamage: 10 + staminaDamage: 70 diff --git a/Resources/Prototypes/_Goobstation/MartialArts/judo.yml b/Resources/Prototypes/_Goobstation/MartialArts/judo.yml new file mode 100644 index 0000000000..bb89f1fcc4 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/MartialArts/judo.yml @@ -0,0 +1,45 @@ +- type: martialArt + id: CorporateJudo + martialArtsForm: CorporateJudo + roundstartCombos: CorporateJudoMoves + baseDamageModifier: 5 + +- type: comboList + id: CorporateJudoMoves + combos: + - JudoThrow + - JudoEyepoke + - JudoArmbar + +- type: combo + id: JudoThrow + name: Judo Throw + martialArtsForm: CorporateJudo + attacks: + - Grab + - Disarm + event: !type:JudoThrowPerformedEvent + staminaDamage: 50 + paralyzeTime: 7 + +- type: combo + id: JudoArmbar + name: Armbar + martialArtsForm: CorporateJudo + attacks: + - Disarm + - Disarm + - Grab + event: !type:JudoArmbarPerformedEvent + staminaDamage: 45 + paralyzeTime: 5 + +- type: combo + id: JudoEyepoke + name: Eyepoke + martialArtsForm: CorporateJudo + attacks: + - Disarm + - Harm + event: !type:JudoEyePokePerformedEvent + extraDamage: 5 diff --git a/Resources/Prototypes/_Goobstation/MartialArts/kravmaga.yml b/Resources/Prototypes/_Goobstation/MartialArts/kravmaga.yml new file mode 100644 index 0000000000..9998ce727a --- /dev/null +++ b/Resources/Prototypes/_Goobstation/MartialArts/kravmaga.yml @@ -0,0 +1,50 @@ +- type: entity + id: ActionLegSweep + name: Leg Sweep + description: Sweeps the legs out from under a target to knock them down for a few seconds. + categories: [ HideSpawnMenu ] + components: + - type: InstantAction + icon: + sprite: _Goobstation/Actions/kravmaga.rsi + state: legsweep + useDelay: 3 + event: !type:KravMagaActionEvent { } + - type: KravMagaAction + configuration: LegSweep + name: Leg Sweep + +- type: entity + id: ActionNeckChop + name: Neck Chop + description: A hard swing with the side of your hand deals some damage and disables the target's ability to speak for twenty seconds + categories: [ HideSpawnMenu ] + components: + - type: InstantAction + icon: + sprite: _Goobstation/Actions/kravmaga.rsi + state: neckchop + useDelay: 3 + event: !type:KravMagaActionEvent { } + - type: KravMagaAction + configuration: NeckChop + name: Neck Chop + effectTime: 20 + +- type: entity + id: ActionLungPunch + name: Lung Punch + description: Deals 30 stamina damage and prevents breathing for ten seconds. Four of those will incapacitate a target less-than-lethally, but beware of the loss of breath you cause. + categories: [ HideSpawnMenu ] + components: + - type: InstantAction + icon: + sprite: _Goobstation/Actions/kravmaga.rsi + state: lungpunch + useDelay: 3 + event: !type:KravMagaActionEvent { } + - type: KravMagaAction + configuration: LungPunch + name: Lung Punch + staminaDamage: 40 + effectTime: 10 diff --git a/Resources/Prototypes/_Nuclear14/Recipes/Lathes/materials.yml b/Resources/Prototypes/_Nuclear14/Recipes/Lathes/materials.yml index c15bc3244d..212714a548 100644 --- a/Resources/Prototypes/_Nuclear14/Recipes/Lathes/materials.yml +++ b/Resources/Prototypes/_Nuclear14/Recipes/Lathes/materials.yml @@ -3,14 +3,14 @@ result: N14IngotLead1 miningPoints: 10 applyMaterialDiscount: false - completetime: 2 + completetime: 0.01 # 0.3 per 30 materials: RawLead: 100 - type: latheRecipe id: IngotCopper1 result: IngotCopper1 - completetime: 2 + completetime: 0.016 # 0.5 per 30 miningPoints: 10 materials: RawCopper: 100 @@ -19,7 +19,7 @@ - type: latheRecipe id: N14IngotAluminium1 result: N14IngotAluminium1 - completetime: 2 + completetime: 0.016 # 0.5 per 30 miningPoints: 10 materials: RawAluminium: 100 diff --git a/Resources/Prototypes/_White/Entities/Clothing/Hands/gloves.yml b/Resources/Prototypes/_White/Entities/Clothing/Hands/gloves.yml index 7c4fd6a6a8..c4b2443ee2 100644 --- a/Resources/Prototypes/_White/Entities/Clothing/Hands/gloves.yml +++ b/Resources/Prototypes/_White/Entities/Clothing/Hands/gloves.yml @@ -19,31 +19,3 @@ sprite: _White/Clothing/Hands/sheriff_gloves.rsi - type: Clothing sprite: _White/Clothing/Hands/sheriff_gloves.rsi - -- type: entity - parent: ClothingHandsGlovesPowerglove - id: ClothingHandsGlovesPowergloveReal # WWDP HIGH RISK WARDEN GLOVES (fake krav magas) - name: power gloves - suffix: Powered - description: Now I'm playin' with power! BAM! - components: - - type: Insulated - - type: MeleeWeapon - autoAttack: true - attackRate: 0.5 - canHeavyAttack: false - maxTargets: 1 - damage: - types: - Blunt: 5 - soundHit: - collection: Punch - animation: WeaponArcFist - mustBeEquippedToUse: true - - type: StaminaDamageOnHit - damage: 25 - - type: Tag - tags: - - HighRiskItem - - type: StealTarget - stealGroup: WardenPowerGloves diff --git a/Resources/Prototypes/_White/Objectives/stealTargerGroups.yml b/Resources/Prototypes/_White/Objectives/stealTargerGroups.yml deleted file mode 100644 index f31ee3caa1..0000000000 --- a/Resources/Prototypes/_White/Objectives/stealTargerGroups.yml +++ /dev/null @@ -1,6 +0,0 @@ -- type: stealTargetGroup - id: WardenPowerGloves - name: steal-target-power-gloves - sprite: - sprite: Clothing/Hands/Gloves/powerglove.rsi - state: icon diff --git a/Resources/Prototypes/_White/Objectives/traitor.yml b/Resources/Prototypes/_White/Objectives/traitor.yml deleted file mode 100644 index 9c31850f43..0000000000 --- a/Resources/Prototypes/_White/Objectives/traitor.yml +++ /dev/null @@ -1,11 +0,0 @@ -- type: entity - categories: [HideSpawnMenu] - parent: BaseTraitorStealObjective - id: PowerGlovesStealObjective - components: - - type: NotJobRequirement - job: Warden - - type: StealCondition - stealGroup: WardenPowerGloves - verifyMapExistence: true - owner: job-name-warden diff --git a/Resources/Textures/DeltaV/Clothing/Hands/Gloves/inspection.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/Hands/Gloves/inspection.rsi/meta.json index 89b3fb1d12..17ac407320 100644 --- a/Resources/Textures/DeltaV/Clothing/Hands/Gloves/inspection.rsi/meta.json +++ b/Resources/Textures/DeltaV/Clothing/Hands/Gloves/inspection.rsi/meta.json @@ -23,4 +23,4 @@ "directions": 4 } ] -} +} \ No newline at end of file diff --git a/Resources/Textures/_Goobstation/Actions/kravmaga.rsi/legsweep.png b/Resources/Textures/_Goobstation/Actions/kravmaga.rsi/legsweep.png new file mode 100644 index 0000000000000000000000000000000000000000..33c3f611c91d4166994155a127bd404b86f54b32 GIT binary patch literal 552 zcmV+@0@wYCP)!5>+n`;IYIuvmTid`(V&xJQV)4R*1cVZEr<(ekx^Lzi?pH}FX^$)Q4 z0AW}gcRw1mQ7zBhdx%HIcRR~ZG#K&cY!2!DJ`hlO5P2#L0CN`1T_FkqaO4bO zGPg;8VF20Omy7_z-oY5-%TZr>-!*zI0E~mZi_-exE%6LkJF96yT%-hmImXBH9dQlg zJag`cBGD@WIC@S$#L;6Mo<`(TbFYMQ{avQw3;?HJ&H|!G_a`IKU2jQgS~UGi00_ot z!0Y|zbO{cQn?#fJms?HRqDVmakhTf22kc(f#Wgn}q95HvVm+9AN}vC+l~B$AN`UAA z;8WhVW7Ho)<}f-fMA!$CT<>XrtG0KSqZ1cJR@}ChP47<2#i?}{E+H|OtIP^Pq{si1(9KjNVid0 qPeb|THqCJ|dQ*SB`2URlJir&V<|WlbwbDWW0000?K@^3rM2onAEhMA}s07<|T56%CjfI7z@f~90 zBiQI82sUD2VPmO5%&t)sA*V3oWbQrRz4JpR<&QN6 z_}>79Lh&7+4-fYfzYYNN+Ehu6mkRPeDnu#(R!Y(A=IO0JG3{PAG5`~@QVJF0v+QU3 z6TN6h;_F->RscO=Zm}!R^{lEmG?n2Fa1Lt_Q>!O$kr9CAezmCnf4gc#3~GK!mU_)d z2e3W_8i?_=13N_G8Gt#ekL&PdPV#4cgTsx$*pGgXn4B~uv$EjKKLnsxPjhYoDn^z0 zqoSN|cBH(0uVT(8XJqxr6WO>6yTTYi_|*k#7pxs%+nEUB{$2(~5|{!+DS){gm~#!m zKXYYGHpyF{w;zdF{r;&J&SSi@DXI(X3S$XjlM_I1zpnMy$KbD*I2Ue%1HuVlGH(SH zq7(C#Yq>pMR&yBRX0){G^#WWP0>A-ekm>Y8YVRve$*!HK1BHW&xj29h!FOR+qHC-j zu$eRxQAmku2;na3eaG6KZS^%qbd>m6{da}|_$3z&$n9L9JB_4|x5?l{hYzAg^& zB>??dST-;$5#jR6P}T!7IsLXJ&9Mqd83wMgYC#Fos;_ zHVB9ysXG7@2>Yo52Q5!BH$n83iR4WLpb39W#OKq95NYDAhwwW;G`|x6zkimG0mcA7 Zp%1AKTWjm1Ao&0Q002ovPDHLkV1mB{54QjS literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Actions/kravmaga.rsi/meta.json b/Resources/Textures/_Goobstation/Actions/kravmaga.rsi/meta.json new file mode 100644 index 0000000000..31cbad53ff --- /dev/null +++ b/Resources/Textures/_Goobstation/Actions/kravmaga.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise at https://github.com/ParadiseSS13/Paradise/blob/a5726efe0c300662cb6f3a4a12d9151aa3eabe78/icons/mob/actions/actions.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "legsweep" + }, + { + "name": "lungpunch" + }, + { + "name": "neckchop" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_Goobstation/Actions/kravmaga.rsi/neckchop.png b/Resources/Textures/_Goobstation/Actions/kravmaga.rsi/neckchop.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef2373bbec1f62f6a951c716dfebc0696a08d0d GIT binary patch literal 615 zcmV-t0+{`YP)6IgBC=1Q!J& z5C8>~&oZ-_7Dae(tn)~aFo*O+W*UA05NiZ%2x}+6Ga15Jl(J!!9iRl@6hUZKVIl|kDrvhR|cRoJYN?1Tsvut5uWy=Z@tI>Bjd>2JHBJL zhc9-eZ(rnC*8-vWY?o}s3y>^d@o<)mqKWaeI$-r_6y)5?Eg4NLmLi1r0KiD^&aYDz zgc$Ye!1WF9o|bA>+As!zC`AC?INyn_mvS9QXwT>eh>Q&42N4Q@++!i+8+nIN3-U-3 z#)af=i0}O%ln$fP%?=0XO4Sb-0>E5jJ=gaHf#@`b-jVPHAmdns3{wOMChTB>!cNIZ zjfg;0bvDR^9?_lvviFPD!tR7B-Y*ouDZkV4M*yhop!Dz~nyH-;E&%%;=(Di%*$Lux z840=@1V%vRW)tQ1qXYob3X8VgLiH8_;J38|_yRjTA?V@qw6p*K002ovPDHLkV1mXb B4w?V} literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/equipped-BELT.png b/Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..09935e7c09fd113b033d2934c1b2f16c85726c7a GIT binary patch literal 503 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|Vnq zPZ!6KiaBp*?e=006mcy-kk>JHZR;_1p{WrWqTbxAuSES~uXC_FXfKenWs^s0VrDwm zW95#14VNPvNy%~vrd2{}Ef#F~Cs#q0Sh-`*dAVt?1RuLdVSd3}??c==)MEpFO){y-I+M)xkeuc4DEM z<#+bTU-4YFETDFkvfaCd5j)&3T+dK@9&*2yHAKrJH{QJdTGrQR7ynJ?vvu+P`Iq&i z*Xq8#HP0{p+Vpyz1!sn@dH>1I%=^pg3nM#p^_J8K3r64S&-rxs>*1eoYx2MFzIeW@ z{rK*0TXIDo$S)Sf>Q3w)n9T4$=koh|Z2V5#VtyOuI6Oa=DRSdlO=3Eq#}ou1Ht{r>z~WbJ(H*4HxtZVF|R=66eZ={22TJOPl1n?hIb zA0(w@YYs06Apoz!ZMr-%EamTBW02+vAp|(xuh8L{L5aPbv-Pq&z(I|;M&X4y+Fr{D zV}$_gyFp5CWGQkICW`0S+-58*b-5Du?!g>6kn1ScB>)t;T&48N1uY%Su<>{(|kfBYS==^zeQKr4lp0*?D5aU?50-|0wGhiZ9L>{V9Et&DZM@ zIlLqUz@@3CbXGB{sAa6Dw{_19D%A?BnhSjn#Er*{S+=HDXwaWt0ThU)EQn~6ncIRn zs(r{mw!~u24Z+tShnGjkA0nOrATZ~`nWOUd^XD<0jHLnEL2waq4A7@(`fM0y?yX$* zS+TNdN&Opk4S+4Snr8bv&ffmkUjP?`aNKu*UP=KdfPn*i0lhEFZALE1OaK4?07*qo IM6N<$g4SK-vH$=8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/meta.json b/Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/meta.json new file mode 100644 index 0000000000..86066df528 --- /dev/null +++ b/Resources/Textures/_Goobstation/Clothing/Belt/judobelt.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise at https://github.com/ParadiseSS13/Paradise/blob/7da09f5e7230369ec48d9e5d31bdddb3f95a6d8f/icons/mob/clothing/belt.dmi, https://github.com/ParadiseSS13/Paradise/blob/7da09f5e7230369ec48d9e5d31bdddb3f95a6d8f/icons/obj/clothing/belts.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "equipped-BELT", + "directions": 4 + }, + { + "name": "icon" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/equipped-HAND.png b/Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/equipped-HAND.png new file mode 100644 index 0000000000000000000000000000000000000000..6d4e42c4cd80a231751b748e29e4ddc9cccaaad4 GIT binary patch literal 530 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|Vm` zPZ!6KiaBp*?e{xuAaKl{W$KU3MrCPhk6hZwe_?O`#Esm=V#jRQs^u4O2Tk*eoGE$Q z!@)`8i3=~s(!TS4yKBBjOPOvv|Ln>|%OErckGZ-c$Gdc8eG9Yt4>^-yo{Onh6 znfcexSHION9=`nSlcbj2Z+BO{Gkjdlx+X6#P=wWBw%IISj}K3GxlBtv@J(=|jPkzl z13R<|?PojrY-7niG;?}o@{+=yAA8Fibj)_kI0hMtNa|-i`|;?s)u-EB0loa4_q83w zF6J$$SZT;|>o7u;Pebdk@rP5f}AJ8xOnsRm~` lqqZr3Z+kuhH;OXk;vd$@?2>=q5+kgN7 literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/icon.png b/Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..78a7b892d110e42069b561b6ad1fb278240605fc GIT binary patch literal 486 zcmV@P)vxE?`DSFZOK0?0z`la5CPU3;A(%n z;rjA*zVT-OXSYV`Hx*(sfbKVR{Z>n64A0X-5Uhy1sF2c`-I^7VlVB)wDPva3&39YnY$u{HrEiW zj&C+P0D90uAbjQ!%#jOo@tv!-AS?iwBN2&l(Y|aarf`m-)DSf0xo(w~1%N+E+r=)`!sj=Aopo$0U#l!Ung8bicHbn-rgQtS=@Apidz`G*h(Re@G%g c1o#bo0jz-=bl=@P8~^|S07*qoM6N<$g6PrGC;$Ke literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/meta.json b/Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/meta.json new file mode 100644 index 0000000000..28854c9bcd --- /dev/null +++ b/Resources/Textures/_Goobstation/Clothing/Hands/Gloves/kravgloves.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise at https://github.com/ParadiseSS13/Paradise/blob/bd91a1b962fe9bd38e346e9fafd4ebb10784fcb3/icons/mob/clothing/hands.dmi and https://github.com/ParadiseSS13/Paradise/blob/bd91a1b962fe9bd38e346e9fafd4ebb10784fcb3/icons/obj/clothing/gloves.dmi and https://github.com/ParadiseSS13/Paradise/blob/HEAD/icons/mob/clothing/hands.dmi ", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-HAND", + "directions": 4 + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/icon-alt.png b/Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/icon-alt.png new file mode 100644 index 0000000000000000000000000000000000000000..f01ed13e7ef4c85a9d6602b0a435fc3da08fccf2 GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEVF!Fi2IEF;DCMQU+E=~~XDLLTL zqttoe*8e3^f0AmA1JgDOWIwR?)o0`8JoIYb{+g2o#h*)(dR6Z+@&JK)oIu#&lD|5d zZj+udEPH+1!)VScz6Qp{^KaBv_T8Of$Cm&E9=^V=56{oDovl-RqUeBSSuzjz$&a=- z`4${;DmmaH8l1svVPWxa^~#lhMU~*KcB-UF3-Q{%DbDJniU&8iaWW~*nl7`ENqg{wfFb;cbZj;^fUz;Y+_{iy}et! UbKlkqU;r_Ay85}Sb4q9e0Kk-i&Hw-a literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/icon.png b/Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..059c565fc5bb60cd44499ead2710d6278248a633 GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyDgizrt_KbrP*70t^71M!E@owA zUB7;P0|Uc;Uf!EGZ!YHMUeK2G^*kj(e!&d?5rFeZfErLd!PCVt#G?1@ zxr=uF?)DWJyu{#?iGOrZ<-!le#_awbS&#{-aDXO N44$rjF6*2UngHoHT8{t# literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/meta.json new file mode 100644 index 0000000000..0371deee2a --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Misc/cqc_manual.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprite taken at: https://github.com/tgstation/tgstation", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "icon-alt" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/equipped-BELT.png b/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..9dc2b59ac870c461f4d11664a7a68094cdaa07c6 GIT binary patch literal 409 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|TSC zr;B4q#hkad4852WMUH$FJfe`f^)%<2mIkxTGrVtX96EXxSc;fmH%#y6zmS#Pu zrS6d)C73&D&s0`^gR=&o^Y`T`+E4q-^#1MPJq!o1p$&3her>vOrP5B~t)qt2f$PtO z?%VILsGF11Hr-f~Matp(50)E>SNg-97Su88y-Pc5SyID%F3-K9qCLi>Vf$~^W7aL% zhAdJCs=hWZf5}^5+8$)mu=rkP^8&H2QZ{d79M=93PO zR&1>Hoj-$FLb9Rk`GRw4;*C>y9IPu=%C^jM**u9cW3_CH)ZxvOm?ggdFB3F)pm2iG z#G2!X;T{=>(A^wso-n-PS`*6>R>bh;3B!$Q4j|3M@EM4mdK II;Vst08jay;Q#;t literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/inhand-left.png b/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..ed1902af960a7f666cc1089d7ceee212c9fc5677 GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1F?j zi(^Q|oVPb^xtbkBTptRbXkyMgfO?zT($=$dAYre%+cd=KTH`ZMGwOsD_ zN2Bt$D?hQ=oh~}Lds_(Shgr+K?`>UL(Xj7*_uk8s%HMvB$7v>tRTufA-n@xEC(L&t zDP4Y|_4$SB0oCd9Q;p9rWY}8%Ezt6F3-gv6H{G9{d%Pd&&K>%!Q=`wmp8NL%(8mm( Lu6{1-oD!M&yS>7B zP78L2Im`;@7zLg)bQCijv1E88!%)cA01;j%{lK>GcD97v@6U5x)8DbpnBIEr);Ig> zQ709wKED+Hu}=G@OPU?;hnZ@dI?vqU4e;9eclQ16b8q4iM&K|REPRn$vYf5z5TnsM zo-Z*~Oh8Uw4A+Fh^amam4#(y;%Kc}8I;n2i8CR*qx4IQTPcnGA`njxgN@xNAqBd_( literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/meta.json b/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/meta.json new file mode 100644 index 0000000000..098f421f0d --- /dev/null +++ b/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/80ab61c8c7741e1d95e5f168357a9e6e61b38f2c", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "scroll" + }, + { + "name": "scroll2" + }, + { + "name": "equipped-BELT", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/scroll.png b/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/scroll.png new file mode 100644 index 0000000000000000000000000000000000000000..e7780ff2cafdfce82c61d3e8318616e18267cfbe GIT binary patch literal 633 zcmV-<0*3vGP)_H%aq~MmHeT+}xmP8SK9Dm<@67qmH#6s4!}Q1aCosMQ zN*8GpV`4WK3QRyZh@H=pu|;1WMKyQxcO(GEg_Su9PaAEUO!5INUb-(RJKBxqM8cK; z9C|^j1)5skpja%awRpK)pqF}s5^G82k2uf8yyNqpHDIK6)Yy2sQffd}w{d==Ot0Uu zo&xyZ4UPoh7+VZc@%B>frdFv_Gg6>v>rG=cm9GwL2_Row0|*ESn~_;XL&$m;>MH~1sast{6u&aJ65fBc14oJw|qrl`r zwR?uuWz4)ti@+1yR{2|f!k2MRCMnG zzKnEEIkX_o0UdazV0Ckk9&XOtR_CoozTx1C?%e;sBLG`x_gVy)ME~6VI_B#4YC%r| z$Yr#ZCuB!TuK8>)qJ9@60Gne3B48ylDva-6GhO@u%|~)+ TC*K=w00000NkvXXu0mjfPgo00 literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/scroll2.png b/Resources/Textures/_Goobstation/Wizard/Objects/scroll.rsi/scroll2.png new file mode 100644 index 0000000000000000000000000000000000000000..2f00a2340183f2699d42669764231e4f85aef91e GIT binary patch literal 673 zcmV;S0$%-zP)fK-Y=gn%+c;K3)py*=@Ze0W9q9@1Ss7!mz1AK7ioGv%In+HD697 zYzbh2>Et#~t$kw@i;ZXnFO~9i_xMUf!y{@v{M;0Bj`KZxAd#F>x_Izm)g^H4hF9OV(x0MXMw2-FN^(}L*d|p{wqvgd#(uMXx z#LXm000@kql@w?Hqk{;L{eapglJReW82k<+%AgBv1xmLSRa-atS(Un!0NV-*NV%=S z*@glj9QjQGOajiO+ze@hDCXW@{SpD$2NHHlsQE^zxM>4lMoz#s1MIrrN(6)hp92yy zdo-9lh-BSm^YQ)Q1z!rlDHO0~zSEU4=gghY`*G>N1a`6yQk2FG``GyH4sI$EKR$>~ z4>Rfr9-Z6>S)0$={X5$k6`V=Pj}b4pDxf|pYIgx&Ms}whGDhadH5=LE9MFMh2?i!+ z>EdY5u&Q4*@(Tx7boKs^(o8m`Mr4n7I@xOxU=rV--LGTrey=U)NuZidj;uW(fgrr! z<-UgvMFJB*^I=3Yy4KSOqW&&M05