From 16be126ca1e65ebc94a0d688d7d5eca749fc272d Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Sun, 2 Jun 2024 20:11:48 +1200 Subject: [PATCH 01/63] Remove `noSpawn: true` from action entity prototypes (#28508) --- Resources/Prototypes/Actions/borgs.yml | 1 - Resources/Prototypes/Actions/crit.yml | 3 --- Resources/Prototypes/Actions/diona.yml | 2 -- Resources/Prototypes/Actions/internals.yml | 1 - Resources/Prototypes/Actions/mech.yml | 3 --- Resources/Prototypes/Actions/ninja.yml | 6 ----- Resources/Prototypes/Actions/polymorph.yml | 4 --- Resources/Prototypes/Actions/revenant.yml | 5 ---- Resources/Prototypes/Actions/speech.yml | 1 - Resources/Prototypes/Actions/spider.yml | 2 -- Resources/Prototypes/Actions/types.yml | 27 ------------------- .../Clothing/Masks/base_clothingmask.yml | 3 +-- .../Entities/Clothing/Neck/misc.yml | 1 - .../Entities/Clothing/Shoes/magboots.yml | 5 ---- .../Entities/Clothing/Shoes/misc.yml | 1 - .../Entities/Mobs/NPCs/regalrat.yml | 6 ----- .../Entities/Mobs/Player/admin_ghost.yml | 6 ----- .../Entities/Mobs/Player/dragon.yml | 3 --- .../Entities/Mobs/Player/guardian.yml | 1 - .../Entities/Mobs/Player/observer.yml | 5 ---- .../Objects/Devices/chameleon_projector.yml | 2 -- .../Prototypes/Entities/Objects/Fun/pai.yml | 2 -- .../Objects/Specific/Chapel/bibles.yml | 1 - .../Specific/Robotics/borg_modules.yml | 1 - .../Entities/Objects/Tools/jetpacks.yml | 1 - Resources/Prototypes/Magic/event_spells.yml | 1 - .../Prototypes/Magic/forcewall_spells.yml | 1 - Resources/Prototypes/Magic/knock_spell.yml | 1 - .../Prototypes/Magic/projectile_spells.yml | 3 --- Resources/Prototypes/Magic/rune_spells.yml | 4 --- Resources/Prototypes/Magic/smite_spells.yml | 1 - Resources/Prototypes/Magic/spawn_spells.yml | 1 - Resources/Prototypes/Magic/staves.yml | 1 - .../Prototypes/Magic/teleport_spells.yml | 1 - Resources/Prototypes/Magic/utility_spells.yml | 1 - .../Prototypes/Roles/Jobs/Civilian/mime.yml | 1 - 36 files changed, 1 insertion(+), 108 deletions(-) diff --git a/Resources/Prototypes/Actions/borgs.yml b/Resources/Prototypes/Actions/borgs.yml index 6d35c69cf6..a0168ef00f 100644 --- a/Resources/Prototypes/Actions/borgs.yml +++ b/Resources/Prototypes/Actions/borgs.yml @@ -2,7 +2,6 @@ id: ActionViewLaws name: View Laws description: View the laws that you must follow. - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem diff --git a/Resources/Prototypes/Actions/crit.yml b/Resources/Prototypes/Actions/crit.yml index 705ee6ee6b..c5712844bf 100644 --- a/Resources/Prototypes/Actions/crit.yml +++ b/Resources/Prototypes/Actions/crit.yml @@ -3,7 +3,6 @@ id: ActionCritSuccumb name: Succumb description: Accept your fate. - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem @@ -18,7 +17,6 @@ id: ActionCritFakeDeath name: Fake Death description: Pretend to take your final breath while staying alive. - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem @@ -34,7 +32,6 @@ id: ActionCritLastWords name: Say Last Words description: Whisper your last words to anyone nearby, and then succumb to your fate. You only have 30 characters to work with. - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem diff --git a/Resources/Prototypes/Actions/diona.yml b/Resources/Prototypes/Actions/diona.yml index 11db30386a..9f80f18178 100644 --- a/Resources/Prototypes/Actions/diona.yml +++ b/Resources/Prototypes/Actions/diona.yml @@ -2,7 +2,6 @@ id: DionaGibAction name: Gib Yourself! description: Split apart into 3 nymphs. - noSpawn: true components: - type: InstantAction icon: @@ -16,7 +15,6 @@ id: DionaReformAction name: Reform description: Reform back into a whole Diona. - noSpawn: true components: - type: InstantAction icon: diff --git a/Resources/Prototypes/Actions/internals.yml b/Resources/Prototypes/Actions/internals.yml index dd83a45332..5982c3daa2 100644 --- a/Resources/Prototypes/Actions/internals.yml +++ b/Resources/Prototypes/Actions/internals.yml @@ -2,7 +2,6 @@ id: ActionToggleInternals name: Toggle Internals description: Breathe from the equipped gas tank. Also requires equipped breath mask. - noSpawn: true components: - type: InstantAction icon: diff --git a/Resources/Prototypes/Actions/mech.yml b/Resources/Prototypes/Actions/mech.yml index 2005133a70..48092f9c5a 100644 --- a/Resources/Prototypes/Actions/mech.yml +++ b/Resources/Prototypes/Actions/mech.yml @@ -2,7 +2,6 @@ id: ActionMechCycleEquipment name: Cycle description: Cycles currently selected equipment - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem @@ -16,7 +15,6 @@ id: ActionMechOpenUI name: Control Panel description: Opens the control panel for the mech - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem @@ -30,7 +28,6 @@ id: ActionMechEject name: Eject description: Ejects the pilot from the mech - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem diff --git a/Resources/Prototypes/Actions/ninja.yml b/Resources/Prototypes/Actions/ninja.yml index 5fe6f23b27..adaf563692 100644 --- a/Resources/Prototypes/Actions/ninja.yml +++ b/Resources/Prototypes/Actions/ninja.yml @@ -3,7 +3,6 @@ id: ActionToggleNinjaGloves name: Toggle ninja gloves description: Toggles all glove actions on left click. Includes your doorjack, draining power, stunning enemies, downloading research and calling in a threat. - noSpawn: true components: - type: InstantAction priority: -13 @@ -14,7 +13,6 @@ id: ActionCreateThrowingStar name: Create throwing star description: Channels suit power into creating a throwing star that deals extra stamina damage. - noSpawn: true components: - type: InstantAction useDelay: 0.5 @@ -29,7 +27,6 @@ id: ActionRecallKatana name: Recall katana description: Teleports the Energy Katana linked to this suit to its wearer, cost based on distance. - noSpawn: true components: - type: InstantAction useDelay: 1 @@ -44,7 +41,6 @@ id: ActionNinjaEmp name: EM Burst description: Disable any nearby technology with an electro-magnetic pulse. - noSpawn: true components: - type: InstantAction icon: @@ -58,7 +54,6 @@ id: ActionTogglePhaseCloak name: Phase cloak description: Toggles your suit's phase cloak. Beware that if you are hit, all abilities are disabled for 5 seconds, including your cloak! - noSpawn: true components: - type: InstantAction # have to plan (un)cloaking ahead of time @@ -71,7 +66,6 @@ id: ActionEnergyKatanaDash name: Katana dash description: Teleport to anywhere you can see, if your Energy Katana is in your hand. - noSpawn: true components: - type: WorldTargetAction icon: diff --git a/Resources/Prototypes/Actions/polymorph.yml b/Resources/Prototypes/Actions/polymorph.yml index 445dc8d9f5..81feba4eac 100644 --- a/Resources/Prototypes/Actions/polymorph.yml +++ b/Resources/Prototypes/Actions/polymorph.yml @@ -2,14 +2,12 @@ id: ActionRevertPolymorph name: Revert description: Revert back into your original form. - noSpawn: true components: - type: InstantAction event: !type:RevertPolymorphActionEvent - type: entity id: ActionPolymorph - noSpawn: true components: - type: InstantAction event: !type:PolymorphActionEvent @@ -19,7 +17,6 @@ id: ActionPolymorphWizardSpider name: Spider Polymorph description: Polymorphs you into a Spider. - noSpawn: true components: - type: InstantAction useDelay: 60 @@ -34,7 +31,6 @@ id: ActionPolymorphWizardRod name: Rod Form description: CLANG! - noSpawn: true components: - type: InstantAction useDelay: 60 diff --git a/Resources/Prototypes/Actions/revenant.yml b/Resources/Prototypes/Actions/revenant.yml index da7b4ba56f..dca491a99b 100644 --- a/Resources/Prototypes/Actions/revenant.yml +++ b/Resources/Prototypes/Actions/revenant.yml @@ -2,7 +2,6 @@ id: ActionRevenantShop name: Shop description: Opens the ability shop. - noSpawn: true components: - type: InstantAction icon: Interface/Actions/shop.png @@ -12,7 +11,6 @@ id: ActionRevenantDefile name: Defile description: Costs 30 Essence. - noSpawn: true components: - type: InstantAction icon: Interface/Actions/defile.png @@ -23,7 +21,6 @@ id: ActionRevenantOverloadLights name: Overload Lights description: Costs 40 Essence. - noSpawn: true components: - type: InstantAction icon: Interface/Actions/overloadlight.png @@ -34,7 +31,6 @@ # id: ActionRevenantBlight # name: Blight # description: Costs 50 Essence. -# noSpawn: true # components: # - type: InstantAction # icon: Interface/Actions/blight.png @@ -45,7 +41,6 @@ id: ActionRevenantMalfunction name: Malfunction description: Costs 60 Essence. - noSpawn: true components: - type: InstantAction icon: Interface/Actions/malfunction.png diff --git a/Resources/Prototypes/Actions/speech.yml b/Resources/Prototypes/Actions/speech.yml index 39db04b1b3..c71ec74880 100644 --- a/Resources/Prototypes/Actions/speech.yml +++ b/Resources/Prototypes/Actions/speech.yml @@ -2,7 +2,6 @@ id: ActionConfigureMeleeSpeech name: Set Battlecry description: Set a custom battlecry for when you attack! - noSpawn: true components: - type: InstantAction itemIconStyle: BigItem diff --git a/Resources/Prototypes/Actions/spider.yml b/Resources/Prototypes/Actions/spider.yml index 14b9fb6ccb..fe37085eca 100644 --- a/Resources/Prototypes/Actions/spider.yml +++ b/Resources/Prototypes/Actions/spider.yml @@ -2,7 +2,6 @@ id: ActionSpiderWeb name: Spider Web description: Spawns a web that slows your prey down. - noSpawn: true components: - type: InstantAction icon: Interface/Actions/web.png @@ -13,7 +12,6 @@ id: ActionSericulture name: Weave silk description: Weave a bit of silk for use in arts and crafts. - noSpawn: true components: - type: InstantAction icon: Interface/Actions/web.png diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index fb156a732e..4b3d75bf92 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -13,7 +13,6 @@ id: ActionScream name: Scream description: AAAAAAAAAAAAAAAAAAAAAAAAA - noSpawn: true components: - type: InstantAction useDelay: 10 @@ -25,7 +24,6 @@ id: ActionTurnUndead name: Turn Undead description: Succumb to your infection and become a zombie. - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -37,7 +35,6 @@ id: ActionToggleLight name: Toggle Light description: Turn the light on and off. - noSpawn: true components: - type: InstantAction icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } @@ -48,7 +45,6 @@ id: ActionOpenStorageImplant name: Open Storage Implant description: Opens the storage implant embedded under your skin - noSpawn: true components: - type: InstantAction itemIconStyle: BigAction @@ -63,7 +59,6 @@ id: ActionActivateMicroBomb name: Activate Microbomb description: Activates your internal microbomb, completely destroying you and your equipment - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -80,7 +75,6 @@ id: ActionActivateDeathAcidifier name: Activate Death-Acidifier description: Activates your death-acidifier, completely melting you and your equipment - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -96,7 +90,6 @@ id: ActionActivateFreedomImplant name: Break Free description: Activating your freedom implant will free you from any hand restraints - noSpawn: true components: - type: InstantAction charges: 3 @@ -112,7 +105,6 @@ id: ActionOpenUplinkImplant name: Open Uplink description: Opens the syndicate uplink embedded under your skin - noSpawn: true components: - type: InstantAction itemIconStyle: BigAction @@ -126,7 +118,6 @@ id: ActionActivateEmpImplant name: Activate EMP description: Triggers a small EMP pulse around you - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -143,7 +134,6 @@ id: ActionActivateScramImplant name: SCRAM! description: Randomly teleports you within a large distance. - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -160,7 +150,6 @@ id: ActionActivateDnaScramblerImplant name: Scramble DNA description: Randomly changes your name and appearance. - noSpawn: true components: - type: InstantAction charges: 1 @@ -175,7 +164,6 @@ id: ActionMorphGeras name: Morph into Geras description: Morphs you into a Geras - a miniature version of you which allows you to move fast, at the cost of your inventory. - noSpawn: true components: - type: InstantAction itemIconStyle: BigAction @@ -190,7 +178,6 @@ id: ActionToggleSuitPiece name: Toggle Suit Piece description: Remember to equip the important pieces of your suit before going into action. - noSpawn: true components: - type: InstantAction itemIconStyle: BigItem @@ -201,7 +188,6 @@ id: ActionCombatModeToggle name: "[color=red]Combat Mode[/color]" description: Enter combat mode - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -216,7 +202,6 @@ parent: ActionCombatModeToggle name: "[color=red]Combat Mode[/color]" description: Enter combat mode - noSpawn: true components: - type: InstantAction enabled: false @@ -227,7 +212,6 @@ id: ActionChangeVoiceMask name: Set name description: Change the name others hear to something else. - noSpawn: true components: - type: InstantAction icon: { sprite: Interface/Actions/voice-mask.rsi, state: icon } @@ -237,7 +221,6 @@ id: ActionVendingThrow name: Dispense Item description: Randomly dispense an item from your stock. - noSpawn: true components: - type: InstantAction useDelay: 30 @@ -247,7 +230,6 @@ id: ActionArtifactActivate name: Activate Artifact description: Immediately activates your current artifact node. - noSpawn: true components: - type: InstantAction icon: @@ -260,7 +242,6 @@ id: ActionToggleBlock name: Block description: Raise or lower your shield. - noSpawn: true components: - type: InstantAction icon: { sprite: Objects/Weapons/Melee/shields.rsi, state: teleriot-icon } @@ -271,7 +252,6 @@ id: ActionClearNetworkLinkOverlays name: Clear network link overlays description: Clear network link overlays. - noSpawn: true components: - type: InstantAction clientExclusive: true @@ -285,7 +265,6 @@ id: ActionAnimalLayEgg name: Lay egg description: Uses hunger to lay an egg. - noSpawn: true components: - type: InstantAction icon: { sprite: Objects/Consumable/Food/egg.rsi, state: icon } @@ -296,7 +275,6 @@ id: ActionSleep name: Sleep description: Go to sleep. - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -308,7 +286,6 @@ id: ActionWake name: Wake up description: Stop sleeping. - noSpawn: true components: - type: InstantAction icon: { sprite: Clothing/Head/Hats/pyjamasyndicatered.rsi, state: icon } @@ -320,7 +297,6 @@ id: ActionActivateHonkImplant name: Honk description: Activates your honking implant, which will produce the signature sound of the clown. - noSpawn: true components: - type: InstantAction icon: { sprite: Objects/Fun/bikehorn.rsi, state: icon } @@ -331,7 +307,6 @@ id: ActionFireStarter name: Ignite description: Ignites enemies in a radius around you. - noSpawn: true components: - type: InstantAction priority: -1 @@ -343,7 +318,6 @@ id: ActionToggleEyes name: Open/Close eyes description: Close your eyes to protect your peepers, or open your eyes to enjoy the pretty lights. - noSpawn: true components: - type: InstantAction icon: Interface/Actions/eyeopen.png @@ -357,7 +331,6 @@ id: ActionToggleWagging name: action-name-toggle-wagging description: action-description-toggle-wagging - noSpawn: true components: - type: InstantAction icon: { sprite: Mobs/Customization/reptilian_parts.rsi, state: tail_smooth_behind } diff --git a/Resources/Prototypes/Entities/Clothing/Masks/base_clothingmask.yml b/Resources/Prototypes/Entities/Clothing/Masks/base_clothingmask.yml index 3531a26a6c..00dcd8263f 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/base_clothingmask.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/base_clothingmask.yml @@ -21,7 +21,6 @@ id: ActionToggleMask name: Toggle Mask description: Handy, but prevents insertion of pie into your pie hole. - noSpawn: true components: - type: InstantAction icon: { sprite: Clothing/Mask/gas.rsi, state: icon } @@ -49,4 +48,4 @@ Quantity: 10 - type: Tag tags: - - ClothMade \ No newline at end of file + - ClothMade diff --git a/Resources/Prototypes/Entities/Clothing/Neck/misc.yml b/Resources/Prototypes/Entities/Clothing/Neck/misc.yml index 51325c0bbb..8dfc709bc4 100644 --- a/Resources/Prototypes/Entities/Clothing/Neck/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/Neck/misc.yml @@ -70,7 +70,6 @@ - type: entity id: ActionStethoscope name: Listen with stethoscope - noSpawn: true components: - type: EntityTargetAction icon: diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml index 485d530ea5..e80ed74305 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml @@ -132,7 +132,6 @@ id: ActionBaseToggleMagboots name: Toggle Magboots description: Toggles the magboots on and off. - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem @@ -141,7 +140,6 @@ - type: entity id: ActionToggleMagboots parent: ActionBaseToggleMagboots - noSpawn: true components: - type: InstantAction icon: { sprite: Clothing/Shoes/Boots/magboots.rsi, state: icon } @@ -150,7 +148,6 @@ - type: entity id: ActionToggleMagbootsAdvanced parent: ActionBaseToggleMagboots - noSpawn: true components: - type: InstantAction icon: { sprite: Clothing/Shoes/Boots/magboots-advanced.rsi, state: icon } @@ -159,7 +156,6 @@ - type: entity id: ActionToggleMagbootsSci parent: ActionBaseToggleMagboots - noSpawn: true components: - type: InstantAction icon: { sprite: Clothing/Shoes/Boots/magboots-science.rsi, state: icon } @@ -168,7 +164,6 @@ - type: entity id: ActionToggleMagbootsSyndie parent: ActionBaseToggleMagboots - noSpawn: true components: - type: InstantAction icon: { sprite: Clothing/Shoes/Boots/magboots-syndicate.rsi, state: icon } diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml b/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml index d5a695c7c0..cbea9d319d 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml @@ -128,7 +128,6 @@ id: ActionToggleSpeedBoots name: Toggle Speed Boots description: Toggles the speed boots on and off. - noSpawn: true components: - type: InstantAction itemIconStyle: NoItem diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml index aa12eac1c2..38debe2a9a 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -301,7 +301,6 @@ id: ActionRatKingRaiseArmy name: Raise Army description: Spend some hunger to summon an allied rat to help defend you. - noSpawn: true components: - type: InstantAction useDelay: 4 @@ -314,7 +313,6 @@ id: ActionRatKingDomain name: Rat King's Domain description: Spend some hunger to release a cloud of ammonia into the air. - noSpawn: true components: - type: InstantAction useDelay: 6 @@ -327,7 +325,6 @@ id: ActionRatKingOrderStay name: Stay description: Command your army to stand in place. - noSpawn: true components: - type: InstantAction useDelay: 1 @@ -346,7 +343,6 @@ id: ActionRatKingOrderFollow name: Follow description: Command your army to follow you around. - noSpawn: true components: - type: InstantAction useDelay: 1 @@ -365,7 +361,6 @@ id: ActionRatKingOrderCheeseEm name: Cheese 'Em description: Command your army to attack whoever you point at. - noSpawn: true components: - type: InstantAction useDelay: 1 @@ -384,7 +379,6 @@ id: ActionRatKingOrderLoose name: Loose description: Command your army to act at their own will. - noSpawn: true components: - type: InstantAction useDelay: 1 diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index 0fa85fc84f..4a83593bc3 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -97,7 +97,6 @@ id: ActionAGhostShowSolar name: Solar Control Interface description: View a solar control interface. - noSpawn: true components: - type: InstantAction icon: { sprite: Structures/Machines/parts.rsi, state: box_0 } @@ -110,7 +109,6 @@ id: ActionAGhostShowCommunications name: Communications Interface description: View a communications interface. - noSpawn: true components: - type: InstantAction icon: { sprite: Structures/Machines/parts.rsi, state: box_0 } @@ -123,7 +121,6 @@ id: ActionAGhostShowRadar name: Mass Scanner Interface description: View a mass scanner interface. - noSpawn: true components: - type: InstantAction icon: { sprite: Structures/Machines/parts.rsi, state: box_0 } @@ -136,7 +133,6 @@ id: ActionAGhostShowCargo name: Cargo Ordering Interface description: View a cargo ordering interface. - noSpawn: true components: - type: InstantAction icon: { sprite: Structures/Machines/parts.rsi, state: box_0 } @@ -149,7 +145,6 @@ id: ActionAGhostShowCrewMonitoring name: Crew Monitoring Interface description: View a crew monitoring interface. - noSpawn: true components: - type: InstantAction icon: { sprite: Structures/Machines/parts.rsi, state: box_0 } @@ -162,7 +157,6 @@ id: ActionAGhostShowStationRecords name: Station Records Interface description: View a station records Interface - noSpawn: true components: - type: InstantAction icon: { sprite: Structures/Machines/parts.rsi, state: box_0 } diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index 258488af9b..869fb88084 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -203,7 +203,6 @@ id: ActionSpawnRift name: Summon Carp Rift description: Summons a carp rift that will periodically spawns carps. - noSpawn: true components: - type: InstantAction icon: @@ -217,7 +216,6 @@ id: ActionDevour name: "[color=red]Devour[/color]" description: Attempt to break a structure with your jaws or swallow a creature. - noSpawn: true components: - type: EntityTargetAction icon: { sprite : Interface/Actions/devour.rsi, state: icon } @@ -226,7 +224,6 @@ priority: 1 - type: entity - noSpawn: true id: ActionDragonsBreath name: "[color=orange]Dragon's Breath[/color]" description: Spew out flames at anyone foolish enough to attack you! diff --git a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml index 80ee2c55b8..9ccfdf4e50 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml @@ -259,7 +259,6 @@ id: ActionToggleGuardian name: Toggle Guardian description: Either manifests the guardian or recalls it back into your body - noSpawn: true components: - type: InstantAction icon: Interface/Actions/manifest.png diff --git a/Resources/Prototypes/Entities/Mobs/Player/observer.yml b/Resources/Prototypes/Entities/Mobs/Player/observer.yml index 114c3fa747..85be42cc02 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/observer.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/observer.yml @@ -53,7 +53,6 @@ id: ActionGhostBoo name: Boo! description: Scare your crew members because of boredom! - noSpawn: true components: - type: InstantAction icon: Interface/Actions/scream.png @@ -65,7 +64,6 @@ id: ActionToggleLighting name: Toggle All Lighting description: Toggle all light rendering to better observe dark areas. - noSpawn: true components: - type: InstantAction icon: Interface/VerbIcons/light.svg.192dpi.png @@ -77,7 +75,6 @@ id: ActionToggleFov name: Toggle FoV description: Toggles field-of-view in order to see what players see. - noSpawn: true components: - type: InstantAction icon: Interface/VerbIcons/vv.svg.192dpi.png @@ -89,7 +86,6 @@ id: ActionToggleGhosts name: Toggle Ghosts description: Toggle the visibility of other ghosts. - noSpawn: true components: - type: InstantAction icon: { sprite: Mobs/Ghosts/ghost_human.rsi, state: icon } @@ -101,7 +97,6 @@ id: ActionToggleGhostHearing name: Toggle Ghost Hearing description: Toggle between hearing all messages and hearing only radio & nearby messages. - noSpawn: true components: - type: InstantAction checkCanInteract: false diff --git a/Resources/Prototypes/Entities/Objects/Devices/chameleon_projector.yml b/Resources/Prototypes/Entities/Objects/Devices/chameleon_projector.yml index e021281021..20e138f81a 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/chameleon_projector.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/chameleon_projector.yml @@ -49,7 +49,6 @@ # actions - type: entity - noSpawn: true id: ActionDisguiseNoRot name: Toggle Rotation description: Use this to prevent your disguise from rotating, making it easier to hide in some scenarios. @@ -59,7 +58,6 @@ event: !type:DisguiseToggleNoRotEvent - type: entity - noSpawn: true id: ActionDisguiseAnchor name: Toggle Anchored description: For many objects you will want to be anchored to not be completely obvious. diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 1b9c5303c6..02bbce2843 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -136,7 +136,6 @@ id: ActionPAIPlayMidi name: Play MIDI description: Open your portable MIDI interface to soothe your owner. - noSpawn: true components: - type: InstantAction checkCanInteract: false @@ -149,7 +148,6 @@ id: ActionPAIOpenMap name: Open Map description: Open your map interface and guide your owner. - noSpawn: true components: - type: InstantAction checkCanInteract: false diff --git a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml index f6b2b0a70c..58f7e01550 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml @@ -80,7 +80,6 @@ id: ActionBibleSummon name: Summon familiar description: Summon a familiar that will aid you and gain humanlike intelligence once inhabited by a soul. - noSpawn: true components: - type: InstantAction icon: { sprite: Clothing/Head/Hats/witch.rsi, state: icon } diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml index 07206711d9..74e91a768c 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml @@ -32,7 +32,6 @@ id: ActionBorgSwapModule name: Swap Module description: Select this module, enabling you to use the tools it provides. - noSpawn: true components: - type: InstantAction itemIconStyle: BigItem diff --git a/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml index 04f8b9f9f6..6fee48daf1 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml @@ -62,7 +62,6 @@ id: ActionToggleJetpack name: Toggle jetpack description: Toggles the jetpack, giving you movement outside the station. - noSpawn: true components: - type: InstantAction icon: diff --git a/Resources/Prototypes/Magic/event_spells.yml b/Resources/Prototypes/Magic/event_spells.yml index e59e1b2db8..01006b4ffe 100644 --- a/Resources/Prototypes/Magic/event_spells.yml +++ b/Resources/Prototypes/Magic/event_spells.yml @@ -2,7 +2,6 @@ id: ActionSummonGhosts name: Summon Ghosts description: Makes all current ghosts permanently invisible - noSpawn: true components: - type: InstantAction useDelay: 120 diff --git a/Resources/Prototypes/Magic/forcewall_spells.yml b/Resources/Prototypes/Magic/forcewall_spells.yml index d3d8fef760..f1865cf722 100644 --- a/Resources/Prototypes/Magic/forcewall_spells.yml +++ b/Resources/Prototypes/Magic/forcewall_spells.yml @@ -2,7 +2,6 @@ id: ActionForceWall name: Forcewall description: Creates a magical barrier. - noSpawn: true components: - type: InstantAction useDelay: 10 diff --git a/Resources/Prototypes/Magic/knock_spell.yml b/Resources/Prototypes/Magic/knock_spell.yml index e2c3dcfd4c..5ba456d3be 100644 --- a/Resources/Prototypes/Magic/knock_spell.yml +++ b/Resources/Prototypes/Magic/knock_spell.yml @@ -2,7 +2,6 @@ id: ActionKnock name: Knock description: This spell opens nearby doors. - noSpawn: true components: - type: InstantAction useDelay: 10 diff --git a/Resources/Prototypes/Magic/projectile_spells.yml b/Resources/Prototypes/Magic/projectile_spells.yml index b8db7557bb..71bbc096c5 100644 --- a/Resources/Prototypes/Magic/projectile_spells.yml +++ b/Resources/Prototypes/Magic/projectile_spells.yml @@ -2,7 +2,6 @@ id: ActionFireball name: Fireball description: Fires an explosive fireball towards the clicked location. - noSpawn: true components: - type: Magic - type: WorldTargetAction @@ -29,7 +28,6 @@ parent: ActionFireball name: Fireball II description: Fires a fireball, but faster! - noSpawn: true components: - type: WorldTargetAction useDelay: 10 @@ -52,7 +50,6 @@ parent: ActionFireball name: Fireball III description: The fastest fireball in the west! - noSpawn: true components: - type: WorldTargetAction useDelay: 8 diff --git a/Resources/Prototypes/Magic/rune_spells.yml b/Resources/Prototypes/Magic/rune_spells.yml index 42022f5785..7ba357e7c1 100644 --- a/Resources/Prototypes/Magic/rune_spells.yml +++ b/Resources/Prototypes/Magic/rune_spells.yml @@ -2,7 +2,6 @@ id: ActionFlashRune name: Flash Rune description: Summons a rune that flashes if used. - noSpawn: true components: - type: InstantAction useDelay: 10 @@ -17,7 +16,6 @@ id: ActionExplosionRune name: Explosion Rune description: Summons a rune that explodes if used. - noSpawn: true components: - type: InstantAction useDelay: 20 @@ -32,7 +30,6 @@ id: ActionIgniteRune name: Ignite Rune description: Summons a rune that ignites if used. - noSpawn: true components: - type: InstantAction useDelay: 15 @@ -47,7 +44,6 @@ id: ActionStunRune name: Stun Rune description: Summons a rune that stuns if used. - noSpawn: true components: - type: InstantAction useDelay: 10 diff --git a/Resources/Prototypes/Magic/smite_spells.yml b/Resources/Prototypes/Magic/smite_spells.yml index e629e56505..10f5bdd538 100644 --- a/Resources/Prototypes/Magic/smite_spells.yml +++ b/Resources/Prototypes/Magic/smite_spells.yml @@ -2,7 +2,6 @@ id: ActionSmite name: Smite description: Instantly gibs a target. - noSpawn: true components: - type: EntityTargetAction useDelay: 60 diff --git a/Resources/Prototypes/Magic/spawn_spells.yml b/Resources/Prototypes/Magic/spawn_spells.yml index 3f8148b83c..76674d5bfa 100644 --- a/Resources/Prototypes/Magic/spawn_spells.yml +++ b/Resources/Prototypes/Magic/spawn_spells.yml @@ -2,7 +2,6 @@ id: ActionSpawnMagicarpSpell name: Summon Magicarp description: This spell summons three Magi-Carp to your aid! May or may not turn on user. - noSpawn: true components: - type: WorldTargetAction useDelay: 10 diff --git a/Resources/Prototypes/Magic/staves.yml b/Resources/Prototypes/Magic/staves.yml index ef94a3910f..ccabb516fd 100644 --- a/Resources/Prototypes/Magic/staves.yml +++ b/Resources/Prototypes/Magic/staves.yml @@ -34,7 +34,6 @@ - type: entity id: ActionRgbLight - noSpawn: true components: - type: EntityTargetAction whitelist: { components: [ PointLight ] } diff --git a/Resources/Prototypes/Magic/teleport_spells.yml b/Resources/Prototypes/Magic/teleport_spells.yml index cc89cf8ee0..6f1ed9a6e4 100644 --- a/Resources/Prototypes/Magic/teleport_spells.yml +++ b/Resources/Prototypes/Magic/teleport_spells.yml @@ -2,7 +2,6 @@ id: ActionBlink name: Blink description: Teleport to the clicked location. - noSpawn: true components: - type: WorldTargetAction useDelay: 10 diff --git a/Resources/Prototypes/Magic/utility_spells.yml b/Resources/Prototypes/Magic/utility_spells.yml index dccdda3789..90bcdc7487 100644 --- a/Resources/Prototypes/Magic/utility_spells.yml +++ b/Resources/Prototypes/Magic/utility_spells.yml @@ -2,7 +2,6 @@ id: ActionChargeSpell name: Charge description: Adds a charge back to your wand - noSpawn: true components: - type: InstantAction useDelay: 30 diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml index 1eac292eee..27a164210b 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml @@ -33,7 +33,6 @@ id: ActionMimeInvisibleWall name: Create Invisible Wall description: Create an invisible wall in front of you, if placeable there. - noSpawn: true components: - type: InstantAction priority: -1 From 77a3d6c6f12e10031f6a6e5723705c515389279b Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 3 Jun 2024 02:59:22 +1200 Subject: [PATCH 02/63] Update engine to v224.0.1 (#28520) --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index ff4548f108..f648218756 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit ff4548f108a5b11e1a81cb7c01f7462400e4af2b +Subproject commit f64821875655dfec4e2c951d5c22c0db873fe86e From 9a23a6c695400d2b583b1a77e503cd366fb28cdc Mon Sep 17 00:00:00 2001 From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:52:40 -0400 Subject: [PATCH 03/63] Fix mid round antags not starting (#28523) --- Content.Server/StationEvents/Events/StationEventSystem.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Content.Server/StationEvents/Events/StationEventSystem.cs b/Content.Server/StationEvents/Events/StationEventSystem.cs index 38390cedb1..35dc646bce 100644 --- a/Content.Server/StationEvents/Events/StationEventSystem.cs +++ b/Content.Server/StationEvents/Events/StationEventSystem.cs @@ -98,7 +98,11 @@ public abstract class StationEventSystem : GameRuleSystem where T : ICompo if (!GameTicker.IsGameRuleAdded(uid, ruleData)) continue; - if (stationEvent.EndTime != null && Timing.CurTime >= stationEvent.EndTime && GameTicker.IsGameRuleActive(uid, ruleData)) + if (!GameTicker.IsGameRuleActive(uid, ruleData) && !HasComp(uid)) + { + GameTicker.StartGameRule(uid, ruleData); + } + else if (stationEvent.EndTime != null && Timing.CurTime >= stationEvent.EndTime && GameTicker.IsGameRuleActive(uid, ruleData)) { GameTicker.EndGameRule(uid, ruleData); } From 6b40b5269e1c8ee9c7475ec753b3f9baf2931cea Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 2 Jun 2024 16:53:47 +0000 Subject: [PATCH 04/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a6e7cbbc71..0bfd57a3b9 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Fix store refunds. - type: Fix - id: 6165 - time: '2024-03-16T14:06:17.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26173 - author: LordCarve changes: - message: Decayed anomalies no longer show as having gone supercritical in logs. @@ -3853,3 +3846,10 @@ id: 6664 time: '2024-06-02T04:17:53.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27369 +- author: AJCM-git + changes: + - message: Midround antags work again + type: Fix + id: 6665 + time: '2024-06-02T16:52:40.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28523 From 66835ac84e01890aaffaa823b9d08cb25758f66f Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Sun, 2 Jun 2024 19:30:27 +0200 Subject: [PATCH 05/63] Beacons no longer glitch off on grid split (#28518) --- Content.Server/Pinpointer/NavMapSystem.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Content.Server/Pinpointer/NavMapSystem.cs b/Content.Server/Pinpointer/NavMapSystem.cs index dba964753f..424b6427de 100644 --- a/Content.Server/Pinpointer/NavMapSystem.cs +++ b/Content.Server/Pinpointer/NavMapSystem.cs @@ -237,6 +237,16 @@ public sealed partial class NavMapSystem : SharedNavMapSystem component.Chunks.Clear(); component.Beacons.Clear(); + // Refresh beacons + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var qUid, out var qNavComp, out var qTransComp)) + { + if (qTransComp.ParentUid != uid) + continue; + + UpdateNavMapBeaconData(qUid, qNavComp); + } + // Loop over all tiles var tileRefs = _mapSystem.GetAllTiles(uid, mapGrid); From 054118757b619c5b0307e10c16797d166c639dc7 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 2 Jun 2024 17:31:33 +0000 Subject: [PATCH 06/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0bfd57a3b9..ec5569327f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: LordCarve - changes: - - message: Decayed anomalies no longer show as having gone supercritical in logs. - type: Fix - id: 6166 - time: '2024-03-16T17:31:21.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26180 - author: Velcroboy changes: - message: Tweaked gas canisters to pass through cargo flaps. @@ -3853,3 +3846,10 @@ id: 6665 time: '2024-06-02T16:52:40.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28523 +- author: Errant-4 + changes: + - message: Map labels no longer suddenly disappear for the rest of the round. + type: Fix + id: 6666 + time: '2024-06-02T17:30:27.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28518 From c5918648668e50cd3cce7a651f978d3bc2bdafee Mon Sep 17 00:00:00 2001 From: UBlueberry <161545003+UBlueberry@users.noreply.github.com> Date: Sun, 2 Jun 2024 15:13:57 -0400 Subject: [PATCH 07/63] Drawl capitalization coldfix (part 2: rise of accidentally commiting to master) (#26639) fixed finally yay --- .../EntitySystems/SouthernAccentSystem.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Content.Server/Speech/EntitySystems/SouthernAccentSystem.cs b/Content.Server/Speech/EntitySystems/SouthernAccentSystem.cs index b9260eb844..c1f8a0be30 100644 --- a/Content.Server/Speech/EntitySystems/SouthernAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/SouthernAccentSystem.cs @@ -5,9 +5,12 @@ namespace Content.Server.Speech.EntitySystems; public sealed class SouthernAccentSystem : EntitySystem { - private static readonly Regex RegexIng = new(@"ing\b"); - private static readonly Regex RegexAnd = new(@"\band\b"); - private static readonly Regex RegexDve = new("d've"); + private static readonly Regex RegexLowerIng = new(@"ing\b"); + private static readonly Regex RegexUpperIng = new(@"ING\b"); + private static readonly Regex RegexLowerAnd = new(@"\band\b"); + private static readonly Regex RegexUpperAnd = new(@"\bAND\b"); + private static readonly Regex RegexLowerDve = new(@"d've\b"); + private static readonly Regex RegexUpperDve = new(@"D'VE\b"); [Dependency] private readonly ReplacementAccentSystem _replacement = default!; @@ -24,9 +27,12 @@ public sealed class SouthernAccentSystem : EntitySystem message = _replacement.ApplyReplacements(message, "southern"); //They shoulda started runnin' an' hidin' from me! - message = RegexIng.Replace(message, "in'"); - message = RegexAnd.Replace(message, "an'"); - message = RegexDve.Replace(message, "da"); + message = RegexLowerIng.Replace(message, "in'"); + message = RegexUpperIng.Replace(message, "IN'"); + message = RegexLowerAnd.Replace(message, "an'"); + message = RegexUpperAnd.Replace(message, "AN'"); + message = RegexLowerDve.Replace(message, "da"); + message = RegexUpperDve.Replace(message, "DA"); args.Message = message; } }; From 4eadbbc39d2df69aace020583f1f5c57d0826c85 Mon Sep 17 00:00:00 2001 From: Killerqu00 <47712032+Killerqu00@users.noreply.github.com> Date: Sun, 2 Jun 2024 21:40:02 +0200 Subject: [PATCH 08/63] fix typos in bonfire descriptions (#28515) * fix typo * a --- Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml b/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml index cc69a6304d..29efdaea5d 100644 --- a/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml +++ b/Resources/Prototypes/Entities/Structures/Decoration/bonfire.yml @@ -2,7 +2,7 @@ id: Bonfire parent: BaseStructure name: bonfire - description: What can be better then late evening under the sky with guitar and friends. + description: What can be better than a late evening under the sky with guitar and friends? components: - type: Sprite noRot: true From 81821e87af5e14c6399482c0cc0f34aa73b86a02 Mon Sep 17 00:00:00 2001 From: stellar-novas Date: Sun, 2 Jun 2024 15:49:31 -0400 Subject: [PATCH 09/63] Update to nixpkgs 24.05 (#28529) --- flake.lock | 14 +++++++------- flake.nix | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/flake.lock b/flake.lock index 6ab38fa41b..7baaa468ea 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -20,16 +20,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1708210246, - "narHash": "sha256-Q8L9XwrBK53fbuuIFMbjKvoV7ixfLFKLw4yV+SD28Y8=", + "lastModified": 1717352157, + "narHash": "sha256-hbBzucWOhwxt3QzeAyUojtD6/aHH81JssDfhFfmqOy0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "69405156cffbdf2be50153f13cbdf9a0bea38e49", + "rev": "44f538ab12e2726af450877a5529f4fd88ddb0fb", "type": "github" }, "original": { "owner": "NixOS", - "ref": "release-23.11", + "ref": "release-24.05", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index e2e119eb99..095e6b017c 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,7 @@ { description = "Development environment for Space Station 14"; - inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-23.11"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-24.05"; inputs.flake-utils.url = "github:numtide/flake-utils"; outputs = { self, nixpkgs, flake-utils }: From 504208c6656bb7e56681c23e3e46092c3205c940 Mon Sep 17 00:00:00 2001 From: Voomra Date: Mon, 3 Jun 2024 02:51:19 +0300 Subject: [PATCH 10/63] fix: localize PraySystem UI (#28535) tweak: localize PraySystem UI --- Content.Server/Prayer/PrayerSystem.cs | 2 +- Resources/Locale/en-US/prayers/prayers.ftl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/Prayer/PrayerSystem.cs b/Content.Server/Prayer/PrayerSystem.cs index c8ef368dad..3b1ec3fa08 100644 --- a/Content.Server/Prayer/PrayerSystem.cs +++ b/Content.Server/Prayer/PrayerSystem.cs @@ -54,7 +54,7 @@ public sealed class PrayerSystem : EntitySystem return; } - _quickDialog.OpenDialog(actor.PlayerSession, Loc.GetString(comp.Verb), "Message", (string message) => + _quickDialog.OpenDialog(actor.PlayerSession, Loc.GetString(comp.Verb), Loc.GetString("prayer-popup-notify-pray-ui-message"), (string message) => { Pray(actor.PlayerSession, comp, message); }); diff --git a/Resources/Locale/en-US/prayers/prayers.ftl b/Resources/Locale/en-US/prayers/prayers.ftl index 07713bc821..532ba4954f 100644 --- a/Resources/Locale/en-US/prayers/prayers.ftl +++ b/Resources/Locale/en-US/prayers/prayers.ftl @@ -13,3 +13,4 @@ prayer-popup-notify-centcom-sent = You left a voicemail message for Central Comm prayer-popup-notify-syndicate-sent = You left a voicemail message for Syndicate High Command... prayer-popup-notify-pray-sent = Your message has been sent to the gods... prayer-popup-notify-pray-locked = You don't feel worthy enough... +prayer-popup-notify-pray-ui-message = Message From 947ed7bb22655e2499f27e521766e094663b13dc Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 2 Jun 2024 23:52:25 +0000 Subject: [PATCH 11/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index ec5569327f..53f9f65ab3 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Velcroboy - changes: - - message: Tweaked gas canisters to pass through cargo flaps. - type: Tweak - id: 6167 - time: '2024-03-17T00:55:32.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26193 - author: metalgearsloth changes: - message: Fix ID cards sometimes not loading properly. @@ -3853,3 +3846,10 @@ id: 6666 time: '2024-06-02T17:30:27.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28518 +- author: Voomra + changes: + - message: localize Pray UI + type: Fix + id: 6667 + time: '2024-06-02T23:51:19.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28535 From 307a0428c7fa324a69ec93fc0faf2a3679cd83de Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Mon, 3 Jun 2024 03:05:18 +0200 Subject: [PATCH 12/63] Shut up a child throwing a tantrum (#28538) --- Resources/Credits/GitHub.txt | 2 +- Tools/contribs_shared.ps1 | 2 ++ Tools/dump_github_contributors.ps1 | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index b3627580b1..f240c95247 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, Afrokada, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlexUm418, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, BellwetherLogic, BGare, bhenrich, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blueDev2, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CakeQ, Callmore, CaptainSqrBeard, Carbonhell, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, Ciac32, clement-or, Clyybber, Cojoke-dot, ColdAutumnRain, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, deepdarkdepths, deepy, Delete69, deltanedas, DerbyX, DexlerXD, Doctor-Cpu, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DoutorWhite, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, DuskyJay, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, gusxyz, Gyrandola, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, hitomishirichan, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, j-giebel, Jackal298, Jackrost, jamessimo, janekvap, Jark255, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, joelhed, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTether, JustinTrotter, K-Dynamic, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, luckyshotpictures, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Mangohydra, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, pigeonpeas, pissdemon, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Psychpsyo, psykzz, PuroSlavKing, PursuitInAshes, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, RumiTiger, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, SethLafuente, ShadowCommander, Shadowtheprotogen546, shampunj, SignalWalker, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, snebl, Snowni, snowsignal, SonicHDC, SoulFN, SoulSloth, SpaceManiac, SpeltIncorrectyl, SphiraI, spoogemonster, ssdaniel24, Stealthbomber16, StrawberryMoses, superjj18, SweptWasTaken, Szunti, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, Terraspark4941, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UBlueberry, UKNOWH, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, volundr-, Voomra, Vordenburg, vulppine, wafehling, waylon531, weaversam8, whateverusername0, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, Afrokada, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlexUm418, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, BellwetherLogic, BGare, bhenrich, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blueDev2, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CakeQ, Callmore, CaptainSqrBeard, Carbonhell, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, Ciac32, clement-or, Clyybber, Cojoke-dot, ColdAutumnRain, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, deepdarkdepths, deepy, Delete69, deltanedas, DerbyX, DexlerXD, Doctor-Cpu, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DoutorWhite, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, DuskyJay, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, Ghagliiarghii, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, gusxyz, Gyrandola, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, hitomishirichan, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Huxellberger, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, j-giebel, Jackal298, Jackrost, jamessimo, janekvap, Jark255, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, joelhed, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTether, JustinTrotter, K-Dynamic, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, luckyshotpictures, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Mangohydra, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, pigeonpeas, pissdemon, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Psychpsyo, psykzz, PuroSlavKing, PursuitInAshes, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, RamZ, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, RumiTiger, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, SethLafuente, ShadowCommander, Shadowtheprotogen546, shampunj, SignalWalker, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, snebl, Snowni, snowsignal, SonicHDC, SoulFN, SoulSloth, SpaceManiac, SpeltIncorrectyl, SphiraI, spoogemonster, ssdaniel24, Stealthbomber16, StrawberryMoses, superjj18, SweptWasTaken, Szunti, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, Terraspark4941, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UBlueberry, UKNOWH, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, volundr-, Voomra, Vordenburg, vulppine, wafehling, waylon531, weaversam8, whateverusername0, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem diff --git a/Tools/contribs_shared.ps1 b/Tools/contribs_shared.ps1 index ba97c50a9a..a3638b41b8 100644 --- a/Tools/contribs_shared.ps1 +++ b/Tools/contribs_shared.ps1 @@ -12,3 +12,5 @@ $ignore = @{ "ZDDM" = $true "TYoung86" = $true } + +$add = @("RamZ") diff --git a/Tools/dump_github_contributors.ps1 b/Tools/dump_github_contributors.ps1 index 51d8612b28..10e74bcf0b 100755 --- a/Tools/dump_github_contributors.ps1 +++ b/Tools/dump_github_contributors.ps1 @@ -29,7 +29,7 @@ function load_contribs([string] $repo) $engineJson = load_contribs("space-wizards/RobustToolbox") $contentJson = load_contribs("space-wizards/space-station-14") -($engineJson).login + ($contentJson).login ` +($engineJson).login + ($contentJson).login + ($add) ` | select -unique ` | Where-Object { -not $ignore[$_] }` | ForEach-Object { if($replacements[$_] -eq $null){ $_ } else { $replacements[$_] }} ` From 9dbdacda9533304004382ebf5f8c63a32e50916e Mon Sep 17 00:00:00 2001 From: Whisper <121047731+QuietlyWhisper@users.noreply.github.com> Date: Sun, 2 Jun 2024 22:18:49 -0400 Subject: [PATCH 13/63] Rename admin cloak to weh cloak (#28540) --- Resources/Prototypes/Entities/Clothing/Neck/cloaks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Clothing/Neck/cloaks.yml b/Resources/Prototypes/Entities/Clothing/Neck/cloaks.yml index 35a793791c..a329c4034b 100644 --- a/Resources/Prototypes/Entities/Clothing/Neck/cloaks.yml +++ b/Resources/Prototypes/Entities/Clothing/Neck/cloaks.yml @@ -8,7 +8,7 @@ sprite: Clothing/Neck/Cloaks/centcomcloakformal.rsi - type: StealTarget stealGroup: HeadCloak # leaving this here because I suppose it might be interesting? - + - type: entity parent: ClothingNeckBase id: ClothingNeckCloakCap @@ -118,7 +118,7 @@ - type: entity parent: ClothingNeckBase id: ClothingNeckCloakAdmin - name: admin cloak + name: weh cloak description: Weh! components: - type: Sprite From 7ecff3e6996c4141e70611f4fb7585d1fcb983e5 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 02:19:55 +0000 Subject: [PATCH 14/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 53f9f65ab3..b602964081 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Fix ID cards sometimes not loading properly. - type: Fix - id: 6168 - time: '2024-03-17T01:10:59.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26195 - author: 21Melkuu changes: - message: Add new explosion-proof backpack in aplink. @@ -3853,3 +3846,10 @@ id: 6667 time: '2024-06-02T23:51:19.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28535 +- author: Whisper + changes: + - message: Renamed the player-obtainable "admin cloak" to "weh cloak". + type: Tweak + id: 6668 + time: '2024-06-03T02:18:49.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28540 From 509e3aedf7b91c1e1d11e5a885608bc92909f552 Mon Sep 17 00:00:00 2001 From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:28:38 -0400 Subject: [PATCH 15/63] RespawnRuleSystem tweaks. (#28528) --- .../Components/RespawnDeadRuleComponent.cs | 5 + .../Components/RespawnTrackerComponent.cs | 12 +- .../GameTicking/Rules/DeathMatchRuleSystem.cs | 4 +- .../GameTicking/Rules/RespawnRuleSystem.cs | 115 +++++++++--------- Resources/Prototypes/GameRules/roundstart.yml | 11 ++ 5 files changed, 84 insertions(+), 63 deletions(-) diff --git a/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs index fafe811dd9..f6e4a3b129 100644 --- a/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/RespawnDeadRuleComponent.cs @@ -6,4 +6,9 @@ [RegisterComponent, Access(typeof(RespawnRuleSystem))] public sealed partial class RespawnDeadRuleComponent : Component { + /// + /// Whether or not we want to add everyone who dies to the respawn tracker + /// + [DataField] + public bool AlwaysRespawnDead; } diff --git a/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs b/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs index 3d338c2d13..b9c8fe1096 100644 --- a/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/RespawnTrackerComponent.cs @@ -13,18 +13,24 @@ public sealed partial class RespawnTrackerComponent : Component /// A list of the people that should be respawned. /// Used to make sure that we don't respawn aghosts or observers. /// - [DataField("players")] + [DataField] public HashSet Players = new(); /// /// The delay between dying and respawning. /// - [DataField("respawnDelay")] + [DataField] public TimeSpan RespawnDelay = TimeSpan.Zero; /// /// A dictionary of player netuserids and when they will respawn. /// - [DataField("respawnQueue")] + [DataField] public Dictionary RespawnQueue = new(); + + /// + /// Whether or not to delete the original body when respawning + /// + [DataField] + public bool DeleteBody = true; } diff --git a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs index ad7c63ff58..9e3203d170 100644 --- a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs @@ -56,7 +56,7 @@ public sealed class DeathMatchRuleSystem : GameRuleSystem(mob); - _respawn.AddToTracker(ev.Player.UserId, uid, tracker); + _respawn.AddToTracker(ev.Player.UserId, (uid, tracker)); _point.EnsurePlayer(ev.Player.UserId, uid, point); @@ -73,7 +73,7 @@ public sealed class DeathMatchRuleSystem : GameRuleSystem SubscribeLocalEvent(OnMobStateChanged); } - private void OnSuicide(SuicideEvent ev) - { - if (!TryComp(ev.Victim, out var actor)) - return; - - var query = EntityQueryEnumerator(); - while (query.MoveNext(out _, out var respawn)) - { - if (respawn.Players.Remove(actor.PlayerSession.UserId)) - QueueDel(ev.Victim); - } - } - - private void OnMobStateChanged(MobStateChangedEvent args) - { - if (args.NewMobState == MobState.Alive) - return; - - if (!TryComp(args.Target, out var actor)) - return; - - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out _, out var rule)) - { - if (!GameTicker.IsGameRuleActive(uid, rule)) - continue; - - if (RespawnPlayer(args.Target, uid, actor: actor)) - break; - } - } - public override void Update(float frameTime) { base.Update(frameTime); @@ -75,8 +44,7 @@ public sealed class RespawnRuleSystem : GameRuleSystem foreach (var tracker in EntityQuery()) { - var queue = new Dictionary(tracker.RespawnQueue); - foreach (var (player, time) in queue) + foreach (var (player, time) in tracker.RespawnQueue) { if (_timing.CurTime < time) continue; @@ -92,53 +60,84 @@ public sealed class RespawnRuleSystem : GameRuleSystem } } - /// - /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die. - /// - public void AddToTracker(EntityUid player, EntityUid tracker, RespawnTrackerComponent? component = null, ActorComponent? actor = null) + private void OnSuicide(SuicideEvent ev) { - if (!Resolve(tracker, ref component) || !Resolve(player, ref actor, false)) - return; + if (!TryComp(ev.Victim, out var actor)) + return; - AddToTracker(actor.PlayerSession.UserId, tracker, component); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out _, out var respawn)) + { + if (respawn.Players.Remove(actor.PlayerSession.UserId)) + QueueDel(ev.Victim); + } } - /// - /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die. - /// - public void AddToTracker(NetUserId id, EntityUid tracker, RespawnTrackerComponent? component = null) + private void OnMobStateChanged(MobStateChangedEvent args) { - if (!Resolve(tracker, ref component)) + if (args.NewMobState != MobState.Dead) return; - component.Players.Add(id); + if (!TryComp(args.Target, out var actor)) + return; + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var respawnRule, out var tracker, out var rule)) + { + if (!GameTicker.IsGameRuleActive(uid, rule)) + continue; + + if (respawnRule.AlwaysRespawnDead) + AddToTracker(actor.PlayerSession.UserId, (uid, tracker)); + if (RespawnPlayer((args.Target, actor), (uid, tracker))) + break; + } } /// /// Attempts to directly respawn a player, skipping the lobby screen. /// - public bool RespawnPlayer(EntityUid player, EntityUid respawnTracker, RespawnTrackerComponent? component = null, ActorComponent? actor = null) + public bool RespawnPlayer(Entity player, Entity respawnTracker) { - if (!Resolve(respawnTracker, ref component) || !Resolve(player, ref actor, false)) + if (!respawnTracker.Comp.Players.Contains(player.Comp.PlayerSession.UserId) || respawnTracker.Comp.RespawnQueue.ContainsKey(player.Comp.PlayerSession.UserId)) return false; - if (!component.Players.Contains(actor.PlayerSession.UserId) || component.RespawnQueue.ContainsKey(actor.PlayerSession.UserId)) - return false; - - if (component.RespawnDelay == TimeSpan.Zero) + if (respawnTracker.Comp.RespawnDelay == TimeSpan.Zero) { if (_station.GetStations().FirstOrNull() is not { } station) return false; - QueueDel(player); - GameTicker.MakeJoinGame(actor.PlayerSession, station, silent: true); + if (respawnTracker.Comp.DeleteBody) + QueueDel(player); + GameTicker.MakeJoinGame(player.Comp.PlayerSession, station, silent: true); return false; } - var msg = Loc.GetString("rule-respawn-in-seconds", ("second", component.RespawnDelay.TotalSeconds)); + var msg = Loc.GetString("rule-respawn-in-seconds", ("second", respawnTracker.Comp.RespawnDelay.TotalSeconds)); var wrappedMsg = Loc.GetString("chat-manager-server-wrap-message", ("message", msg)); - _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMsg, respawnTracker, false, actor.PlayerSession.Channel, Color.LimeGreen); - component.RespawnQueue[actor.PlayerSession.UserId] = _timing.CurTime + component.RespawnDelay; + _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMsg, respawnTracker, false, player.Comp.PlayerSession.Channel, Color.LimeGreen); + + respawnTracker.Comp.RespawnQueue[player.Comp.PlayerSession.UserId] = _timing.CurTime + respawnTracker.Comp.RespawnDelay; + return true; } + + /// + /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die. + /// + public void AddToTracker(Entity player, Entity respawnTracker) + { + if (!Resolve(respawnTracker, ref respawnTracker.Comp) || !Resolve(player, ref player.Comp, false)) + return; + + AddToTracker(player.Comp.PlayerSession.UserId, (respawnTracker, respawnTracker.Comp)); + } + + /// + /// Adds a given player to the respawn tracker, ensuring that they are respawned if they die. + /// + public void AddToTracker(NetUserId id, Entity tracker) + { + tracker.Comp.Players.Add(id); + } } diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index 93350163f6..cf2c5b2f47 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -5,6 +5,17 @@ components: - type: GameRule +- type: entity + noSpawn: true + parent: BaseGameRule + id: RespawnDeadRule + components: + - type: RespawnDeadRule + alwaysRespawnDead: true + - type: RespawnTracker + respawnDelay: 10 + deleteBody: false + - type: entity noSpawn: true parent: BaseGameRule From 31eb3ed62ce607205aaac59416c53f7f2c40da97 Mon Sep 17 00:00:00 2001 From: Verm <32827189+Vermidia@users.noreply.github.com> Date: Sun, 2 Jun 2024 22:28:53 -0500 Subject: [PATCH 16/63] Welding tweaks (#27959) --- .../Configurable/ConfigurationSystem.cs | 6 +- .../DamageOnToolInteractComponent.cs | 27 +++---- .../Systems/DamageOnToolInteractSystem.cs | 5 +- .../Mech/Systems/MechAssemblySystem.cs | 4 +- Content.Server/Mech/Systems/MechSystem.cs | 4 +- .../PneumaticCannon/PneumaticCannonSystem.cs | 8 +- .../Melee/EnergySword/EnergySwordSystem.cs | 6 +- .../ArtifactElectricityTriggerSystem.cs | 4 +- .../EntitySystems/AnchorableSystem.cs | 2 +- .../EntitySystems/EncryptionKeySystem.cs | 4 +- .../Tools/Components/ToolComponent.cs | 75 ++++++++----------- .../Components/ToolRefinableComponent.cs | 11 +-- .../Tools/Systems/SharedToolSystem.Welder.cs | 22 +++--- .../Tools/Systems/SharedToolSystem.cs | 3 +- .../Tools/Systems/ToolRefinableSystem.cs | 20 +++-- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 2 +- .../Prototypes/Entities/Mobs/NPCs/xeno.yml | 2 +- .../Consumable/Drinks/drinks_bottles.yml | 2 +- .../Objects/Consumable/Drinks/drinks_cans.yml | 2 +- .../Entities/Objects/Materials/shards.yml | 10 +-- .../Entities/Objects/Misc/broken_bottle.yml | 2 +- .../Objects/Misc/fire_extinguisher.yml | 2 +- .../Entities/Objects/Power/lights.yml | 14 ++-- .../Objects/Specific/Medical/surgery.yml | 8 +- .../Entities/Objects/Tools/cowtools.yml | 10 +-- .../Entities/Objects/Tools/gas_tanks.yml | 2 +- .../Entities/Objects/Tools/jaws_of_life.yml | 4 +- .../Entities/Objects/Tools/tools.yml | 4 +- .../Entities/Objects/Tools/welders.yml | 4 +- .../Objects/Weapons/Melee/baseball_bat.yml | 2 +- .../Structures/Storage/Tanks/tanks.yml | 4 +- .../Structures/Wallmounts/walldispenser.yml | 3 +- .../XenoArch/Effects/utility_effects.yml | 2 +- 33 files changed, 139 insertions(+), 141 deletions(-) rename Content.Server/Construction/Components/WelderRefinableComponent.cs => Content.Shared/Tools/Components/ToolRefinableComponent.cs (74%) rename Content.Server/Construction/RefiningSystem.cs => Content.Shared/Tools/Systems/ToolRefinableSystem.cs (59%) diff --git a/Content.Server/Configurable/ConfigurationSystem.cs b/Content.Server/Configurable/ConfigurationSystem.cs index 5f5f1ef7d1..bf89c3f7ed 100644 --- a/Content.Server/Configurable/ConfigurationSystem.cs +++ b/Content.Server/Configurable/ConfigurationSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Configurable; using Content.Shared.Interaction; using Content.Shared.Tools.Components; +using Content.Shared.Tools.Systems; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.Player; @@ -11,6 +12,7 @@ namespace Content.Server.Configurable; public sealed class ConfigurationSystem : EntitySystem { [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; + [Dependency] private readonly SharedToolSystem _toolSystem = default!; public override void Initialize() { @@ -28,7 +30,7 @@ public sealed class ConfigurationSystem : EntitySystem if (args.Handled) return; - if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.Contains(component.QualityNeeded)) + if (!_toolSystem.HasQuality(args.Used, component.QualityNeeded)) return; args.Handled = _uiSystem.TryOpenUi(uid, ConfigurationUiKey.Key, args.User); @@ -68,7 +70,7 @@ public sealed class ConfigurationSystem : EntitySystem private void OnInsert(EntityUid uid, ConfigurationComponent component, ContainerIsInsertingAttemptEvent args) { - if (!TryComp(args.EntityUid, out ToolComponent? tool) || !tool.Qualities.Contains(component.QualityNeeded)) + if (!_toolSystem.HasQuality(args.EntityUid, component.QualityNeeded)) return; args.Cancel(); diff --git a/Content.Server/Damage/Components/DamageOnToolInteractComponent.cs b/Content.Server/Damage/Components/DamageOnToolInteractComponent.cs index e54090cdbb..547c29a202 100644 --- a/Content.Server/Damage/Components/DamageOnToolInteractComponent.cs +++ b/Content.Server/Damage/Components/DamageOnToolInteractComponent.cs @@ -1,22 +1,19 @@ using Content.Shared.Damage; using Content.Shared.Tools; -using Robust.Shared.Utility; +using Robust.Shared.Prototypes; -namespace Content.Server.Damage.Components +namespace Content.Server.Damage.Components; + +[RegisterComponent] +public sealed partial class DamageOnToolInteractComponent : Component { - [RegisterComponent] - public sealed partial class DamageOnToolInteractComponent : Component - { - [DataField("tools")] - public PrototypeFlags Tools { get; private set; } = new (); + [DataField] + public ProtoId Tools { get; private set; } - // TODO: Remove this snowflake stuff, make damage per-tool quality perhaps? - [DataField("weldingDamage")] - [ViewVariables(VVAccess.ReadWrite)] - public DamageSpecifier? WeldingDamage { get; private set; } + // TODO: Remove this snowflake stuff, make damage per-tool quality perhaps? + [DataField] + public DamageSpecifier? WeldingDamage { get; private set; } - [DataField("defaultDamage")] - [ViewVariables(VVAccess.ReadWrite)] - public DamageSpecifier? DefaultDamage { get; private set; } - } + [DataField] + public DamageSpecifier? DefaultDamage { get; private set; } } diff --git a/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs b/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs index 42676c1891..5980455e49 100644 --- a/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs +++ b/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Damage; using Content.Shared.Database; using Content.Shared.Interaction; using Content.Shared.Tools.Components; +using Content.Shared.Tools.Systems; using ItemToggleComponent = Content.Shared.Item.ItemToggle.Components.ItemToggleComponent; namespace Content.Server.Damage.Systems @@ -12,6 +13,7 @@ namespace Content.Server.Damage.Systems { [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedToolSystem _toolSystem = default!; public override void Initialize() { @@ -42,8 +44,7 @@ namespace Content.Server.Damage.Systems args.Handled = true; } else if (component.DefaultDamage is {} damage - && EntityManager.TryGetComponent(args.Used, out ToolComponent? tool) - && tool.Qualities.ContainsAny(component.Tools)) + && _toolSystem.HasQuality(args.Used, component.Tools)) { var dmg = _damageableSystem.TryChangeDamage(args.Target, damage, origin: args.User); diff --git a/Content.Server/Mech/Systems/MechAssemblySystem.cs b/Content.Server/Mech/Systems/MechAssemblySystem.cs index c1fff819b4..4b408343b7 100644 --- a/Content.Server/Mech/Systems/MechAssemblySystem.cs +++ b/Content.Server/Mech/Systems/MechAssemblySystem.cs @@ -2,6 +2,7 @@ using Content.Shared.Interaction; using Content.Shared.Tag; using Content.Shared.Tools.Components; +using Content.Shared.Tools.Systems; using Robust.Server.Containers; using Robust.Shared.Containers; @@ -15,6 +16,7 @@ public sealed class MechAssemblySystem : EntitySystem { [Dependency] private readonly ContainerSystem _container = default!; [Dependency] private readonly TagSystem _tag = default!; + [Dependency] private readonly SharedToolSystem _toolSystem = default!; /// public override void Initialize() @@ -30,7 +32,7 @@ public sealed class MechAssemblySystem : EntitySystem private void OnInteractUsing(EntityUid uid, MechAssemblyComponent component, InteractUsingEvent args) { - if (TryComp(args.Used, out var toolComp) && toolComp.Qualities.Contains(component.QualityNeeded)) + if (_toolSystem.HasQuality(args.Used, component.QualityNeeded)) { foreach (var tag in component.RequiredParts.Keys) { diff --git a/Content.Server/Mech/Systems/MechSystem.cs b/Content.Server/Mech/Systems/MechSystem.cs index 53c6c62cdb..68b973f588 100644 --- a/Content.Server/Mech/Systems/MechSystem.cs +++ b/Content.Server/Mech/Systems/MechSystem.cs @@ -17,6 +17,7 @@ using Content.Shared.Tools.Components; using Content.Shared.Verbs; using Content.Shared.Wires; using Content.Server.Body.Systems; +using Content.Shared.Tools.Systems; using Robust.Server.Containers; using Robust.Server.GameObjects; using Robust.Shared.Containers; @@ -35,6 +36,7 @@ public sealed partial class MechSystem : SharedMechSystem [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly SharedToolSystem _toolSystem = default!; /// public override void Initialize() @@ -87,7 +89,7 @@ public sealed partial class MechSystem : SharedMechSystem return; } - if (TryComp(args.Used, out var tool) && tool.Qualities.Contains("Prying") && component.BatterySlot.ContainedEntity != null) + if (_toolSystem.HasQuality(args.Used, "Prying") && component.BatterySlot.ContainedEntity != null) { var doAfterEventArgs = new DoAfterArgs(EntityManager, args.User, component.BatteryRemovalDelay, new RemoveBatteryEvent(), uid, target: uid, used: args.Target) diff --git a/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs b/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs index 6e0e0c503a..7882522d30 100644 --- a/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs +++ b/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs @@ -7,7 +7,7 @@ using Content.Shared.Containers.ItemSlots; using Content.Shared.Interaction; using Content.Shared.PneumaticCannon; using Content.Shared.StatusEffect; -using Content.Shared.Tools.Components; +using Content.Shared.Tools.Systems; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; using Content.Shared.Weapons.Ranged.Systems; @@ -22,6 +22,7 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem [Dependency] private readonly GunSystem _gun = default!; [Dependency] private readonly StunSystem _stun = default!; [Dependency] private readonly ItemSlotsSystem _slots = default!; + [Dependency] private readonly SharedToolSystem _toolSystem = default!; public override void Initialize() { @@ -38,10 +39,7 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem if (args.Handled) return; - if (!TryComp(args.Used, out var tool)) - return; - - if (!tool.Qualities.Contains(component.ToolModifyPower)) + if (!_toolSystem.HasQuality(args.Used, component.ToolModifyPower)) return; var val = (int) component.Power; diff --git a/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs b/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs index e8897781f5..5970e16319 100644 --- a/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs +++ b/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs @@ -2,8 +2,7 @@ using Content.Shared.Interaction; using Content.Shared.Light; using Content.Shared.Light.Components; using Content.Shared.Toggleable; -using Content.Shared.Tools.Components; -using Content.Shared.Item; +using Content.Shared.Tools.Systems; using Robust.Shared.Random; namespace Content.Server.Weapons.Melee.EnergySword; @@ -13,6 +12,7 @@ public sealed class EnergySwordSystem : EntitySystem [Dependency] private readonly SharedRgbLightControllerSystem _rgbSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedToolSystem _toolSystem = default!; public override void Initialize() { @@ -38,7 +38,7 @@ public sealed class EnergySwordSystem : EntitySystem if (args.Handled) return; - if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.ContainsAny("Pulsing")) + if (!_toolSystem.HasQuality(args.Used, "Pulsing")) return; args.Handled = true; diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactElectricityTriggerSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactElectricityTriggerSystem.cs index aa2a16aa1b..019e09bbbb 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactElectricityTriggerSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactElectricityTriggerSystem.cs @@ -3,12 +3,14 @@ using Content.Server.Power.Events; using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components; using Content.Shared.Interaction; using Content.Shared.Tools.Components; +using Content.Shared.Tools.Systems; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems; public sealed class ArtifactElectricityTriggerSystem : EntitySystem { [Dependency] private readonly ArtifactSystem _artifactSystem = default!; + [Dependency] private readonly SharedToolSystem _toolSystem = default!; public override void Initialize() { @@ -42,7 +44,7 @@ public sealed class ArtifactElectricityTriggerSystem : EntitySystem if (args.Handled) return; - if (!TryComp(args.Used, out ToolComponent? tool) || !tool.Qualities.ContainsAny("Pulsing")) + if (!_toolSystem.HasQuality(args.Used, "Pulsing")) return; args.Handled = _artifactSystem.TryActivateArtifact(uid, args.User); diff --git a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs index e9ef053f62..efb5dfd024 100644 --- a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs +++ b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs @@ -79,7 +79,7 @@ public sealed partial class AnchorableSystem : EntitySystem return; // If the used entity doesn't have a tool, return early. - if (!TryComp(args.Used, out ToolComponent? usedTool) || !usedTool.Qualities.Contains(anchorable.Tool)) + if (!TryComp(args.Used, out ToolComponent? usedTool) || !_tool.HasQuality(args.Used, anchorable.Tool, usedTool)) return; args.Handled = true; diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index 746147eb5b..ea07b5f8a5 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -6,10 +6,8 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Radio.Components; -using Content.Shared.Tools; using Content.Shared.Tools.Components; using Content.Shared.Wires; -using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Network; @@ -106,7 +104,7 @@ public sealed partial class EncryptionKeySystem : EntitySystem TryInsertKey(uid, component, args); } else if (TryComp(args.Used, out var tool) - && tool.Qualities.Contains(component.KeysExtractionMethod) + && _tool.HasQuality(args.Used, component.KeysExtractionMethod, tool) && component.KeyContainer.ContainedEntities.Count > 0) // dont block deconstruction { args.Handled = true; diff --git a/Content.Shared/Tools/Components/ToolComponent.cs b/Content.Shared/Tools/Components/ToolComponent.cs index 92857ab905..a7210c6fa0 100644 --- a/Content.Shared/Tools/Components/ToolComponent.cs +++ b/Content.Shared/Tools/Components/ToolComponent.cs @@ -1,52 +1,43 @@ +using Content.Shared.Tools.Systems; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Utility; -namespace Content.Shared.Tools.Components +namespace Content.Shared.Tools.Components; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedToolSystem))] +public sealed partial class ToolComponent : Component { - [RegisterComponent, NetworkedComponent] // TODO move tool system to shared, and make it a friend. - public sealed partial class ToolComponent : Component - { - [DataField("qualities")] - public PrototypeFlags Qualities { get; set; } = new(); - - /// - /// For tool interactions that have a delay before action this will modify the rate, time to wait is divided by this value - /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("speed")] - public float SpeedModifier { get; set; } = 1; - - [DataField("useSound")] - public SoundSpecifier? UseSound { get; set; } - } + [DataField] + public PrototypeFlags Qualities = []; /// - /// Attempt event called *before* any do afters to see if the tool usage should succeed or not. - /// Raised on both the tool and then target. + /// For tool interactions that have a delay before action this will modify the rate, time to wait is divided by this value /// - public sealed class ToolUseAttemptEvent : CancellableEntityEventArgs - { - public EntityUid User { get; } + [DataField] + public float SpeedModifier = 1; - public ToolUseAttemptEvent(EntityUid user) - { - User = user; - } - } - - /// - /// Event raised on the user of a tool to see if they can actually use it. - /// - [ByRefEvent] - public struct ToolUserAttemptUseEvent - { - public EntityUid? Target; - public bool Cancelled = false; - - public ToolUserAttemptUseEvent(EntityUid? target) - { - Target = target; - } - } + [DataField] + public SoundSpecifier? UseSound; +} + +/// +/// Attempt event called *before* any do afters to see if the tool usage should succeed or not. +/// Raised on both the tool and then target. +/// +public sealed class ToolUseAttemptEvent(EntityUid user, float fuel) : CancellableEntityEventArgs +{ + public EntityUid User { get; } = user; + public float Fuel = fuel; +} + +/// +/// Event raised on the user of a tool to see if they can actually use it. +/// +[ByRefEvent] +public struct ToolUserAttemptUseEvent(EntityUid? target) +{ + public EntityUid? Target = target; + public bool Cancelled = false; } diff --git a/Content.Server/Construction/Components/WelderRefinableComponent.cs b/Content.Shared/Tools/Components/ToolRefinableComponent.cs similarity index 74% rename from Content.Server/Construction/Components/WelderRefinableComponent.cs rename to Content.Shared/Tools/Components/ToolRefinableComponent.cs index 2fe88f2670..5a311cdda8 100644 --- a/Content.Server/Construction/Components/WelderRefinableComponent.cs +++ b/Content.Shared/Tools/Components/ToolRefinableComponent.cs @@ -1,15 +1,16 @@ using Content.Shared.Storage; -using Content.Shared.Tools; +using Robust.Shared.GameStates; using Robust.Shared.Prototypes; +using Content.Shared.Tools.Systems; -namespace Content.Server.Construction.Components; +namespace Content.Shared.Tools.Components; /// /// Used for something that can be refined by welder. /// For example, glass shard can be refined to glass sheet. /// -[RegisterComponent, Access(typeof(RefiningSystem))] -public sealed partial class WelderRefinableComponent : Component +[RegisterComponent, NetworkedComponent, Access(typeof(ToolRefinablSystem))] +public sealed partial class ToolRefinableComponent : Component { /// /// The items created when the item is refined. @@ -27,7 +28,7 @@ public sealed partial class WelderRefinableComponent : Component /// The amount of fuel it takes to refine a given item. /// [DataField] - public float RefineFuel; + public float RefineFuel = 3f; /// /// The tool type needed in order to refine this item. diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs b/Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs index e790b59cd1..60eafce474 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs @@ -16,8 +16,15 @@ public abstract partial class SharedToolSystem { SubscribeLocalEvent(OnWelderExamine); SubscribeLocalEvent(OnWelderAfterInteract); - SubscribeLocalEvent>(OnWelderToolUseAttempt); + + SubscribeLocalEvent((uid, comp, ev) => { + CanCancelWelderUse((uid, comp), ev.User, ev.Fuel, ev); + }); + SubscribeLocalEvent>((uid, comp, ev) => { + CanCancelWelderUse((uid, comp), ev.Event.User, ev.Event.Fuel, ev); + }); SubscribeLocalEvent(OnWelderDoAfter); + SubscribeLocalEvent(OnToggle); SubscribeLocalEvent(OnActivateAttempt); } @@ -120,23 +127,20 @@ public abstract partial class SharedToolSystem } } - private void OnWelderToolUseAttempt(Entity entity, ref DoAfterAttemptEvent args) + private void CanCancelWelderUse(Entity entity, EntityUid user, float requiredFuel, CancellableEntityEventArgs ev) { - var user = args.DoAfter.Args.User; - if (!ItemToggle.IsActivated(entity.Owner)) { _popup.PopupClient(Loc.GetString("welder-component-welder-not-lit-message"), entity, user); - args.Cancel(); - return; + ev.Cancel(); } - var (fuel, _) = GetWelderFuelAndCapacity(entity); + var (currentFuel, _) = GetWelderFuelAndCapacity(entity); - if (args.Event.Fuel > fuel) + if (requiredFuel > currentFuel) { _popup.PopupClient(Loc.GetString("welder-component-cannot-weld-message"), entity, user); - args.Cancel(); + ev.Cancel(); } } diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.cs b/Content.Shared/Tools/Systems/SharedToolSystem.cs index 9edae9b78f..72e984fd82 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.cs @@ -217,7 +217,7 @@ public abstract partial class SharedToolSystem : EntitySystem return false; // check if the tool allows being used - var beforeAttempt = new ToolUseAttemptEvent(user); + var beforeAttempt = new ToolUseAttemptEvent(user, fuel); RaiseLocalEvent(tool, beforeAttempt); if (beforeAttempt.Cancelled) return false; @@ -296,4 +296,3 @@ public abstract partial class SharedToolSystem : EntitySystem public sealed partial class CableCuttingFinishedEvent : SimpleDoAfterEvent; #endregion - diff --git a/Content.Server/Construction/RefiningSystem.cs b/Content.Shared/Tools/Systems/ToolRefinableSystem.cs similarity index 59% rename from Content.Server/Construction/RefiningSystem.cs rename to Content.Shared/Tools/Systems/ToolRefinableSystem.cs index ce7eb49ef1..e8ac4d492d 100644 --- a/Content.Server/Construction/RefiningSystem.cs +++ b/Content.Shared/Tools/Systems/ToolRefinableSystem.cs @@ -1,25 +1,26 @@ -using Content.Server.Construction.Components; using Content.Shared.Construction; using Content.Shared.Interaction; using Content.Shared.Storage; -using Content.Shared.Tools.Systems; +using Content.Shared.Tools.Components; +using Robust.Shared.Network; using Robust.Shared.Random; -namespace Content.Server.Construction; +namespace Content.Shared.Tools.Systems; -public sealed class RefiningSystem : EntitySystem +public sealed class ToolRefinablSystem : EntitySystem { + [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedToolSystem _toolSystem = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnInteractUsing); - SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent(OnDoAfter); } - private void OnInteractUsing(EntityUid uid, WelderRefinableComponent component, InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, ToolRefinableComponent component, InteractUsingEvent args) { if (args.Handled) return; @@ -34,11 +35,14 @@ public sealed class RefiningSystem : EntitySystem fuel: component.RefineFuel); } - private void OnDoAfter(EntityUid uid, WelderRefinableComponent component, WelderRefineDoAfterEvent args) + private void OnDoAfter(EntityUid uid, ToolRefinableComponent component, WelderRefineDoAfterEvent args) { if (args.Cancelled) return; + if (_net.IsClient) + return; + var xform = Transform(uid); var spawns = EntitySpawnCollection.GetSpawns(component.RefineResult, _random); foreach (var spawn in spawns) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index b5f69e6f56..51647f6985 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -2255,7 +2255,7 @@ - DoorBumpOpener - FootstepSound - type: Tool # Open door from xeno.yml. - speed: 1.5 + speedModifier: 1.5 qualities: - Prying useSound: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index a3d4eafacb..8c262d23da 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -22,7 +22,7 @@ NavSmash: !type:Bool true - type: Tool - speed: 1.5 + speedModifier: 1.5 qualities: - Prying - type: Prying diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml index 35ad43586b..7287119019 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml @@ -80,7 +80,7 @@ - type: Tool qualities: - Rolling - speed: 0.75 # not as good as a rolling pin but does the job + speedModifier: 0.75 # not as good as a rolling pin but does the job - type: PhysicalComposition materialComposition: Glass: 100 diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml index 5d092673ed..f5cb260e03 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml @@ -56,7 +56,7 @@ - type: Tool qualities: - Rolling - speed: 0.25 # its small so takes longer to roll the entire dough flat + speedModifier: 0.25 # its small so takes longer to roll the entire dough flat - type: SpaceGarbage - type: TrashOnSolutionEmpty solution: drink diff --git a/Resources/Prototypes/Entities/Objects/Materials/shards.yml b/Resources/Prototypes/Entities/Objects/Materials/shards.yml index 561140a46a..fa6937dac3 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/shards.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/shards.yml @@ -85,7 +85,7 @@ components: - type: Sprite color: "#bbeeff" - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - type: DamageUserOnTrigger @@ -120,7 +120,7 @@ damage: types: Slash: 4.5 - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: PartRodMetal1 @@ -156,7 +156,7 @@ damage: types: Slash: 5.5 - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: SheetPlasma1 @@ -195,7 +195,7 @@ types: Slash: 4.5 Radiation: 2 - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: SheetUranium1 @@ -230,7 +230,7 @@ components: - type: Sprite color: "#e0aa36" - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: SheetBrass1 diff --git a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml index 32222d0036..9d3ef6c424 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml @@ -26,6 +26,6 @@ materialComposition: Glass: 50 - type: SpaceGarbage - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 diff --git a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml index 112ce99710..71629919ae 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml @@ -46,7 +46,7 @@ - type: Tool qualities: - Rolling - speed: 0.5 # its very big, akward to use + speedModifier: 0.5 # its very big, akward to use - type: Appearance - type: GenericVisualizer visuals: diff --git a/Resources/Prototypes/Entities/Objects/Power/lights.yml b/Resources/Prototypes/Entities/Objects/Power/lights.yml index bccf10bee5..3f7da1efab 100644 --- a/Resources/Prototypes/Entities/Objects/Power/lights.yml +++ b/Resources/Prototypes/Entities/Objects/Power/lights.yml @@ -66,7 +66,7 @@ materialComposition: Glass: 25 - type: SpaceGarbage - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 @@ -273,7 +273,7 @@ - type: Construction graph: CyanLight node: icon - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: ShardCrystalCyan @@ -293,7 +293,7 @@ - type: Construction graph: BlueLight node: icon - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: ShardCrystalBlue @@ -313,7 +313,7 @@ - type: Construction graph: PinkLight node: icon - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: ShardCrystalPink @@ -333,7 +333,7 @@ - type: Construction graph: OrangeLight node: icon - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: ShardCrystalOrange @@ -353,7 +353,7 @@ - type: Construction graph: RedLight node: icon - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: ShardCrystalRed @@ -373,7 +373,7 @@ - type: Construction graph: GreenLight node: icon - - type: WelderRefinable + - type: ToolRefinable refineResult: - id: SheetGlass1 - id: ShardCrystalGreen diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml index aa0cf46187..c4f7798154 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml @@ -178,7 +178,7 @@ - type: Tool qualities: - Sawing - speed: 1.0 + speedModifier: 1.0 # No melee for regular saw because have you ever seen someone use a band saw as a weapon? It's dumb. - type: entity @@ -200,7 +200,7 @@ - type: Tool qualities: - Sawing - speed: 0.5 + speedModifier: 0.5 - type: entity name: circular saw @@ -222,7 +222,7 @@ - type: Tool qualities: - Sawing - speed: 1.5 + speedModifier: 1.5 - type: entity name: advanced circular saw @@ -245,4 +245,4 @@ - type: Tool qualities: - Sawing - speed: 2.0 + speedModifier: 2.0 diff --git a/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml b/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml index 87959ebef3..c9b37b8b1a 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml @@ -21,7 +21,7 @@ - Cutting useSound: path: /Audio/Items/wirecutter.ogg - speed: 0.05 + speedModifier: 0.05 - type: Item sprite: Objects/Tools/Cowtools/haycutters.rsi @@ -46,7 +46,7 @@ - Screwing useSound: collection: Screwdriver - speed: 0.05 + speedModifier: 0.05 - type: entity name: wronch @@ -69,7 +69,7 @@ - Anchoring useSound: path: /Audio/Items/ratchet.ogg - speed: 0.05 + speedModifier: 0.05 - type: entity name: cowbar @@ -93,7 +93,7 @@ - Prying useSound: path: /Audio/Items/crowbar.ogg - speed: 0.05 + speedModifier: 0.05 - type: ToolTileCompatible - type: Prying @@ -127,7 +127,7 @@ size: Small sprite: Objects/Tools/Cowtools/cowelder.rsi - type: Tool - speed: 0.05 + speedModifier: 0.05 - type: entity name: milkalyzer diff --git a/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml b/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml index 7bdd32f457..53423e84a4 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml @@ -51,7 +51,7 @@ - type: Tool qualities: - Rolling - speed: 0.6 # fairly unwieldly but nice round surface + speedModifier: 0.6 # fairly unwieldly but nice round surface - type: entity parent: GasTankRoundBase diff --git a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml index 8e2b759797..c80e53870e 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml @@ -21,7 +21,7 @@ - type: Tool qualities: - Prying - speed: 1.5 + speedModifier: 1.5 useSound: /Audio/Items/jaws_pry.ogg - type: Prying pryPowered: true @@ -69,7 +69,7 @@ - type: Tool qualities: - Prying - speed: 3.0 + speedModifier: 3.0 - type: MultipleTool entries: - behavior: Prying diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index 452a905329..7930482960 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -304,7 +304,7 @@ - type: Tool qualities: - Screwing - speed: 1.5 + speedModifier: 1.5 useSound: /Audio/Items/drill_use.ogg - type: MultipleTool statusShowBehavior: true @@ -479,7 +479,7 @@ - type: Tool qualities: - Screwing - speed: 1.2 # Kept for future adjustments. Currently 1.2x for balance + speedModifier: 1.2 # Kept for future adjustments. Currently 1.2x for balance useSound: /Audio/Items/drill_use.ogg - type: ToolTileCompatible - type: MultipleTool diff --git a/Resources/Prototypes/Entities/Objects/Tools/welders.yml b/Resources/Prototypes/Entities/Objects/Tools/welders.yml index 9bf3f2e2cb..9db30edb52 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/welders.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/welders.yml @@ -139,7 +139,7 @@ Quantity: 250 maxVol: 250 - type: Tool - speed: 1.3 + speedModifier: 1.3 - type: entity name: experimental welding tool @@ -190,7 +190,7 @@ Quantity: 50 maxVol: 50 - type: Tool - speed: 0.7 + speedModifier: 0.7 - type: PointLight enabled: false radius: 1.0 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml index 5347096bf1..818c4bd676 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/baseball_bat.yml @@ -26,7 +26,7 @@ - type: Tool qualities: - Rolling - speed: 0.75 # a bit unwieldly but does the job + speedModifier: 0.75 # a bit unwieldly but does the job - type: Clothing quickEquip: false slots: diff --git a/Resources/Prototypes/Entities/Structures/Storage/Tanks/tanks.yml b/Resources/Prototypes/Entities/Structures/Storage/Tanks/tanks.yml index 934298b620..df19550cdb 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Tanks/tanks.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Tanks/tanks.yml @@ -25,8 +25,7 @@ - type: ReagentTank tankType: Fuel - type: DamageOnToolInteract - tools: - - Welding + tools: Welding weldingDamage: types: Heat: 10 @@ -217,4 +216,3 @@ fillBaseName: watertank-2- - type: ExaminableSolution solution: tank - diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml index 72ea308af0..3570264a57 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/walldispenser.yml @@ -82,8 +82,7 @@ - type: ReagentTank tankType: Fuel - type: DamageOnToolInteract - tools: - - Welding + tools: Welding weldingDamage: types: Heat: 20 diff --git a/Resources/Prototypes/XenoArch/Effects/utility_effects.yml b/Resources/Prototypes/XenoArch/Effects/utility_effects.yml index 84df09af33..a896708057 100644 --- a/Resources/Prototypes/XenoArch/Effects/utility_effects.yml +++ b/Resources/Prototypes/XenoArch/Effects/utility_effects.yml @@ -220,7 +220,7 @@ - type: Tool qualities: - Screwing - speed: 2 # Very powerful multitool to balance out the desire to sell or scrap for points + speedModifier: 2 # Very powerful multitool to balance out the desire to sell or scrap for points useSound: /Audio/Items/drill_use.ogg - type: Tag tags: From 91875e91e13e77af5c9ca3b0c8a65a0fa232d5cd Mon Sep 17 00:00:00 2001 From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:30:00 -0400 Subject: [PATCH 17/63] Strip Items From Things Before Biomassing Them (#28544) --- .../Medical/BiomassReclaimer/BiomassReclaimerSystem.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs index f8d5139a46..a6285294c9 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs @@ -15,6 +15,7 @@ using Content.Shared.DoAfter; using Content.Shared.Humanoid; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; +using Content.Shared.Inventory; using Content.Shared.Jittering; using Content.Shared.Medical; using Content.Shared.Mind; @@ -36,6 +37,7 @@ namespace Content.Server.Medical.BiomassReclaimer public sealed class BiomassReclaimerSystem : EntitySystem { [Dependency] private readonly IConfigurationManager _configManager = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedJitteringSystem _jitteringSystem = default!; [Dependency] private readonly SharedAudioSystem _sharedAudioSystem = default!; @@ -49,6 +51,7 @@ namespace Content.Server.Medical.BiomassReclaimer [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly MaterialStorageSystem _material = default!; [Dependency] private readonly SharedMindSystem _minds = default!; + [Dependency] private readonly InventorySystem _inventory = default!; [ValidatePrototypeId] public const string BiomassPrototype = "Biomass"; @@ -221,6 +224,12 @@ namespace Content.Server.Medical.BiomassReclaimer component.ProcessingTimer = physics.FixturesMass * component.ProcessingTimePerUnitMass; + var inventory = _inventory.GetHandOrInventoryEntities(toProcess); + foreach (var item in inventory) + { + _transform.DropNextTo(item, ent.Owner); + } + QueueDel(toProcess); } From 0a8167f055929533129a8c2b2aa518937db1d968 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 03:29:59 +0000 Subject: [PATCH 18/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b602964081..3086e6a71c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: 21Melkuu - changes: - - message: Add new explosion-proof backpack in aplink. - type: Add - id: 6169 - time: '2024-03-17T02:21:13.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26187 - author: Ilya246 changes: - message: Syndicate decoy bombs may now be purchased from the uplink. @@ -3853,3 +3846,10 @@ id: 6668 time: '2024-06-03T02:18:49.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28540 +- author: Vermidia + changes: + - message: Glass shards are no longer weldable with an unlit welder. + type: Fix + id: 6669 + time: '2024-06-03T03:28:53.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27959 From 42217079b76084ef2d45d3b32b96027ae36c5355 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 03:31:08 +0000 Subject: [PATCH 19/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 3086e6a71c..941b933136 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,14 +1,4 @@ Entries: -- author: Ilya246 - changes: - - message: Syndicate decoy bombs may now be purchased from the uplink. - type: Add - - message: Syndicate bomb description no longer lies about their minimum detonation - time. - type: Fix - id: 6170 - time: '2024-03-17T02:31:41.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26034 - author: wafehling changes: - message: Added 18 new bounties to cargo bounty system. @@ -3853,3 +3843,11 @@ id: 6669 time: '2024-06-03T03:28:53.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27959 +- author: AJCM-git + changes: + - message: Biomass reclaimers no longer act as a void to any unfortunate belongings + a corpse may be wearing + type: Tweak + id: 6670 + time: '2024-06-03T03:30:00.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28544 From be35a5d36991237525a490116af5363e06ab5216 Mon Sep 17 00:00:00 2001 From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:33:30 -0400 Subject: [PATCH 20/63] Header of Gas tank UI screen now fetched from Entity name and local (#28545) --- .../GasTank/GasTankBoundUserInterface.cs | 3 +- .../Systems/Atmos/GasTank/GasTankWindow.cs | 339 +++++++++--------- .../Locale/en-US/atmos/gas-tank-component.ftl | 1 - 3 files changed, 167 insertions(+), 176 deletions(-) diff --git a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs index ee8cb28d2c..4702f8f365 100644 --- a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs +++ b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Atmos.Components; using JetBrains.Annotations; -using Robust.Client.GameObjects; namespace Content.Client.UserInterface.Systems.Atmos.GasTank { @@ -30,7 +29,7 @@ namespace Content.Client.UserInterface.Systems.Atmos.GasTank protected override void Open() { base.Open(); - _window = new GasTankWindow(this); + _window = new GasTankWindow(this, EntMan.GetComponent(Owner).EntityName); _window.OnClose += Close; _window.OpenCentered(); } diff --git a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs index 7797a096de..c23850a650 100644 --- a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs +++ b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs @@ -10,201 +10,194 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using static Robust.Client.UserInterface.Controls.BoxContainer; -namespace Content.Client.UserInterface.Systems.Atmos.GasTank +namespace Content.Client.UserInterface.Systems.Atmos.GasTank; + +public sealed class GasTankWindow + : BaseWindow { - public sealed class GasTankWindow - : BaseWindow + private readonly RichTextLabel _lblPressure; + private readonly FloatSpinBox _spbPressure; + private readonly RichTextLabel _lblInternals; + private readonly Button _btnInternals; + + public GasTankWindow(GasTankBoundUserInterface owner, string uidName) { - private GasTankBoundUserInterface _owner; - private readonly Label _lblName; - private readonly BoxContainer _topContainer; - private readonly Control _contentContainer; + Control contentContainer; + BoxContainer topContainer; + TextureButton btnClose; + var resourceCache = IoCManager.Resolve(); + var rootContainer = new LayoutContainer { Name = "GasTankRoot" }; + AddChild(rootContainer); + MouseFilter = MouseFilterMode.Stop; - private readonly IResourceCache _resourceCache = default!; - private readonly RichTextLabel _lblPressure; - private readonly FloatSpinBox _spbPressure; - private readonly RichTextLabel _lblInternals; - private readonly Button _btnInternals; - - public GasTankWindow(GasTankBoundUserInterface owner) + var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"); + var back = new StyleBoxTexture { - TextureButton btnClose; - _resourceCache = IoCManager.Resolve(); - _owner = owner; - var rootContainer = new LayoutContainer {Name = "GasTankRoot"}; - AddChild(rootContainer); + Texture = panelTex, + Modulate = Color.FromHex("#25252A"), + }; - MouseFilter = MouseFilterMode.Stop; + back.SetPatchMargin(StyleBox.Margin.All, 10); - var panelTex = _resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"); - var back = new StyleBoxTexture + var topPanel = new PanelContainer + { + PanelOverride = back, + MouseFilter = MouseFilterMode.Pass + }; + + var bottomWrap = new LayoutContainer + { + Name = "BottomWrap" + }; + + rootContainer.AddChild(topPanel); + rootContainer.AddChild(bottomWrap); + + LayoutContainer.SetAnchorPreset(topPanel, LayoutContainer.LayoutPreset.Wide); + LayoutContainer.SetMarginBottom(topPanel, -85); + + LayoutContainer.SetAnchorPreset(bottomWrap, LayoutContainer.LayoutPreset.VerticalCenterWide); + LayoutContainer.SetGrowHorizontal(bottomWrap, LayoutContainer.GrowDirection.Both); + + + var topContainerWrap = new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Children = { - Texture = panelTex, - Modulate = Color.FromHex("#25252A"), - }; - - back.SetPatchMargin(StyleBox.Margin.All, 10); - - var topPanel = new PanelContainer - { - PanelOverride = back, - MouseFilter = MouseFilterMode.Pass - }; - - var bottomWrap = new LayoutContainer - { - Name = "BottomWrap" - }; - - rootContainer.AddChild(topPanel); - rootContainer.AddChild(bottomWrap); - - LayoutContainer.SetAnchorPreset(topPanel, LayoutContainer.LayoutPreset.Wide); - LayoutContainer.SetMarginBottom(topPanel, -85); - - LayoutContainer.SetAnchorPreset(bottomWrap, LayoutContainer.LayoutPreset.VerticalCenterWide); - LayoutContainer.SetGrowHorizontal(bottomWrap, LayoutContainer.GrowDirection.Both); - - - var topContainerWrap = new BoxContainer - { - Orientation = LayoutOrientation.Vertical, - Children = + (topContainer = new BoxContainer { - (_topContainer = new BoxContainer - { - Orientation = LayoutOrientation.Vertical - }), - new Control {MinSize = new Vector2(0, 110)} - } - }; + Orientation = LayoutOrientation.Vertical + }), + new Control {MinSize = new Vector2(0, 110)} + } + }; - rootContainer.AddChild(topContainerWrap); + rootContainer.AddChild(topContainerWrap); - LayoutContainer.SetAnchorPreset(topContainerWrap, LayoutContainer.LayoutPreset.Wide); + LayoutContainer.SetAnchorPreset(topContainerWrap, LayoutContainer.LayoutPreset.Wide); - var font = _resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13); + var font = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13); - var topRow = new BoxContainer + var topRow = new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Margin = new Thickness(4, 2, 12, 2), + Children = + { + (new Label + { + Text = uidName, + FontOverride = font, + FontColorOverride = StyleNano.NanoGold, + VerticalAlignment = VAlignment.Center, + HorizontalExpand = true, + HorizontalAlignment = HAlignment.Left, + Margin = new Thickness(0, 0, 20, 0), + }), + (btnClose = new TextureButton + { + StyleClasses = {DefaultWindow.StyleClassWindowCloseButton}, + VerticalAlignment = VAlignment.Center + }) + } + }; + + var middle = new PanelContainer + { + PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#202025") }, + Children = + { + (contentContainer = new BoxContainer + { + Orientation = LayoutOrientation.Vertical, + Margin = new Thickness(8, 4), + }) + } + }; + + topContainer.AddChild(topRow); + topContainer.AddChild(new PanelContainer + { + MinSize = new Vector2(0, 2), + PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#525252ff") } + }); + topContainer.AddChild(middle); + topContainer.AddChild(new PanelContainer + { + MinSize = new Vector2(0, 2), + PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#525252ff") } + }); + + + _lblPressure = new RichTextLabel(); + contentContainer.AddChild(_lblPressure); + + //internals + _lblInternals = new RichTextLabel + { MinSize = new Vector2(200, 0), VerticalAlignment = VAlignment.Center }; + _btnInternals = new Button { Text = Loc.GetString("gas-tank-window-internals-toggle-button") }; + + contentContainer.AddChild( + new BoxContainer { Orientation = LayoutOrientation.Horizontal, - Margin = new Thickness(4, 2, 12, 2), - Children = - { - (_lblName = new Label - { - Text = Loc.GetString("gas-tank-window-label"), - FontOverride = font, - FontColorOverride = StyleNano.NanoGold, - VerticalAlignment = VAlignment.Center, - HorizontalExpand = true, - HorizontalAlignment = HAlignment.Left, - Margin = new Thickness(0, 0, 20, 0), - }), - (btnClose = new TextureButton - { - StyleClasses = {DefaultWindow.StyleClassWindowCloseButton}, - VerticalAlignment = VAlignment.Center - }) - } - }; - - var middle = new PanelContainer - { - PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#202025")}, - Children = - { - (_contentContainer = new BoxContainer - { - Orientation = LayoutOrientation.Vertical, - Margin = new Thickness(8, 4), - }) - } - }; - - _topContainer.AddChild(topRow); - _topContainer.AddChild(new PanelContainer - { - MinSize = new Vector2(0, 2), - PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#525252ff")} - }); - _topContainer.AddChild(middle); - _topContainer.AddChild(new PanelContainer - { - MinSize = new Vector2(0, 2), - PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#525252ff")} + Margin = new Thickness(0, 7, 0, 0), + Children = { _lblInternals, _btnInternals } }); - - _lblPressure = new RichTextLabel(); - _contentContainer.AddChild(_lblPressure); - - //internals - _lblInternals = new RichTextLabel - {MinSize = new Vector2(200, 0), VerticalAlignment = VAlignment.Center}; - _btnInternals = new Button {Text = Loc.GetString("gas-tank-window-internals-toggle-button") }; - - _contentContainer.AddChild( - new BoxContainer - { - Orientation = LayoutOrientation.Horizontal, - Margin = new Thickness(0, 7, 0, 0), - Children = {_lblInternals, _btnInternals} - }); - - // Separator - _contentContainer.AddChild(new Control - { - MinSize = new Vector2(0, 10) - }); - - _contentContainer.AddChild(new Label - { - Text = Loc.GetString("gas-tank-window-output-pressure-label"), - Align = Label.AlignMode.Center - }); - _spbPressure = new FloatSpinBox - { - IsValid = f => f >= 0 || f <= 3000, - Margin = new Thickness(25, 0, 25, 7) - }; - _contentContainer.AddChild(_spbPressure); - - // Handlers - _spbPressure.OnValueChanged += args => - { - _owner.SetOutputPressure(args.Value); - }; - - _btnInternals.OnPressed += args => - { - _owner.ToggleInternals(); - }; - - btnClose.OnPressed += _ => Close(); - } - - public void UpdateState(GasTankBoundUserInterfaceState state) + // Separator + contentContainer.AddChild(new Control { - _lblPressure.SetMarkup(Loc.GetString("gas-tank-window-tank-pressure-text", ("tankPressure", $"{state.TankPressure:0.##}"))); - _btnInternals.Disabled = !state.CanConnectInternals; - _lblInternals.SetMarkup(Loc.GetString("gas-tank-window-internal-text", - ("status", Loc.GetString(state.InternalsConnected ? "gas-tank-window-internal-connected" : "gas-tank-window-internal-disconnected")))); - if (state.OutputPressure.HasValue) - { - _spbPressure.Value = state.OutputPressure.Value; - } - } + MinSize = new Vector2(0, 10) + }); - protected override DragMode GetDragModeFor(Vector2 relativeMousePos) + contentContainer.AddChild(new Label { - return DragMode.Move; - } + Text = Loc.GetString("gas-tank-window-output-pressure-label"), + Align = Label.AlignMode.Center + }); + _spbPressure = new FloatSpinBox + { + IsValid = f => f >= 0 || f <= 3000, + Margin = new Thickness(25, 0, 25, 7) + }; + contentContainer.AddChild(_spbPressure); - protected override bool HasPoint(Vector2 point) + // Handlers + _spbPressure.OnValueChanged += args => { - return false; + owner.SetOutputPressure(args.Value); + }; + + _btnInternals.OnPressed += args => + { + owner.ToggleInternals(); + }; + + btnClose.OnPressed += _ => Close(); + } + + public void UpdateState(GasTankBoundUserInterfaceState state) + { + _lblPressure.SetMarkup(Loc.GetString("gas-tank-window-tank-pressure-text", ("tankPressure", $"{state.TankPressure:0.##}"))); + _btnInternals.Disabled = !state.CanConnectInternals; + _lblInternals.SetMarkup(Loc.GetString("gas-tank-window-internal-text", + ("status", Loc.GetString(state.InternalsConnected ? "gas-tank-window-internal-connected" : "gas-tank-window-internal-disconnected")))); + if (state.OutputPressure.HasValue) + { + _spbPressure.Value = state.OutputPressure.Value; } } + + protected override DragMode GetDragModeFor(Vector2 relativeMousePos) + { + return DragMode.Move; + } + + protected override bool HasPoint(Vector2 point) + { + return false; + } } diff --git a/Resources/Locale/en-US/atmos/gas-tank-component.ftl b/Resources/Locale/en-US/atmos/gas-tank-component.ftl index ae10d5630c..1f2d8f1e9f 100644 --- a/Resources/Locale/en-US/atmos/gas-tank-component.ftl +++ b/Resources/Locale/en-US/atmos/gas-tank-component.ftl @@ -14,7 +14,6 @@ comp-gas-tank-examine-closed-valve = Gas release valve is [color=green]closed[/c control-verb-open-control-panel-text = Open Control Panel ## UI -gas-tank-window-label = Gas Tank gas-tank-window-internals-toggle-button = Toggle gas-tank-window-output-pressure-label = Output Pressure gas-tank-window-tank-pressure-text = Pressure: {$tankPressure} kPA From 39481fb2b018921bca058f49433422db848cd7ef Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 03:34:36 +0000 Subject: [PATCH 21/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 941b933136..f30481fee7 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: wafehling - changes: - - message: Added 18 new bounties to cargo bounty system. - type: Add - id: 6171 - time: '2024-03-17T17:06:17.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26160 - author: Ko4erga changes: - message: Added craftable high and small wooden fences, bench. New stairs. @@ -3851,3 +3844,10 @@ id: 6670 time: '2024-06-03T03:30:00.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28544 +- author: Laneron + changes: + - message: Jetpack UI window now has correctly displayed header + type: Fix + id: 6671 + time: '2024-06-03T03:33:31.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28545 From 0d864d324cd0ca06e06484b38eadd8ea5c06ef5b Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Mon, 3 Jun 2024 01:12:13 -0400 Subject: [PATCH 22/63] Add support for HeldPrefix to SolutionContainerVisualsSystem (#28532) --- .../Visualizers/SolutionContainerVisualsSystem.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs b/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs index f1e8e8d7aa..17b88fb5a8 100644 --- a/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs +++ b/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Hands; +using Content.Shared.Item; using Content.Shared.Rounding; using Robust.Client.GameObjects; using Robust.Shared.Prototypes; @@ -150,6 +151,9 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem(uid, out var item)) + return; + if (!AppearanceSystem.TryGetData(uid, SolutionContainerVisuals.FillFraction, out var fraction, appearance)) return; @@ -159,7 +163,8 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem Date: Mon, 3 Jun 2024 17:21:46 +1200 Subject: [PATCH 23/63] Add PrototypeUploadTest (#28522) --- .../PrototypeTests/PrototypeUploadTest.cs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Content.IntegrationTests/Tests/PrototypeTests/PrototypeUploadTest.cs diff --git a/Content.IntegrationTests/Tests/PrototypeTests/PrototypeUploadTest.cs b/Content.IntegrationTests/Tests/PrototypeTests/PrototypeUploadTest.cs new file mode 100644 index 0000000000..c641cd9bd1 --- /dev/null +++ b/Content.IntegrationTests/Tests/PrototypeTests/PrototypeUploadTest.cs @@ -0,0 +1,85 @@ +using Content.Shared.Tag; +using Robust.Client.Upload.Commands; +using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; +using Robust.Shared.Upload; + +namespace Content.IntegrationTests.Tests.PrototypeTests; + +public sealed class PrototypeUploadTest +{ + public const string IdA = "UploadTestPrototype"; + public const string IdB = $"{IdA}NoParent"; + public const string IdC = $"{IdA}Abstract"; + public const string IdD = $"{IdA}UploadedParent"; + + private const string File = $@" +- type: entity + parent: BaseStructure # BaseItem can cause AllItemsHaveSpritesTest to fail + id: {IdA} + +- type: entity + id: {IdB} + +- type: entity + id: {IdC} + abstract: true + components: + - type: Tag + +- type: entity + id: {IdD} + parent: {IdC} +"; + + [Test] + [TestOf(typeof(LoadPrototypeCommand))] + public async Task TestFileUpload() + { + await using var pair = await PoolManager.GetServerClient(new PoolSettings {Connected = true}); + var sCompFact = pair.Server.ResolveDependency(); + var cCompFact = pair.Client.ResolveDependency(); + + Assert.That(!pair.Server.ProtoMan.TryIndex(IdA, out _)); + Assert.That(!pair.Server.ProtoMan.TryIndex(IdB, out _)); + Assert.That(!pair.Server.ProtoMan.TryIndex(IdC, out _)); + Assert.That(!pair.Server.ProtoMan.TryIndex(IdD, out _)); + + Assert.That(!pair.Client.ProtoMan.TryIndex(IdA, out _)); + Assert.That(!pair.Client.ProtoMan.TryIndex(IdB, out _)); + Assert.That(!pair.Client.ProtoMan.TryIndex(IdC, out _)); + Assert.That(!pair.Client.ProtoMan.TryIndex(IdD, out _)); + + var protoLoad = pair.Client.ResolveDependency(); + await pair.Client.WaitPost(() => protoLoad.SendGamePrototype(File)); + await pair.RunTicksSync(10); + + Assert.That(pair.Server.ProtoMan.TryIndex(IdA, out var sProtoA)); + Assert.That(pair.Server.ProtoMan.TryIndex(IdB, out var sProtoB)); + Assert.That(!pair.Server.ProtoMan.TryIndex(IdC, out _)); + Assert.That(pair.Server.ProtoMan.TryIndex(IdD, out var sProtoD)); + + Assert.That(pair.Client.ProtoMan.TryIndex(IdA, out var cProtoA)); + Assert.That(pair.Client.ProtoMan.TryIndex(IdB, out var cProtoB)); + Assert.That(!pair.Client.ProtoMan.TryIndex(IdC, out _)); + Assert.That(pair.Client.ProtoMan.TryIndex(IdD, out var cProtoD)); + + // Arbitrarily choosing TagComponent to check that inheritance works for uploaded prototypes. + + await pair.Server.WaitPost(() => + { + Assert.That(sProtoA!.TryGetComponent(out _, sCompFact), Is.True); + Assert.That(sProtoB!.TryGetComponent(out _, sCompFact), Is.False); + Assert.That(sProtoD!.TryGetComponent(out _, sCompFact), Is.True); + }); + + await pair.Client.WaitPost(() => + { + Assert.That(cProtoA!.TryGetComponent(out _, cCompFact), Is.True); + Assert.That(cProtoB!.TryGetComponent(out _, cCompFact), Is.False); + Assert.That(cProtoD!.TryGetComponent(out _, cCompFact), Is.True); + }); + + await pair.CleanReturnAsync(); + } +} From 36396e3f864b85783f831dde21f9f94b121b2da5 Mon Sep 17 00:00:00 2001 From: Verm <32827189+Vermidia@users.noreply.github.com> Date: Mon, 3 Jun 2024 06:54:32 -0500 Subject: [PATCH 24/63] Changes SyndiCat spawner to a radio (#28492) --- Resources/Locale/en-US/store/uplink-catalog.ftl | 4 ++-- Resources/Prototypes/Catalog/uplink_catalog.yml | 2 +- .../reinforcement_teleporter.yml | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index 3ae2d65c16..1b9fa8aff9 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -370,8 +370,8 @@ uplink-syndicate-sponge-box-desc = A box containing 6 syndicate sponges disguise uplink-slipocalypse-clustersoap-name = Slipocalypse Clustersoap uplink-slipocalypse-clustersoap-desc = Scatters arounds small pieces of syndicate-brand soap after being thrown, these pieces of soap evaporate after 60 seconds. -uplink-mobcat-microbomb-name = SyndiCat -uplink-mobcat-microbomb-desc = A hand cat equipped with a microbomb implant. Explodes when seriously injured. Can bite painfully +uplink-mobcat-microbomb-name = SyndiCat Teleporter +uplink-mobcat-microbomb-desc = Call in a handy cat equipped with a microbomb implant. Explodes when seriously injured. Can bite painfully. uplink-chameleon-projector-name = Chameleon Projector uplink-chameleon-projector-desc = Disappear in plain sight by creating a hologram of an item around you. Do not use this to play the game "Object Search". diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index c8d6eb4f61..efec2417d0 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -999,7 +999,7 @@ name: uplink-mobcat-microbomb-name description: uplink-mobcat-microbomb-desc icon: { sprite: /Textures/Mobs/Pets/cat.rsi, state: syndicat } - productEntity: MobCatSyndy + productEntity: ReinforcementRadioSyndicateSyndiCat cost: Telecrystal: 6 categories: diff --git a/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/reinforcement_teleporter.yml b/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/reinforcement_teleporter.yml index c62783fcee..2085422c9b 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/reinforcement_teleporter.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/reinforcement_teleporter.yml @@ -54,6 +54,23 @@ prototype: MobMonkeySyndicateAgentNukeops selectablePrototypes: ["SyndicateMonkeyNukeops", "SyndicateKoboldNukeops"] +- type: entity + parent: ReinforcementRadioSyndicate + id: ReinforcementRadioSyndicateSyndiCat + name: syndicat reinforcement radio + description: Calls in a faithfully trained cat with a microbomb to assist you. + components: + - type: GhostRole + name: ghost-role-information-SyndiCat-name + description: ghost-role-information-SyndiCat-description + rules: ghost-role-information-SyndiCat-rules + raffle: + settings: default + - type: GhostRoleMobSpawner + prototype: MobCatSyndy + - type: EmitSoundOnUse + sound: /Audio/Animals/cat_meow.ogg + - type: entity parent: ReinforcementRadioSyndicate id: ReinforcementRadioSyndicateCyborgAssault # Reinforcement radio exclusive to nukeops uplink From ba5af33ee42b82d7c653e7724ddf67b0a8c3cf1a Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 11:55:38 +0000 Subject: [PATCH 25/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f30481fee7..7235a60a0d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Ko4erga - changes: - - message: Added craftable high and small wooden fences, bench. New stairs. - type: Add - id: 6172 - time: '2024-03-17T21:18:59.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26182 - author: potato1234_x changes: - message: Changed the puddle sprites so the smoothing is less jagged @@ -3851,3 +3844,10 @@ id: 6671 time: '2024-06-03T03:33:31.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28545 +- author: Vermidia + changes: + - message: SyndiCats now spawn from a radio like other reinforcements. + type: Tweak + id: 6672 + time: '2024-06-03T11:54:32.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28492 From eb026c9b5b582420ba8e97f1bdee02dc5193c736 Mon Sep 17 00:00:00 2001 From: Cojoke <83733158+Cojoke-dot@users.noreply.github.com> Date: Mon, 3 Jun 2024 07:05:14 -0500 Subject: [PATCH 26/63] Gives Medibots Random Lines(not a good title) (#28543) --- Resources/Locale/en-US/advertisements/other/medibot.ftl | 9 +++++++++ .../Catalog/VendingMachines/advertisements.yml | 6 ++++++ Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml | 2 ++ 3 files changed, 17 insertions(+) create mode 100644 Resources/Locale/en-US/advertisements/other/medibot.ftl diff --git a/Resources/Locale/en-US/advertisements/other/medibot.ftl b/Resources/Locale/en-US/advertisements/other/medibot.ftl new file mode 100644 index 0000000000..9e919ce49f --- /dev/null +++ b/Resources/Locale/en-US/advertisements/other/medibot.ftl @@ -0,0 +1,9 @@ +advertisement-medibot-1 = What kind of medbay is this? Everyone's dropping like dead flies. +advertisement-medibot-2 = I knew it, I should've been a plastic surgeon. +advertisement-medibot-3 = There's always a catch, and I'm the best there is. +advertisement-medibot-4 = An apple a day keeps me away. +advertisement-medibot-5 = I'm different! +advertisement-medibot-6 = Fuck you. +advertisement-medibot-7 = Why are we still here? Just to suffer? +advertisement-medibot-8 = I...I've never lost a patient before. Not today, I mean. +advertisement-medibot-9 = Lexorin in. diff --git a/Resources/Prototypes/Catalog/VendingMachines/advertisements.yml b/Resources/Prototypes/Catalog/VendingMachines/advertisements.yml index 6dbb60af6a..c0052dba07 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/advertisements.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/advertisements.yml @@ -255,3 +255,9 @@ values: prefix: advertisement-virodrobe- count: 3 + +- type: localizedDataset + id: MedibotAds + values: + prefix: advertisement-medibot- + count: 9 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index b2fefb67ae..12788e457f 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -287,6 +287,8 @@ interactFailureString: petting-failure-medibot interactSuccessSound: path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: Advertise + pack: MedibotAds - type: entity parent: MobSiliconBase From 64ff99231ad36ccdad2dfd1f1a07370643c7c3b9 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 12:06:20 +0000 Subject: [PATCH 27/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 7235a60a0d..784f6f0de0 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: potato1234_x - changes: - - message: Changed the puddle sprites so the smoothing is less jagged - type: Tweak - id: 6173 - time: '2024-03-17T23:15:45.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26171 - author: FungiFellow changes: - message: Changed Monkey Reinf Price to 6TC @@ -3851,3 +3844,10 @@ id: 6672 time: '2024-06-03T11:54:32.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28492 +- author: Cojoke-dot + changes: + - message: Medibots will now occasionally talk + type: Tweak + id: 6673 + time: '2024-06-03T12:05:14.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28543 From a0b49116be679f2bd13c009a70f6aa4ef58b8839 Mon Sep 17 00:00:00 2001 From: Cojoke <83733158+Cojoke-dot@users.noreply.github.com> Date: Mon, 3 Jun 2024 07:10:24 -0500 Subject: [PATCH 28/63] Adds Chat Triggers to the Gasp Emote (#28466) --- Resources/Prototypes/Voice/speech_emotes.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Voice/speech_emotes.yml b/Resources/Prototypes/Voice/speech_emotes.yml index e571836976..e47d6382a1 100644 --- a/Resources/Prototypes/Voice/speech_emotes.yml +++ b/Resources/Prototypes/Voice/speech_emotes.yml @@ -1,4 +1,4 @@ -# vocal emotes +# vocal emotes - type: emote id: Scream name: chat-emote-name-scream @@ -345,6 +345,16 @@ components: - Respirator chatMessages: ["chat-emote-msg-gasp"] + chatTriggers: + - gasp + - gasp. + - gasp! + - gasps + - gasps. + - gasps! + - gasped + - gasped. + - gasped! - type: emote id: DefaultDeathgasp From f8f55dea1ee00e4e32d3852116d4c45e38694703 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 12:11:31 +0000 Subject: [PATCH 29/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 784f6f0de0..91acfe3296 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: FungiFellow - changes: - - message: Changed Monkey Reinf Price to 6TC - type: Tweak - id: 6174 - time: '2024-03-18T01:25:58.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26214 - author: Golinth changes: - message: Criminal record icons now show up below job icons @@ -3851,3 +3844,10 @@ id: 6673 time: '2024-06-03T12:05:14.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28543 +- author: Cojoke-dot + changes: + - message: The player can now use the gasping emote + type: Tweak + id: 6674 + time: '2024-06-03T12:10:25.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28466 From 50f8de08a4ce5f7647ea4cd15ddca4ac2790b55e Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:34:50 +0000 Subject: [PATCH 30/63] prevent nukie kidnapping (#28387) --- Content.Server/Antag/AntagSelectionSystem.cs | 21 +++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Content.Server/Antag/AntagSelectionSystem.cs b/Content.Server/Antag/AntagSelectionSystem.cs index 47da1b6475..710bb8f3d7 100644 --- a/Content.Server/Antag/AntagSelectionSystem.cs +++ b/Content.Server/Antag/AntagSelectionSystem.cs @@ -182,20 +182,20 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem GameTicker.PlayerGameStatuses[x.UserId] == PlayerGameStatus.JoinedGame) .ToList(); - ChooseAntags((uid, component), players); + ChooseAntags((uid, component), players, midround: true); } /// /// Chooses antagonists from the given selection of players /// - public void ChooseAntags(Entity ent, IList pool) + public void ChooseAntags(Entity ent, IList pool, bool midround = false) { if (ent.Comp.SelectionsComplete) return; foreach (var def in ent.Comp.Definitions) { - ChooseAntags(ent, pool, def); + ChooseAntags(ent, pool, def, midround: midround); } ent.Comp.SelectionsComplete = true; @@ -204,17 +204,28 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem /// Chooses antagonists from the given selection of players for the given antag definition. /// - public void ChooseAntags(Entity ent, IList pool, AntagSelectionDefinition def) + /// Disable picking players for pre-spawn antags in the middle of a round + public void ChooseAntags(Entity ent, IList pool, AntagSelectionDefinition def, bool midround = false) { var playerPool = GetPlayerPool(ent, pool, def); var count = GetTargetAntagCount(ent, GetTotalPlayerCount(pool), def); // if there is both a spawner and players getting picked, let it fall back to a spawner. var noSpawner = def.SpawnerPrototype == null; + var picking = def.PickPlayer; + if (midround && ent.Comp.SelectionTime == AntagSelectionTime.PrePlayerSpawn) + { + // prevent antag selection from happening if the round is on-going, requiring a spawner if used midround. + // this is so rules like nukies, if added by an admin midround, dont make random living people nukies + Log.Info($"Antags for rule {ent:?} get picked pre-spawn so only spawners will be made."); + DebugTools.Assert(def.SpawnerPrototype != null, $"Rule {ent:?} had no spawner for pre-spawn rule added mid-round!"); + picking = false; + } + for (var i = 0; i < count; i++) { var session = (ICommonSession?) null; - if (def.PickPlayer) + if (picking) { if (!playerPool.TryPickAndTake(RobustRandom, out session) && noSpawner) { From 977bd5ad6dd1a6fe7a32721f296129cd3bb6bbce Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:39:25 +0000 Subject: [PATCH 31/63] make GameRule use entity category (#28294) --- .../Components/GameRuleComponent.cs | 3 +- Resources/Locale/en-US/entity-categories.ftl | 1 + Resources/Prototypes/Entities/categories.yml | 5 +++ .../Prototypes/GameRules/cargo_gifts.yml | 10 ------ Resources/Prototypes/GameRules/events.yml | 33 ------------------- Resources/Prototypes/GameRules/midround.yml | 1 - Resources/Prototypes/GameRules/roundstart.yml | 15 --------- Resources/Prototypes/GameRules/variation.yml | 8 ----- 8 files changed, 8 insertions(+), 68 deletions(-) diff --git a/Content.Server/GameTicking/Components/GameRuleComponent.cs b/Content.Server/GameTicking/Components/GameRuleComponent.cs index 1e6c3f0ab1..635452b3f3 100644 --- a/Content.Server/GameTicking/Components/GameRuleComponent.cs +++ b/Content.Server/GameTicking/Components/GameRuleComponent.cs @@ -1,4 +1,5 @@ using Content.Server.Destructible.Thresholds; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.GameTicking.Components; @@ -7,7 +8,7 @@ namespace Content.Server.GameTicking.Components; /// Component attached to all gamerule entities. /// Used to both track the entity as well as store basic data /// -[RegisterComponent] +[RegisterComponent, EntityCategory("GameRules")] public sealed partial class GameRuleComponent : Component { /// diff --git a/Resources/Locale/en-US/entity-categories.ftl b/Resources/Locale/en-US/entity-categories.ftl index 190fe5713a..457397845d 100644 --- a/Resources/Locale/en-US/entity-categories.ftl +++ b/Resources/Locale/en-US/entity-categories.ftl @@ -1 +1,2 @@ entity-category-name-actions = Actions +entity-category-name-game-rules = Game Rules diff --git a/Resources/Prototypes/Entities/categories.yml b/Resources/Prototypes/Entities/categories.yml index 2fb56818f9..0535a8a4c2 100644 --- a/Resources/Prototypes/Entities/categories.yml +++ b/Resources/Prototypes/Entities/categories.yml @@ -2,3 +2,8 @@ id: Actions name: entity-category-name-actions hideSpawnMenu: true + +- type: entityCategory + id: GameRules + name: entity-category-name-game-rules + hideSpawnMenu: true diff --git a/Resources/Prototypes/GameRules/cargo_gifts.yml b/Resources/Prototypes/GameRules/cargo_gifts.yml index c5a5251297..ffc2ed404b 100644 --- a/Resources/Prototypes/GameRules/cargo_gifts.yml +++ b/Resources/Prototypes/GameRules/cargo_gifts.yml @@ -17,7 +17,6 @@ - type: entity id: GiftsPizzaPartySmall parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 5 @@ -35,7 +34,6 @@ - type: entity id: GiftsPizzaPartyLarge parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 2 @@ -53,7 +51,6 @@ - type: entity id: GiftsEngineering parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 5 @@ -74,7 +71,6 @@ - type: entity id: GiftsVendingRestock parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 4 @@ -95,7 +91,6 @@ - type: entity id: GiftsJanitor parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 6 @@ -113,7 +108,6 @@ - type: entity id: GiftsMedical parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 8 @@ -133,7 +127,6 @@ - type: entity id: GiftsSpacingSupplies parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 4 @@ -153,7 +146,6 @@ - type: entity id: GiftsFireProtection parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 4 @@ -171,7 +163,6 @@ - type: entity id: GiftsSecurityGuns parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 3 @@ -190,7 +181,6 @@ - type: entity id: GiftsSecurityRiot parent: CargoGiftsBase - noSpawn: true components: - type: StationEvent weight: 4 diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 9f6e6a8125..f421cf6818 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -2,7 +2,6 @@ id: BaseStationEvent parent: BaseGameRule abstract: true - noSpawn: true components: - type: GameRule delay: @@ -13,7 +12,6 @@ id: BaseStationEventShortDelay parent: BaseGameRule abstract: true - noSpawn: true components: - type: GameRule delay: @@ -24,7 +22,6 @@ id: BaseStationEventLongDelay parent: BaseGameRule abstract: true - noSpawn: true components: - type: GameRule delay: @@ -34,7 +31,6 @@ - type: entity id: AnomalySpawn parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent startAnnouncementColor: "#18abf5" @@ -47,7 +43,6 @@ - type: entity id: BluespaceArtifact parent: BaseStationEventShortDelay - noSpawn: true components: - type: GameRule delay: @@ -64,7 +59,6 @@ - type: entity id: BluespaceLocker parent: BaseGameRule - noSpawn: true components: - type: StationEvent weight: 2 @@ -76,7 +70,6 @@ - type: entity id: BreakerFlip parent: BaseGameRule - noSpawn: true components: - type: StationEvent weight: 7 @@ -87,7 +80,6 @@ - type: entity id: BureaucraticError parent: BaseGameRule - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-bureaucratic-error-announcement @@ -99,7 +91,6 @@ - type: entity id: ClericalError parent: BaseGameRule - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-clerical-error-announcement @@ -111,7 +102,6 @@ - type: entity parent: BaseGameRule id: ClosetSkeleton - noSpawn: true components: - type: StationEvent weight: 5 @@ -123,7 +113,6 @@ - type: entity parent: BaseGameRule id: DragonSpawn - noSpawn: true components: - type: StationEvent weight: 6.5 @@ -153,7 +142,6 @@ - type: entity parent: BaseGameRule id: NinjaSpawn - noSpawn: true components: - type: StationEvent weight: 6 @@ -166,7 +154,6 @@ - type: entity parent: BaseGameRule id: RevenantSpawn - noSpawn: true components: - type: StationEvent weight: 7.5 @@ -180,7 +167,6 @@ #- type: entity # id: FalseAlarm # parent: BaseGameRule -# noSpawn: true # components: # - type: StationEvent # weight: 15 @@ -190,7 +176,6 @@ - type: entity id: GasLeak parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-gas-leak-start-announcement @@ -203,7 +188,6 @@ - type: entity id: KudzuGrowth parent: BaseStationEventLongDelay - noSpawn: true components: - type: StationEvent earliestStart: 15 @@ -215,7 +199,6 @@ - type: entity id: MeteorSwarm parent: BaseStationEventLongDelay - noSpawn: true components: - type: StationEvent earliestStart: 30 @@ -233,7 +216,6 @@ - type: entity id: MouseMigration parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-vent-creatures-start-announcement @@ -259,7 +241,6 @@ - type: entity id: CockroachMigration parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-vent-creatures-start-announcement @@ -277,7 +258,6 @@ - type: entity id: PowerGridCheck parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent weight: 5 @@ -294,7 +274,6 @@ - type: entity id: RandomSentience parent: BaseGameRule - noSpawn: true components: - type: StationEvent weight: 6 @@ -307,7 +286,6 @@ - type: entity parent: BaseGameRule id: SolarFlare - noSpawn: true components: - type: StationEvent weight: 8 @@ -336,7 +314,6 @@ - type: entity id: VentClog parent: BaseStationEventLongDelay - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-vent-clog-start-announcement @@ -351,7 +328,6 @@ - type: entity id: SlimesSpawn parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-vent-creatures-start-announcement @@ -373,7 +349,6 @@ - type: entity id: SpiderSpawn parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-vent-creatures-start-announcement @@ -391,7 +366,6 @@ - type: entity id: SpiderClownSpawn parent: BaseStationEventShortDelay - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-vent-creatures-start-announcement @@ -409,7 +383,6 @@ - type: entity id: ZombieOutbreak parent: BaseGameRule - noSpawn: true components: - type: StationEvent earliestStart: 50 @@ -441,7 +414,6 @@ prototype: InitialInfected - type: entity - noSpawn: true parent: BaseNukeopsRule id: LoneOpsSpawn components: @@ -475,7 +447,6 @@ prototype: Nukeops - type: entity - noSpawn: true parent: BaseTraitorRule id: SleeperAgentsRule components: @@ -501,7 +472,6 @@ - type: entity id: MassHallucinations parent: BaseGameRule - noSpawn: true components: - type: StationEvent weight: 7 @@ -518,7 +488,6 @@ - type: entity id: ImmovableRodSpawn parent: BaseGameRule - noSpawn: true components: - type: StationEvent startAnnouncement: station-event-immovable-rod-start-announcement @@ -556,7 +525,6 @@ orGroup: rodProto - type: entity - noSpawn: true parent: BaseGameRule id: IonStorm components: @@ -569,7 +537,6 @@ - type: entity id: MimicVendorRule parent: BaseGameRule - noSpawn: true components: - type: StationEvent earliestStart: 0 diff --git a/Resources/Prototypes/GameRules/midround.yml b/Resources/Prototypes/GameRules/midround.yml index fe5af117e6..c190b0333a 100644 --- a/Resources/Prototypes/GameRules/midround.yml +++ b/Resources/Prototypes/GameRules/midround.yml @@ -18,7 +18,6 @@ threats: NinjaThreats - type: entity - noSpawn: true parent: BaseGameRule id: Thief components: diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index cf2c5b2f47..3493749457 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -1,12 +1,10 @@ - type: entity id: BaseGameRule abstract: true - noSpawn: true components: - type: GameRule - type: entity - noSpawn: true parent: BaseGameRule id: RespawnDeadRule components: @@ -17,7 +15,6 @@ deleteBody: false - type: entity - noSpawn: true parent: BaseGameRule id: SubGamemodesRule components: @@ -29,7 +26,6 @@ - type: entity id: DeathMatch31 parent: BaseGameRule - noSpawn: true components: - type: DeathMatchRule rewardSpawns: @@ -59,7 +55,6 @@ - type: entity id: InactivityTimeRestart parent: BaseGameRule - noSpawn: true components: - type: InactivityRule inactivityMaxTime: 600 @@ -68,7 +63,6 @@ - type: entity id: MaxTimeRestart parent: BaseGameRule - noSpawn: true components: - type: MaxTimeRestartRule roundMaxTime: 300 @@ -88,7 +82,6 @@ - type: AntagLoadProfileRule - type: entity - noSpawn: true parent: BaseNukeopsRule id: Nukeops components: @@ -166,7 +159,6 @@ agentName: traitor-round-end-agent-name - type: entity - noSpawn: true parent: BaseTraitorRule id: Traitor components: @@ -188,7 +180,6 @@ - type: entity id: Revolutionary parent: BaseGameRule - noSpawn: true components: - type: GameRule minPlayers: 15 @@ -213,21 +204,18 @@ - type: entity id: Sandbox parent: BaseGameRule - noSpawn: true components: - type: SandboxRule - type: entity id: Secret parent: BaseGameRule - noSpawn: true components: - type: SecretRule - type: entity id: Zombie parent: BaseGameRule - noSpawn: true components: - type: GameRule minPlayers: 20 @@ -260,14 +248,12 @@ - type: entity id: BasicStationEventScheduler parent: BaseGameRule - noSpawn: true components: - type: BasicStationEventScheduler - type: entity id: RampingStationEventScheduler parent: BaseGameRule - noSpawn: true components: - type: RampingStationEventScheduler @@ -275,7 +261,6 @@ - type: entity id: BasicRoundstartVariation parent: BaseGameRule - noSpawn: true components: - type: RoundstartStationVariationRule rules: diff --git a/Resources/Prototypes/GameRules/variation.yml b/Resources/Prototypes/GameRules/variation.yml index 2884d5f9d6..093a832d72 100644 --- a/Resources/Prototypes/GameRules/variation.yml +++ b/Resources/Prototypes/GameRules/variation.yml @@ -4,7 +4,6 @@ id: BaseVariationPass parent: BaseGameRule abstract: true - noSpawn: true components: - type: StationVariationPassRule @@ -13,14 +12,12 @@ - type: entity id: BasicPoweredLightVariationPass parent: BaseVariationPass - noSpawn: true components: - type: PoweredLightVariationPass - type: entity id: SolidWallRustingVariationPass parent: BaseVariationPass - noSpawn: true components: - type: WallReplaceVariationPass - type: EntityReplaceVariationPass @@ -32,7 +29,6 @@ - type: entity id: ReinforcedWallRustingVariationPass parent: BaseVariationPass - noSpawn: true components: - type: ReinforcedWallReplaceVariationPass - type: EntityReplaceVariationPass @@ -44,7 +40,6 @@ - type: entity id: BasicTrashVariationPass parent: BaseVariationPass - noSpawn: true components: - type: EntitySpawnVariationPass tilesPerEntityAverage: 35 @@ -105,7 +100,6 @@ - type: entity id: BasicPuddleMessVariationPass parent: BaseVariationPass - noSpawn: true components: - type: PuddleMessVariationPass randomPuddleSolutionFill: RandomFillTrashPuddle @@ -113,7 +107,6 @@ - type: entity id: BloodbathPuddleMessVariationPass parent: BaseVariationPass - noSpawn: true components: - type: PuddleMessVariationPass tilesPerSpillAverage: 150 @@ -123,7 +116,6 @@ - type: entity id: CutWireVariationPass parent: BaseVariationPass - noSpawn: true components: - type: CutWireVariationPass wireCutChance: 0.01 From e784f2cf3c638d9df1834751924916548389a1ab Mon Sep 17 00:00:00 2001 From: Cojoke <83733158+Cojoke-dot@users.noreply.github.com> Date: Mon, 3 Jun 2024 08:04:07 -0500 Subject: [PATCH 32/63] Make projectiles not hit crates unless clicked on (#28072) --- .../RequireProjectileTargetComponent.cs | 14 +++++ .../Systems/RequireProjectileTargetSystem.cs | 51 +++++++++++++++++++ .../Systems/MobStateSystem.Subscribers.cs | 17 ------- Resources/Prototypes/Entities/Mobs/base.yml | 4 +- .../Storage/Crates/base_structurecrates.yml | 1 + 5 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 Content.Shared/Damage/Components/RequireProjectileTargetComponent.cs create mode 100644 Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs diff --git a/Content.Shared/Damage/Components/RequireProjectileTargetComponent.cs b/Content.Shared/Damage/Components/RequireProjectileTargetComponent.cs new file mode 100644 index 0000000000..5bd8292daa --- /dev/null +++ b/Content.Shared/Damage/Components/RequireProjectileTargetComponent.cs @@ -0,0 +1,14 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Damage.Components; + +/// +/// Prevent the object from getting hit by projetiles unless you target the object. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RequireProjectileTargetSystem))] +public sealed partial class RequireProjectileTargetComponent : Component +{ + [DataField, AutoNetworkedField] + public bool Active = true; +} diff --git a/Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs b/Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs new file mode 100644 index 0000000000..79b374a60f --- /dev/null +++ b/Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs @@ -0,0 +1,51 @@ +using Content.Shared.Projectiles; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Standing; +using Robust.Shared.Physics.Events; + +namespace Content.Shared.Damage.Components; + +public sealed class RequireProjectileTargetSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(PreventCollide); + SubscribeLocalEvent(StandingBulletHit); + SubscribeLocalEvent(LayingBulletPass); + } + + private void PreventCollide(Entity ent, ref PreventCollideEvent args) + { + if (args.Cancelled) + return; + + if (!ent.Comp.Active) + return; + + var other = args.OtherEntity; + if (HasComp(other) && + CompOrNull(other)?.Target != ent) + { + args.Cancelled = true; + } + } + + private void SetActive(Entity ent, bool value) + { + if (ent.Comp.Active == value) + return; + + ent.Comp.Active = value; + Dirty(ent); + } + + private void StandingBulletHit(Entity ent, ref StoodEvent args) + { + SetActive(ent, false); + } + + private void LayingBulletPass(Entity ent, ref DownedEvent args) + { + SetActive(ent, true); + } +} diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs index ee747554e1..08b351e61e 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -46,7 +46,6 @@ public partial class MobStateSystem SubscribeLocalEvent(OnSleepAttempt); SubscribeLocalEvent(OnCombatModeShouldHandInteract); SubscribeLocalEvent(OnAttemptPacifiedAttack); - SubscribeLocalEvent(OnPreventCollide); } private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state) @@ -179,21 +178,5 @@ public partial class MobStateSystem args.Cancelled = true; } - private void OnPreventCollide(Entity ent, ref PreventCollideEvent args) - { - if (args.Cancelled) - return; - - if (IsAlive(ent, ent)) - return; - - var other = args.OtherEntity; - if (HasComp(other) && - CompOrNull(other)?.Target != ent.Owner) - { - args.Cancelled = true; - } - } - #endregion } diff --git a/Resources/Prototypes/Entities/Mobs/base.yml b/Resources/Prototypes/Entities/Mobs/base.yml index 0a2b68d0a1..fae4711310 100644 --- a/Resources/Prototypes/Entities/Mobs/base.yml +++ b/Resources/Prototypes/Entities/Mobs/base.yml @@ -1,4 +1,4 @@ -# The progenitor. This should only container the most basic components possible. +# The progenitor. This should only container the most basic components possible. # Only put things on here if every mob *must* have it. This includes ghosts. - type: entity save: false @@ -43,6 +43,8 @@ - type: MovementSpeedModifier - type: Polymorphable - type: StatusIcon + - type: RequireProjectileTarget + active: False # Used for mobs that have health and can take damage. - type: entity diff --git a/Resources/Prototypes/Entities/Structures/Storage/Crates/base_structurecrates.yml b/Resources/Prototypes/Entities/Structures/Storage/Crates/base_structurecrates.yml index 2d84541231..01c226cb0f 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Crates/base_structurecrates.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Crates/base_structurecrates.yml @@ -89,6 +89,7 @@ node: crategenericsteel containers: - entity_storage + - type: RequireProjectileTarget - type: entity parent: CrateGeneric From 33d963a149a0b0ad0a7dc29a0c3ef808c98f8bd2 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 13:05:14 +0000 Subject: [PATCH 33/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 91acfe3296..0587709ee3 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Golinth - changes: - - message: Criminal record icons now show up below job icons - type: Tweak - id: 6175 - time: '2024-03-18T01:37:00.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26203 - author: PJB3005 changes: - message: Fixed pressure damage calculations to what they were always supposed @@ -3851,3 +3844,13 @@ id: 6674 time: '2024-06-03T12:10:25.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28466 +- author: Cojoke-dot + changes: + - message: Bullets no longer hit crates unless directly clicked on while shooting. + type: Tweak + - message: Bullets now pass over mobs that are lying down unless directly clicked + on while shooting. + type: Tweak + id: 6675 + time: '2024-06-03T13:04:07.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28072 From 8d78b7442af48ff87607efbcdfb4692a00678daa Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:23:52 +0000 Subject: [PATCH 34/63] make objectives use entityCategory (#28269) --- .../Components/ObjectiveComponent.cs | 10 +++-- Resources/Locale/en-US/entity-categories.ftl | 1 + Resources/Prototypes/Entities/categories.yml | 5 +++ .../Prototypes/Objectives/base_objectives.yml | 6 +-- Resources/Prototypes/Objectives/dragon.yml | 2 - Resources/Prototypes/Objectives/ninja.yml | 6 --- Resources/Prototypes/Objectives/thief.yml | 41 ------------------- Resources/Prototypes/Objectives/traitor.yml | 19 --------- 8 files changed, 15 insertions(+), 75 deletions(-) diff --git a/Content.Shared/Objectives/Components/ObjectiveComponent.cs b/Content.Shared/Objectives/Components/ObjectiveComponent.cs index 95fbc68561..36d3fa0bde 100644 --- a/Content.Shared/Objectives/Components/ObjectiveComponent.cs +++ b/Content.Shared/Objectives/Components/ObjectiveComponent.cs @@ -2,6 +2,7 @@ using Content.Shared.Mind; using Content.Shared.Objectives; using Content.Shared.Objectives.Systems; using Robust.Shared.Utility; +using Robust.Shared.Prototypes; namespace Content.Shared.Objectives.Components; @@ -9,32 +10,33 @@ namespace Content.Shared.Objectives.Components; /// Required component for an objective entity prototype. /// [RegisterComponent, Access(typeof(SharedObjectivesSystem))] +[EntityCategory("Objectives")] public sealed partial class ObjectiveComponent : Component { /// /// Difficulty rating used to avoid assigning too many difficult objectives. /// - [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + [DataField(required: true)] public float Difficulty; /// /// Organisation that issued this objective, used for grouping and as a header above common objectives. /// - [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + [DataField(required: true)] public string Issuer = string.Empty; /// /// Unique objectives can only have 1 per prototype id. /// Set this to false if you want multiple objectives of the same prototype. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public bool Unique = true; /// /// Icon of this objective to display in the character menu. /// Can be specified by an handler but is usually done in the prototype. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public SpriteSpecifier? Icon; } diff --git a/Resources/Locale/en-US/entity-categories.ftl b/Resources/Locale/en-US/entity-categories.ftl index 457397845d..6067830b7a 100644 --- a/Resources/Locale/en-US/entity-categories.ftl +++ b/Resources/Locale/en-US/entity-categories.ftl @@ -1,2 +1,3 @@ entity-category-name-actions = Actions entity-category-name-game-rules = Game Rules +entity-category-name-objectives = Objectives \ No newline at end of file diff --git a/Resources/Prototypes/Entities/categories.yml b/Resources/Prototypes/Entities/categories.yml index 0535a8a4c2..bc4dd104de 100644 --- a/Resources/Prototypes/Entities/categories.yml +++ b/Resources/Prototypes/Entities/categories.yml @@ -7,3 +7,8 @@ id: GameRules name: entity-category-name-game-rules hideSpawnMenu: true + +- type: entityCategory + id: Objectives + name: entity-category-name-objectives + hideSpawnMenu: true \ No newline at end of file diff --git a/Resources/Prototypes/Objectives/base_objectives.yml b/Resources/Prototypes/Objectives/base_objectives.yml index 2ab5149213..1fbd23dfce 100644 --- a/Resources/Prototypes/Objectives/base_objectives.yml +++ b/Resources/Prototypes/Objectives/base_objectives.yml @@ -1,6 +1,6 @@ # OBJECTIVE STYLE -# in comments anything that says final prototype means the objective that isnt abstract -# the final prototype must be noSpawn to avoid showing in f5 +# in comments anything that says final prototype means the objective that isnt abstract. +# you dont need noSpawn because Objectives category is automatically added, which has hideSpawnmenu # components are listed in this order: # 1. Objective # 2. requirement components @@ -8,7 +8,7 @@ # 4. the condition component # all objectives should inherit this at some point -# then have its difficulty etc fields set in the final objective prototypes +# then have its icon etc fields set in the final objective prototypes - type: entity abstract: true id: BaseObjective diff --git a/Resources/Prototypes/Objectives/dragon.yml b/Resources/Prototypes/Objectives/dragon.yml index 2cf7eb292f..10ca942cb3 100644 --- a/Resources/Prototypes/Objectives/dragon.yml +++ b/Resources/Prototypes/Objectives/dragon.yml @@ -13,7 +13,6 @@ - DragonRole - type: entity - noSpawn: true parent: BaseDragonObjective id: CarpRiftsObjective components: @@ -30,7 +29,6 @@ - type: CarpRiftsCondition - type: entity - noSpawn: true parent: [BaseDragonObjective, BaseSurviveObjective] id: DragonSurviveObjective name: Survive diff --git a/Resources/Prototypes/Objectives/ninja.yml b/Resources/Prototypes/Objectives/ninja.yml index bc17992e90..3c2fbcaca8 100644 --- a/Resources/Prototypes/Objectives/ninja.yml +++ b/Resources/Prototypes/Objectives/ninja.yml @@ -13,7 +13,6 @@ - NinjaRole - type: entity - noSpawn: true parent: BaseNinjaObjective id: DoorjackObjective components: @@ -29,7 +28,6 @@ - type: DoorjackCondition - type: entity - noSpawn: true parent: BaseNinjaObjective id: StealResearchObjective description: Your gloves can be used to hack a research server and steal its precious data. If science has been slacking you'll have to get to work. @@ -45,7 +43,6 @@ - type: StealResearchCondition - type: entity - noSpawn: true parent: [BaseNinjaObjective, BaseCodeObjective] id: SpiderChargeObjective description: This bomb can be detonated in a specific location. Note that the bomb will not work anywhere else! @@ -56,7 +53,6 @@ state: icon - type: entity - noSpawn: true parent: [BaseNinjaObjective, BaseSurviveObjective] id: NinjaSurviveObjective name: Survive @@ -68,7 +64,6 @@ state: icon - type: entity - noSpawn: true parent: [BaseNinjaObjective, BaseCodeObjective] id: TerrorObjective name: Call in a threat @@ -80,7 +75,6 @@ state: red_phone - type: entity - noSpawn: true parent: [BaseNinjaObjective, BaseCodeObjective] id: MassArrestObjective name: Set everyone to wanted diff --git a/Resources/Prototypes/Objectives/thief.yml b/Resources/Prototypes/Objectives/thief.yml index 1815485097..8b5307e9a0 100644 --- a/Resources/Prototypes/Objectives/thief.yml +++ b/Resources/Prototypes/Objectives/thief.yml @@ -55,7 +55,6 @@ # Collections - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: FigurineStealCollectionObjective components: @@ -67,7 +66,6 @@ difficulty: 0.25 - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: HeadCloakStealCollectionObjective components: @@ -79,7 +77,6 @@ difficulty: 1.5 - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: HeadBedsheetStealCollectionObjective components: @@ -91,7 +88,6 @@ difficulty: 1.0 - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: StampStealCollectionObjective components: @@ -103,7 +99,6 @@ difficulty: 1.0 - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: DoorRemoteStealCollectionObjective components: @@ -115,7 +110,6 @@ difficulty: 1.5 - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: TechnologyDiskStealCollectionObjective components: @@ -130,7 +124,6 @@ difficulty: 0.8 - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: IDCardsStealCollectionObjective components: @@ -145,7 +138,6 @@ - type: entity - noSpawn: true parent: BaseThiefStealCollectionObjective id: LAMPStealCollectionObjective components: @@ -163,7 +155,6 @@ # steal item - type: entity #Security subgroup - noSpawn: true parent: BaseThiefStealObjective id: ForensicScannerStealObjective components: @@ -175,7 +166,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: FlippoEngravedLighterStealObjective components: @@ -187,7 +177,6 @@ difficulty: 0.8 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: ClothingHeadHatWardenStealObjective components: @@ -197,7 +186,6 @@ difficulty: 1.2 - type: entity #Medical subgroup - noSpawn: true parent: BaseThiefStealObjective id: ClothingOuterHardsuitVoidParamedStealObjective components: @@ -209,7 +197,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: MedicalTechFabCircuitboardStealObjective components: @@ -221,7 +208,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: ClothingHeadsetAltMedicalStealObjective components: @@ -233,7 +219,6 @@ difficulty: 1 - type: entity #Engineering subgroup - noSpawn: true parent: BaseThiefStealObjective id: FireAxeStealObjective components: @@ -245,7 +230,6 @@ difficulty: 0.8 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: AmePartFlatpackStealObjective components: @@ -257,7 +241,6 @@ difficulty: 1 - type: entity #Cargo subgroup - noSpawn: true parent: BaseThiefStealObjective id: ExpeditionsCircuitboardStealObjective components: @@ -269,7 +252,6 @@ difficulty: 0.7 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: CargoShuttleCircuitboardStealObjective components: @@ -281,7 +263,6 @@ difficulty: 0.7 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: SalvageShuttleCircuitboardStealObjective components: @@ -293,7 +274,6 @@ difficulty: 0.7 - type: entity #Service subgroup - noSpawn: true parent: BaseThiefStealObjective id: ClothingEyesHudBeerStealObjective components: @@ -305,7 +285,6 @@ difficulty: 0.3 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: BibleStealObjective components: @@ -317,7 +296,6 @@ difficulty: 0.4 - type: entity #Other subgroup - noSpawn: true parent: BaseThiefStealObjective id: ClothingNeckGoldmedalStealObjective components: @@ -329,7 +307,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealObjective id: ClothingNeckClownmedalStealObjective components: @@ -343,7 +320,6 @@ # Structures - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: NuclearBombStealObjective components: @@ -355,7 +331,6 @@ difficulty: 2.5 #Good luck - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: FaxMachineCaptainStealObjective components: @@ -367,7 +342,6 @@ difficulty: 2 - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: ChemDispenserStealObjective components: @@ -379,7 +353,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: XenoArtifactStealObjective components: @@ -391,7 +364,6 @@ difficulty: 0.5 - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: FreezerHeaterStealObjective components: @@ -403,7 +375,6 @@ difficulty: 0.5 - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: TegStealObjective components: @@ -415,7 +386,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: BoozeDispenserStealObjective components: @@ -427,7 +397,6 @@ difficulty: 0.5 - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: AltarNanotrasenStealObjective components: @@ -439,7 +408,6 @@ difficulty: 0.5 - type: entity - noSpawn: true parent: BaseThiefStealStructureObjective id: PlantRDStealObjective components: @@ -453,7 +421,6 @@ # Animal - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: IanStealObjective components: @@ -465,7 +432,6 @@ difficulty: 2.5 - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: BingusStealObjective components: @@ -475,7 +441,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: McGriffStealObjective components: @@ -487,7 +452,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: WalterStealObjective components: @@ -499,7 +463,6 @@ difficulty: 1 - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: MortyStealObjective components: @@ -509,7 +472,6 @@ difficulty: 0.5 - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: RenaultStealObjective components: @@ -521,7 +483,6 @@ difficulty: 2 - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: ShivaStealObjective components: @@ -533,7 +494,6 @@ difficulty: 2 - type: entity - noSpawn: true parent: BaseThiefStealAnimalObjective id: TropicoStealObjective components: @@ -547,7 +507,6 @@ # Escape - type: entity - noSpawn: true parent: [BaseThiefObjective, BaseLivingObjective] id: EscapeThiefShuttleObjective name: Escape to centcom alive and unrestrained. diff --git a/Resources/Prototypes/Objectives/traitor.yml b/Resources/Prototypes/Objectives/traitor.yml index 14397535d4..ad5f56a443 100644 --- a/Resources/Prototypes/Objectives/traitor.yml +++ b/Resources/Prototypes/Objectives/traitor.yml @@ -36,7 +36,6 @@ # state - type: entity - noSpawn: true parent: [BaseTraitorObjective, BaseLivingObjective] id: EscapeShuttleObjective name: Escape to centcom alive and unrestrained. @@ -50,7 +49,6 @@ - type: EscapeShuttleCondition - type: entity - noSpawn: true parent: BaseTraitorObjective id: DieObjective name: Die a glorious death @@ -69,7 +67,6 @@ - type: DieCondition #- type: entity -# noSpawn: true # parent: [BaseTraitorObjective, BaseLivingObjective] # id: HijackShuttleObjective # name: Hijack emergency shuttle @@ -85,7 +82,6 @@ # kill - type: entity - noSpawn: true parent: [BaseTraitorObjective, BaseKillObjective] id: KillRandomPersonObjective description: Do it however you like, just make sure they don't make it to centcom. @@ -98,7 +94,6 @@ - type: PickRandomPerson - type: entity - noSpawn: true parent: [BaseTraitorObjective, BaseKillObjective] id: KillRandomHeadObjective description: We need this head gone and you probably know why. Good luck, agent. @@ -119,7 +114,6 @@ # social - type: entity - noSpawn: true parent: [BaseTraitorSocialObjective, BaseKeepAliveObjective] id: RandomTraitorAliveObjective description: Identify yourself at your own risk. We just need them alive. @@ -131,7 +125,6 @@ - type: RandomTraitorAlive - type: entity - noSpawn: true parent: [BaseTraitorSocialObjective, BaseHelpProgressObjective] id: RandomTraitorProgressObjective description: Identify yourself at your own risk. We just need them to succeed. @@ -157,7 +150,6 @@ owner: job-name-cmo - type: entity - noSpawn: true parent: BaseCMOStealObjective id: CMOHyposprayStealObjective components: @@ -165,7 +157,6 @@ stealGroup: Hypospray - type: entity - noSpawn: true parent: BaseCMOStealObjective id: CMOCrewMonitorStealObjective components: @@ -185,7 +176,6 @@ owner: job-name-rd - type: entity - noSpawn: true parent: BaseRDStealObjective id: RDHardsuitStealObjective components: @@ -196,7 +186,6 @@ difficulty: 3 - type: entity - noSpawn: true parent: BaseRDStealObjective id: HandTeleporterStealObjective components: @@ -206,7 +195,6 @@ ## hos - type: entity - noSpawn: true parent: BaseTraitorStealObjective id: SecretDocumentsStealObjective components: @@ -222,7 +210,6 @@ ## ce - type: entity - noSpawn: true parent: BaseTraitorStealObjective id: MagbootsStealObjective components: @@ -235,7 +222,6 @@ ## qm - type: entity - noSpawn: true parent: BaseTraitorStealObjective id: ClipboardStealObjective components: @@ -248,7 +234,6 @@ ## hop - type: entity - noSpawn: true parent: BaseTraitorStealObjective id: CorgiMeatStealObjective components: @@ -274,7 +259,6 @@ job: Captain - type: entity - noSpawn: true parent: BaseCaptainObjective id: CaptainIDStealObjective components: @@ -282,7 +266,6 @@ stealGroup: CaptainIDCard - type: entity - noSpawn: true parent: BaseCaptainObjective id: CaptainJetpackStealObjective components: @@ -290,7 +273,6 @@ stealGroup: JetpackCaptainFilled - type: entity - noSpawn: true parent: BaseCaptainObjective id: CaptainGunStealObjective components: @@ -299,7 +281,6 @@ owner: job-name-captain - type: entity - noSpawn: true parent: BaseCaptainObjective id: NukeDiskStealObjective components: From def04cdaf52ee4e39fe269d3a92d94d02e1e3dc0 Mon Sep 17 00:00:00 2001 From: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com> Date: Mon, 3 Jun 2024 06:30:47 -0700 Subject: [PATCH 35/63] Add more info to GettingAttackedAttemptEvent (#28548) --- Content.Shared/ActionBlocker/ActionBlockerSystem.cs | 6 +----- .../Interaction/Events/GettingAttackedAttemptEvent.cs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs index d2883b5ef5..f1c77fda43 100644 --- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs +++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs @@ -1,13 +1,9 @@ -using Content.Shared.Bed.Sleep; using Content.Shared.Body.Events; -using Content.Shared.DragDrop; using Content.Shared.Emoting; using Content.Shared.Hands; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Item; -using Content.Shared.Mobs; -using Content.Shared.Mobs.Components; using Content.Shared.Movement.Components; using Content.Shared.Movement.Events; using Content.Shared.Speech; @@ -194,7 +190,7 @@ namespace Content.Shared.ActionBlocker if (target == null) return true; - var tev = new GettingAttackedAttemptEvent(); + var tev = new GettingAttackedAttemptEvent(uid, weapon, disarm); RaiseLocalEvent(target.Value, ref tev); return !tev.Cancelled; } diff --git a/Content.Shared/Interaction/Events/GettingAttackedAttemptEvent.cs b/Content.Shared/Interaction/Events/GettingAttackedAttemptEvent.cs index ed7379fd72..d37c810e3f 100644 --- a/Content.Shared/Interaction/Events/GettingAttackedAttemptEvent.cs +++ b/Content.Shared/Interaction/Events/GettingAttackedAttemptEvent.cs @@ -4,4 +4,4 @@ namespace Content.Shared.Interaction.Events; /// Raised directed on the target entity when being attacked. /// [ByRefEvent] -public record struct GettingAttackedAttemptEvent(bool Cancelled); +public record struct GettingAttackedAttemptEvent(EntityUid Attacker, EntityUid? Weapon, bool Disarm, bool Cancelled = false); From 0b4388d5d423669f7a3d431ea4f983f3ef50a06d Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Tue, 4 Jun 2024 01:36:07 +1200 Subject: [PATCH 36/63] Try fix KeyNotFoundException in KillTrackingSystem (#28553) --- .../KillTracking/KillTrackingSystem.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Content.Server/KillTracking/KillTrackingSystem.cs b/Content.Server/KillTracking/KillTrackingSystem.cs index 63627fd1b9..ba27ea5d9e 100644 --- a/Content.Server/KillTracking/KillTrackingSystem.cs +++ b/Content.Server/KillTracking/KillTrackingSystem.cs @@ -2,6 +2,7 @@ using Content.Server.NPC.HTN; using Content.Shared.Damage; using Content.Shared.FixedPoint; using Content.Shared.Mobs; +using Content.Shared.Mobs.Systems; using Robust.Shared.Player; namespace Content.Server.KillTracking; @@ -14,7 +15,8 @@ public sealed class KillTrackingSystem : EntitySystem /// public override void Initialize() { - SubscribeLocalEvent(OnDamageChanged); + // Add damage to LifetimeDamage before MobStateChangedEvent gets raised + SubscribeLocalEvent(OnDamageChanged, before: [ typeof(MobThresholdSystem) ]); SubscribeLocalEvent(OnMobStateChanged); } @@ -50,7 +52,7 @@ public sealed class KillTrackingSystem : EntitySystem var largestSource = GetLargestSource(component.LifetimeDamage); largestSource ??= killImpulse; - KillSource? killSource; + KillSource killSource; KillSource? assistSource = null; if (killImpulse is KillEnvironmentSource) @@ -69,13 +71,13 @@ public sealed class KillTrackingSystem : EntitySystem killSource = killImpulse; // no assist is given to environmental kills - if (largestSource is not KillEnvironmentSource) + if (largestSource is not KillEnvironmentSource + && component.LifetimeDamage.TryGetValue(largestSource, out var largestDamage)) { - // you have to do at least 50% of largest source's damage to get the assist. - if (component.LifetimeDamage[largestSource] >= component.LifetimeDamage[killSource] / 2) - { + var killDamage = component.LifetimeDamage.GetValueOrDefault(killSource); + // you have to do at least twice as much damage as the killing source to get the assist. + if (largestDamage >= killDamage / 2) assistSource = largestSource; - } } } From 87ffbab4614ff616447d7a89d161a699d5750013 Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Mon, 3 Jun 2024 15:37:30 +0200 Subject: [PATCH 37/63] Remove locale related changelog (#28547) --- Resources/Changelog/Changelog.yml | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0587709ee3..cab645fa8d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -3787,25 +3787,18 @@ id: 6666 time: '2024-06-02T17:30:27.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28518 -- author: Voomra - changes: - - message: localize Pray UI - type: Fix - id: 6667 - time: '2024-06-02T23:51:19.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/28535 - author: Whisper changes: - message: Renamed the player-obtainable "admin cloak" to "weh cloak". type: Tweak - id: 6668 + id: 6667 time: '2024-06-03T02:18:49.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28540 - author: Vermidia changes: - message: Glass shards are no longer weldable with an unlit welder. type: Fix - id: 6669 + id: 6668 time: '2024-06-03T03:28:53.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27959 - author: AJCM-git @@ -3813,35 +3806,35 @@ - message: Biomass reclaimers no longer act as a void to any unfortunate belongings a corpse may be wearing type: Tweak - id: 6670 + id: 6669 time: '2024-06-03T03:30:00.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28544 - author: Laneron changes: - message: Jetpack UI window now has correctly displayed header type: Fix - id: 6671 + id: 6670 time: '2024-06-03T03:33:31.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28545 - author: Vermidia changes: - message: SyndiCats now spawn from a radio like other reinforcements. type: Tweak - id: 6672 + id: 6671 time: '2024-06-03T11:54:32.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28492 - author: Cojoke-dot changes: - message: Medibots will now occasionally talk type: Tweak - id: 6673 + id: 6672 time: '2024-06-03T12:05:14.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28543 - author: Cojoke-dot changes: - message: The player can now use the gasping emote type: Tweak - id: 6674 + id: 6673 time: '2024-06-03T12:10:25.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28466 - author: Cojoke-dot @@ -3851,6 +3844,6 @@ - message: Bullets now pass over mobs that are lying down unless directly clicked on while shooting. type: Tweak - id: 6675 + id: 6674 time: '2024-06-03T13:04:07.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28072 From 8c105810109a076c30518f0b122b58fcac354bd7 Mon Sep 17 00:00:00 2001 From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:12:21 -0400 Subject: [PATCH 38/63] Cleans up StatusIconSystem and fixing some bugs (#28270) --- .../UI/AgentIDCardBoundUserInterface.cs | 4 +- .../Access/UI/AgentIDCardWindow.xaml.cs | 8 +-- Content.Client/Antag/AntagStatusIconSystem.cs | 55 ------------------- .../Commands/ShowHealthBarsCommand.cs | 1 + Content.Client/LateJoin/LateJoinGui.cs | 2 +- .../Lobby/UI/HumanoidProfileEditor.xaml.cs | 2 +- .../Overlays/EntityHealthBarOverlay.cs | 26 +++++---- .../Overlays/ShowCriminalRecordIconsSystem.cs | 4 +- .../Overlays/ShowHealthBarsSystem.cs | 14 ++++- .../Overlays/ShowHealthIconsSystem.cs | 3 +- .../Overlays/ShowHungerIconsSystem.cs | 2 +- Content.Client/Overlays/ShowJobIconsSystem.cs | 2 +- .../Overlays/ShowMindShieldIconsSystem.cs | 4 +- .../Overlays/ShowSyndicateIconsSystem.cs | 3 +- .../Overlays/ShowThirstIconsSystem.cs | 2 +- .../Revolutionary/RevolutionarySystem.cs | 37 +++++-------- .../SSDIndicator/SSDIndicatorSystem.cs | 3 +- .../StatusIcon/StatusIconOverlay.cs | 4 +- Content.Client/StatusIcon/StatusIconSystem.cs | 36 +++++++++++- Content.Client/Stealth/StealthSystem.cs | 3 +- Content.Client/Zombies/ZombieSystem.cs | 50 ++++++++--------- .../Access/Components/AgentIDCardComponent.cs | 6 +- .../Access/Systems/AgentIDCardSystem.cs | 8 +-- .../Access/Systems/IdCardConsoleSystem.cs | 2 +- .../Access/Systems/PresetIdCardSystem.cs | 4 +- .../Revolutionary/RevolutionarySystem.cs | 5 ++ .../Station/Systems/StationSpawningSystem.cs | 4 +- .../Access/SharedAgentIDCardSystem.cs | 10 ++-- .../Antag/IAntagStatusIconComponent.cs | 12 ---- .../Antag/ShowAntagIconsComponent.cs | 9 +++ .../Overlays/ShowHealthBarsComponent.cs | 5 ++ .../Components/HeadRevolutionaryComponent.cs | 5 +- .../Components/RevolutionaryComponent.cs | 5 +- .../Components/ShowRevIconsComponent.cs | 11 ---- .../SharedRevolutionarySystem.cs | 22 +++----- Content.Shared/Roles/JobPrototype.cs | 4 +- .../SSDIndicator/SSDIndicatorComponent.cs | 5 +- .../Components/StatusIconComponent.cs | 14 +---- .../StatusIcon/StatusIconPrototype.cs | 42 +++++++++++--- .../Zombies/InitialInfectedComponent.cs | 8 +-- .../Zombies/ShowZombieIconsComponent.cs | 12 ---- Content.Shared/Zombies/ZombieComponent.cs | 5 +- .../Entities/Mobs/Player/admin_ghost.yml | 3 +- .../{ => StatusIcon}/StatusEffects/health.yml | 0 .../{ => StatusIcon}/StatusEffects/hunger.yml | 0 .../{ => StatusIcon}/StatusEffects/ssd.yml | 0 Resources/Prototypes/StatusIcon/antag.yml | 17 ++++++ .../{StatusEffects => StatusIcon}/job.yml | 0 .../security.yml | 0 49 files changed, 224 insertions(+), 259 deletions(-) delete mode 100644 Content.Client/Antag/AntagStatusIconSystem.cs create mode 100644 Content.Server/Revolutionary/RevolutionarySystem.cs delete mode 100644 Content.Shared/Antag/IAntagStatusIconComponent.cs create mode 100644 Content.Shared/Antag/ShowAntagIconsComponent.cs delete mode 100644 Content.Shared/Revolutionary/Components/ShowRevIconsComponent.cs delete mode 100644 Content.Shared/Zombies/ShowZombieIconsComponent.cs rename Resources/Prototypes/{ => StatusIcon}/StatusEffects/health.yml (100%) rename Resources/Prototypes/{ => StatusIcon}/StatusEffects/hunger.yml (100%) rename Resources/Prototypes/{ => StatusIcon}/StatusEffects/ssd.yml (100%) rename Resources/Prototypes/{StatusEffects => StatusIcon}/job.yml (100%) rename Resources/Prototypes/{StatusEffects => StatusIcon}/security.yml (100%) diff --git a/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs b/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs index c3fac8cb92..761f52988a 100644 --- a/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs +++ b/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs @@ -1,5 +1,7 @@ using Content.Shared.Access.Systems; +using Content.Shared.StatusIcon; using Robust.Client.GameObjects; +using Robust.Shared.Prototypes; namespace Content.Client.Access.UI { @@ -40,7 +42,7 @@ namespace Content.Client.Access.UI SendMessage(new AgentIDCardJobChangedMessage(newJob)); } - public void OnJobIconChanged(string newJobIconId) + public void OnJobIconChanged(ProtoId newJobIconId) { SendMessage(new AgentIDCardJobIconChangedMessage(newJobIconId)); } diff --git a/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs b/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs index 9a38c0c485..6d0b2a184f 100644 --- a/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs +++ b/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs @@ -38,7 +38,7 @@ namespace Content.Client.Access.UI JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text); } - public void SetAllowedIcons(HashSet icons, string currentJobIconId) + public void SetAllowedIcons(HashSet> icons, string currentJobIconId) { IconGrid.DisposeAllChildren(); @@ -46,10 +46,8 @@ namespace Content.Client.Access.UI var i = 0; foreach (var jobIconId in icons) { - if (!_prototypeManager.TryIndex(jobIconId, out var jobIcon)) - { + if (!_prototypeManager.TryIndex(jobIconId, out var jobIcon)) continue; - } String styleBase = StyleBase.ButtonOpenBoth; var modulo = i % JobIconColumnCount; @@ -77,7 +75,7 @@ namespace Content.Client.Access.UI }; jobIconButton.AddChild(jobIconTexture); - jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIcon.ID); + jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIconId); IconGrid.AddChild(jobIconButton); if (jobIconId.Equals(currentJobIconId)) diff --git a/Content.Client/Antag/AntagStatusIconSystem.cs b/Content.Client/Antag/AntagStatusIconSystem.cs deleted file mode 100644 index 804ae21ad4..0000000000 --- a/Content.Client/Antag/AntagStatusIconSystem.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Content.Shared.Antag; -using Content.Shared.Revolutionary.Components; -using Content.Shared.StatusIcon; -using Content.Shared.StatusIcon.Components; -using Content.Shared.Zombies; -using Robust.Client.Player; -using Robust.Shared.Prototypes; - -namespace Content.Client.Antag; - -/// -/// Used for assigning specified icons for antags. -/// -public sealed class AntagStatusIconSystem : SharedStatusIconSystem -{ - [Dependency] private readonly IPrototypeManager _prototype = default!; - [Dependency] private readonly IPlayerManager _player = default!; - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(GetRevIcon); - SubscribeLocalEvent(GetIcon); - SubscribeLocalEvent(GetIcon); - SubscribeLocalEvent(GetIcon); - } - - /// - /// Adds a Status Icon on an entity if the player is supposed to see it. - /// - private void GetIcon(EntityUid uid, T comp, ref GetStatusIconsEvent ev) where T: IAntagStatusIconComponent - { - var ent = _player.LocalSession?.AttachedEntity; - - var canEv = new CanDisplayStatusIconsEvent(ent); - RaiseLocalEvent(uid, ref canEv); - - if (!canEv.Cancelled) - ev.StatusIcons.Add(_prototype.Index(comp.StatusIcon)); - } - - - /// - /// Adds the Rev Icon on an entity if the player is supposed to see it. This additional function is needed to deal - /// with a special case where if someone is a head rev we only want to display the headrev icon. - /// - private void GetRevIcon(EntityUid uid, RevolutionaryComponent comp, ref GetStatusIconsEvent ev) - { - if (HasComp(uid)) - return; - - GetIcon(uid, comp, ref ev); - - } -} diff --git a/Content.Client/Commands/ShowHealthBarsCommand.cs b/Content.Client/Commands/ShowHealthBarsCommand.cs index bd3e21718f..ef918313a0 100644 --- a/Content.Client/Commands/ShowHealthBarsCommand.cs +++ b/Content.Client/Commands/ShowHealthBarsCommand.cs @@ -35,6 +35,7 @@ public sealed class ShowHealthBarsCommand : LocalizedCommands var showHealthBarsComponent = new ShowHealthBarsComponent { DamageContainers = args.ToList(), + HealthStatusIcon = "", NetSyncEnabled = false }; diff --git a/Content.Client/LateJoin/LateJoinGui.cs b/Content.Client/LateJoin/LateJoinGui.cs index ba9351d674..252aa9aafa 100644 --- a/Content.Client/LateJoin/LateJoinGui.cs +++ b/Content.Client/LateJoin/LateJoinGui.cs @@ -244,7 +244,7 @@ namespace Content.Client.LateJoin VerticalAlignment = VAlignment.Center }; - var jobIcon = _prototypeManager.Index(prototype.Icon); + var jobIcon = _prototypeManager.Index(prototype.Icon); icon.Texture = _sprites.Frame0(jobIcon.Icon); jobSelector.AddChild(icon); diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs index eb182c83ee..53c332c185 100644 --- a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs @@ -806,7 +806,7 @@ namespace Content.Client.Lobby.UI TextureScale = new Vector2(2, 2), VerticalAlignment = VAlignment.Center }; - var jobIcon = _prototypeManager.Index(job.Icon); + var jobIcon = _prototypeManager.Index(job.Icon); icon.Texture = jobIcon.Icon.Frame0(); selector.Setup(items, job.LocalizedName, 200, job.LocalizedDescription, icon); diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index 758bb562f9..55978d98f7 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -1,14 +1,17 @@ using System.Numerics; +using Content.Client.StatusIcon; using Content.Client.UserInterface.Systems; using Content.Shared.Damage; using Content.Shared.FixedPoint; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; +using Content.Shared.StatusIcon; using Content.Shared.StatusIcon.Components; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Shared.Enums; +using Robust.Shared.Prototypes; using static Robust.Shared.Maths.Color; namespace Content.Client.Overlays; @@ -19,19 +22,27 @@ namespace Content.Client.Overlays; public sealed class EntityHealthBarOverlay : Overlay { private readonly IEntityManager _entManager; + private readonly IPrototypeManager _prototype; + private readonly SharedTransformSystem _transform; private readonly MobStateSystem _mobStateSystem; private readonly MobThresholdSystem _mobThresholdSystem; + private readonly StatusIconSystem _statusIconSystem; private readonly ProgressColorSystem _progressColor; + + public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; public HashSet DamageContainers = new(); + public ProtoId StatusIcon; - public EntityHealthBarOverlay(IEntityManager entManager) + public EntityHealthBarOverlay(IEntityManager entManager, IPrototypeManager prototype) { _entManager = entManager; + _prototype = prototype; _transform = _entManager.System(); _mobStateSystem = _entManager.System(); _mobThresholdSystem = _entManager.System(); + _statusIconSystem = _entManager.System(); _progressColor = _entManager.System(); } @@ -44,6 +55,7 @@ public sealed class EntityHealthBarOverlay : Overlay const float scale = 1f; var scaleMatrix = Matrix3Helpers.CreateScale(new Vector2(scale, scale)); var rotationMatrix = Matrix3Helpers.CreateRotation(-rotation); + _prototype.TryIndex(StatusIcon, out var statusIcon); var query = _entManager.AllEntityQueryEnumerator(); while (query.MoveNext(out var uid, @@ -52,31 +64,23 @@ public sealed class EntityHealthBarOverlay : Overlay out var damageableComponent, out var spriteComponent)) { - if (_entManager.TryGetComponent(uid, out var metaDataComponent) && - metaDataComponent.Flags.HasFlag(MetaDataFlags.InContainer)) - { + if (statusIcon != null && !_statusIconSystem.IsVisible((uid, _entManager.GetComponent(uid)), statusIcon)) continue; - } + // We want the stealth user to still be able to see his health bar himself if (!xformQuery.TryGetComponent(uid, out var xform) || xform.MapID != args.MapId) - { continue; - } if (damageableComponent.DamageContainerID == null || !DamageContainers.Contains(damageableComponent.DamageContainerID)) - { continue; - } // we use the status icon component bounds if specified otherwise use sprite var bounds = _entManager.GetComponentOrNull(uid)?.Bounds ?? spriteComponent.Bounds; var worldPos = _transform.GetWorldPosition(xform, xformQuery); if (!bounds.Translated(worldPos).Intersects(args.WorldAABB)) - { continue; - } // we are all progressing towards death every day if (CalcProgress(uid, mobStateComponent, damageableComponent, mobThresholdsComponent) is not { } deathProgress) diff --git a/Content.Client/Overlays/ShowCriminalRecordIconsSystem.cs b/Content.Client/Overlays/ShowCriminalRecordIconsSystem.cs index 8f23cd510c..c353b17272 100644 --- a/Content.Client/Overlays/ShowCriminalRecordIconsSystem.cs +++ b/Content.Client/Overlays/ShowCriminalRecordIconsSystem.cs @@ -19,10 +19,10 @@ public sealed class ShowCriminalRecordIconsSystem : EquipmentHudSystem(component.StatusIcon.Id, out var iconPrototype)) + if (_prototype.TryIndex(component.StatusIcon, out var iconPrototype)) ev.StatusIcons.Add(iconPrototype); } } diff --git a/Content.Client/Overlays/ShowHealthBarsSystem.cs b/Content.Client/Overlays/ShowHealthBarsSystem.cs index 170f552cf3..1eb712a898 100644 --- a/Content.Client/Overlays/ShowHealthBarsSystem.cs +++ b/Content.Client/Overlays/ShowHealthBarsSystem.cs @@ -2,6 +2,8 @@ using Content.Shared.Inventory.Events; using Content.Shared.Overlays; using Robust.Client.Graphics; using System.Linq; +using Robust.Client.Player; +using Robust.Shared.Prototypes; namespace Content.Client.Overlays; @@ -11,6 +13,7 @@ namespace Content.Client.Overlays; public sealed class ShowHealthBarsSystem : EquipmentHudSystem { [Dependency] private readonly IOverlayManager _overlayMan = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; private EntityHealthBarOverlay _overlay = default!; @@ -18,16 +21,21 @@ public sealed class ShowHealthBarsSystem : EquipmentHudSystem component) { base.UpdateInternal(component); - foreach (var damageContainerId in component.Components.SelectMany(x => x.DamageContainers)) + foreach (var comp in component.Components) { - _overlay.DamageContainers.Add(damageContainerId); + foreach (var damageContainerId in comp.DamageContainers) + { + _overlay.DamageContainers.Add(damageContainerId); + } + + _overlay.StatusIcon = comp.HealthStatusIcon; } if (!_overlayMan.HasOverlay()) diff --git a/Content.Client/Overlays/ShowHealthIconsSystem.cs b/Content.Client/Overlays/ShowHealthIconsSystem.cs index a546cf4d82..d8af91482b 100644 --- a/Content.Client/Overlays/ShowHealthIconsSystem.cs +++ b/Content.Client/Overlays/ShowHealthIconsSystem.cs @@ -24,7 +24,6 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem(OnGetStatusIconsEvent); - } protected override void UpdateInternal(RefreshEquipmentHudEvent component) @@ -46,7 +45,7 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem entity, ref GetStatusIconsEvent args) { - if (!IsActive || args.InContainer) + if (!IsActive) return; var healthIcons = DecideHealthIcons(entity); diff --git a/Content.Client/Overlays/ShowHungerIconsSystem.cs b/Content.Client/Overlays/ShowHungerIconsSystem.cs index b1c0f3a1a0..6b0d575a81 100644 --- a/Content.Client/Overlays/ShowHungerIconsSystem.cs +++ b/Content.Client/Overlays/ShowHungerIconsSystem.cs @@ -18,7 +18,7 @@ public sealed class ShowHungerIconsSystem : EquipmentHudSystem(component.MindShieldStatusIcon.Id, out var iconPrototype)) + if (_prototype.TryIndex(component.MindShieldStatusIcon, out var iconPrototype)) ev.StatusIcons.Add(iconPrototype); } } diff --git a/Content.Client/Overlays/ShowSyndicateIconsSystem.cs b/Content.Client/Overlays/ShowSyndicateIconsSystem.cs index 660ef198e1..782178a29d 100644 --- a/Content.Client/Overlays/ShowSyndicateIconsSystem.cs +++ b/Content.Client/Overlays/ShowSyndicateIconsSystem.cs @@ -19,11 +19,10 @@ public sealed class ShowSyndicateIconsSystem : EquipmentHudSystem(component.SyndStatusIcon, out var iconPrototype)) ev.StatusIcons.Add(iconPrototype); } } - diff --git a/Content.Client/Overlays/ShowThirstIconsSystem.cs b/Content.Client/Overlays/ShowThirstIconsSystem.cs index b08aa4340b..44be1f7a67 100644 --- a/Content.Client/Overlays/ShowThirstIconsSystem.cs +++ b/Content.Client/Overlays/ShowThirstIconsSystem.cs @@ -18,7 +18,7 @@ public sealed class ShowThirstIconsSystem : EquipmentHudSystem /// Used for the client to get status icons from other revs. /// -public sealed class RevolutionarySystem : EntitySystem +public sealed class RevolutionarySystem : SharedRevolutionarySystem { + [Dependency] private readonly IPrototypeManager _prototype = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnCanShowRevIcon); - SubscribeLocalEvent(OnCanShowRevIcon); + SubscribeLocalEvent(GetRevIcon); + SubscribeLocalEvent(GetHeadRevIcon); } - /// - /// Determine whether a client should display the rev icon. - /// - private void OnCanShowRevIcon(EntityUid uid, T comp, ref CanDisplayStatusIconsEvent args) where T : IAntagStatusIconComponent + private void GetRevIcon(Entity ent, ref GetStatusIconsEvent args) { - args.Cancelled = !CanDisplayIcon(args.User, comp.IconVisibleToGhost); + if (HasComp(ent)) + return; + + if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype)) + args.StatusIcons.Add(iconPrototype); } - /// - /// The criteria that determine whether a client should see Rev/Head rev icons. - /// - private bool CanDisplayIcon(EntityUid? uid, bool visibleToGhost) + private void GetHeadRevIcon(Entity ent, ref GetStatusIconsEvent args) { - if (HasComp(uid) || HasComp(uid)) - return true; - - if (visibleToGhost && HasComp(uid)) - return true; - - return HasComp(uid); + if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype)) + args.StatusIcons.Add(iconPrototype); } - } diff --git a/Content.Client/SSDIndicator/SSDIndicatorSystem.cs b/Content.Client/SSDIndicator/SSDIndicatorSystem.cs index 587450a2f6..e731195317 100644 --- a/Content.Client/SSDIndicator/SSDIndicatorSystem.cs +++ b/Content.Client/SSDIndicator/SSDIndicatorSystem.cs @@ -30,13 +30,12 @@ public sealed class SSDIndicatorSystem : EntitySystem { if (component.IsSSD && _cfg.GetCVar(CCVars.ICShowSSDIndicator) && - !args.InContainer && !_mobState.IsDead(uid) && !HasComp(uid) && TryComp(uid, out var mindContainer) && mindContainer.ShowExamineInfo) { - args.StatusIcons.Add(_prototype.Index(component.Icon)); + args.StatusIcons.Add(_prototype.Index(component.Icon)); } } } diff --git a/Content.Client/StatusIcon/StatusIconOverlay.cs b/Content.Client/StatusIcon/StatusIconOverlay.cs index f1473bda7a..4b3daae22f 100644 --- a/Content.Client/StatusIcon/StatusIconOverlay.cs +++ b/Content.Client/StatusIcon/StatusIconOverlay.cs @@ -45,7 +45,7 @@ public sealed class StatusIconOverlay : Overlay var query = _entity.AllEntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp, out var sprite, out var xform, out var meta)) { - if (xform.MapID != args.MapId) + if (xform.MapID != args.MapId || !sprite.Visible) continue; var bounds = comp.Bounds ?? sprite.Bounds; @@ -72,6 +72,8 @@ public sealed class StatusIconOverlay : Overlay foreach (var proto in icons) { + if (!_statusIcon.IsVisible((uid, meta), proto)) + continue; var curTime = _timing.RealTime; var texture = _sprite.GetFrame(proto.Icon, curTime); diff --git a/Content.Client/StatusIcon/StatusIconSystem.cs b/Content.Client/StatusIcon/StatusIconSystem.cs index 980fd9f2a9..63f5776769 100644 --- a/Content.Client/StatusIcon/StatusIconSystem.cs +++ b/Content.Client/StatusIcon/StatusIconSystem.cs @@ -1,7 +1,11 @@ using Content.Shared.CCVar; +using Content.Shared.Ghost; using Content.Shared.StatusIcon; using Content.Shared.StatusIcon.Components; +using Content.Shared.Stealth.Components; +using Content.Shared.Whitelist; using Robust.Client.Graphics; +using Robust.Client.Player; using Robust.Shared.Configuration; namespace Content.Client.StatusIcon; @@ -13,6 +17,8 @@ public sealed class StatusIconSystem : SharedStatusIconSystem { [Dependency] private readonly IConfigurationManager _configuration = default!; [Dependency] private readonly IOverlayManager _overlay = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!; private bool _globalEnabled; private bool _localEnabled; @@ -54,10 +60,34 @@ public sealed class StatusIconSystem : SharedStatusIconSystem if (meta.EntityLifeStage >= EntityLifeStage.Terminating) return list; - var inContainer = (meta.Flags & MetaDataFlags.InContainer) != 0; - var ev = new GetStatusIconsEvent(list, inContainer); + var ev = new GetStatusIconsEvent(list); RaiseLocalEvent(uid, ref ev); return ev.StatusIcons; } -} + /// + /// For overlay to check if an entity can be seen. + /// + public bool IsVisible(Entity ent, StatusIconData data) + { + var viewer = _playerManager.LocalSession?.AttachedEntity; + + // Always show our icons to our entity + if (viewer == ent.Owner) + return true; + + if (data.VisibleToGhosts && HasComp(viewer)) + return true; + + if (data.HideInContainer && (ent.Comp.Flags & MetaDataFlags.InContainer) != 0) + return false; + + if (data.HideOnStealth && TryComp(ent, out var stealth) && stealth.Enabled) + return false; + + if (data.ShowTo != null && !_entityWhitelist.IsValid(data.ShowTo, viewer)) + return false; + + return true; + } +} diff --git a/Content.Client/Stealth/StealthSystem.cs b/Content.Client/Stealth/StealthSystem.cs index b60ffc2a40..0b94e41f6b 100644 --- a/Content.Client/Stealth/StealthSystem.cs +++ b/Content.Client/Stealth/StealthSystem.cs @@ -1,4 +1,5 @@ using Content.Client.Interactable.Components; +using Content.Client.StatusIcon; using Content.Shared.Stealth; using Content.Shared.Stealth.Components; using Robust.Client.GameObjects; @@ -18,6 +19,7 @@ public sealed class StealthSystem : SharedStealthSystem base.Initialize(); _shader = _protoMan.Index("Stealth").InstanceUnique(); + SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnShaderRender); @@ -93,4 +95,3 @@ public sealed class StealthSystem : SharedStealthSystem args.Sprite.Color = new Color(visibility, visibility, 1, 1); } } - diff --git a/Content.Client/Zombies/ZombieSystem.cs b/Content.Client/Zombies/ZombieSystem.cs index 49b5d6aec1..d250e41850 100644 --- a/Content.Client/Zombies/ZombieSystem.cs +++ b/Content.Client/Zombies/ZombieSystem.cs @@ -1,21 +1,40 @@ using System.Linq; using Content.Shared.Ghost; using Content.Shared.Humanoid; +using Content.Shared.StatusIcon; using Content.Shared.StatusIcon.Components; using Content.Shared.Zombies; using Robust.Client.GameObjects; +using Robust.Shared.Prototypes; namespace Content.Client.Zombies; -public sealed class ZombieSystem : EntitySystem +public sealed class ZombieSystem : SharedZombieSystem { + [Dependency] private readonly IPrototypeManager _prototype = default!; + public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnCanDisplayStatusIcons); - SubscribeLocalEvent(OnCanDisplayStatusIcons); + SubscribeLocalEvent(GetZombieIcon); + SubscribeLocalEvent(GetInitialInfectedIcon); + } + + private void GetZombieIcon(Entity ent, ref GetStatusIconsEvent args) + { + var iconPrototype = _prototype.Index(ent.Comp.StatusIcon); + args.StatusIcons.Add(iconPrototype); + } + + private void GetInitialInfectedIcon(Entity ent, ref GetStatusIconsEvent args) + { + if (HasComp(ent)) + return; + + var iconPrototype = _prototype.Index(ent.Comp.StatusIcon); + args.StatusIcons.Add(iconPrototype); } private void OnStartup(EntityUid uid, ZombieComponent component, ComponentStartup args) @@ -31,29 +50,4 @@ public sealed class ZombieSystem : EntitySystem sprite.LayerSetColor(i, component.SkinColor); } } - - /// - /// Determines whether a player should be able to see the StatusIcon for zombies. - /// - private void OnCanDisplayStatusIcons(EntityUid uid, ZombieComponent component, ref CanDisplayStatusIconsEvent args) - { - if (HasComp(args.User) || HasComp(args.User) || HasComp(args.User)) - return; - - if (component.IconVisibleToGhost && HasComp(args.User)) - return; - - args.Cancelled = true; - } - - private void OnCanDisplayStatusIcons(EntityUid uid, InitialInfectedComponent component, ref CanDisplayStatusIconsEvent args) - { - if (HasComp(args.User) && !HasComp(args.User)) - return; - - if (component.IconVisibleToGhost && HasComp(args.User)) - return; - - args.Cancelled = true; - } } diff --git a/Content.Server/Access/Components/AgentIDCardComponent.cs b/Content.Server/Access/Components/AgentIDCardComponent.cs index 4b92b43ea9..7a97c5f565 100644 --- a/Content.Server/Access/Components/AgentIDCardComponent.cs +++ b/Content.Server/Access/Components/AgentIDCardComponent.cs @@ -1,5 +1,5 @@ using Content.Shared.StatusIcon; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; +using Robust.Shared.Prototypes; namespace Content.Server.Access.Components { @@ -9,7 +9,7 @@ namespace Content.Server.Access.Components /// /// Set of job icons that the agent ID card can show. /// - [DataField("icons", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] - public HashSet Icons = new(); + [DataField] + public HashSet> Icons; } } diff --git a/Content.Server/Access/Systems/AgentIDCardSystem.cs b/Content.Server/Access/Systems/AgentIDCardSystem.cs index d5e9dc357d..f0ce3acbdb 100644 --- a/Content.Server/Access/Systems/AgentIDCardSystem.cs +++ b/Content.Server/Access/Systems/AgentIDCardSystem.cs @@ -90,14 +90,10 @@ namespace Content.Server.Access.Systems private void OnJobIconChanged(EntityUid uid, AgentIDCardComponent comp, AgentIDCardJobIconChangedMessage args) { if (!TryComp(uid, out var idCard)) - { return; - } - if (!_prototypeManager.TryIndex(args.JobIconId, out var jobIcon)) - { + if (!_prototypeManager.TryIndex(args.JobIconId, out var jobIcon)) return; - } _cardSystem.TryChangeJobIcon(uid, jobIcon, idCard); @@ -109,7 +105,7 @@ namespace Content.Server.Access.Systems { foreach (var jobPrototype in _prototypeManager.EnumeratePrototypes()) { - if(jobPrototype.Icon == jobIcon.ID) + if (jobPrototype.Icon == jobIcon.ID) { job = jobPrototype; return true; diff --git a/Content.Server/Access/Systems/IdCardConsoleSystem.cs b/Content.Server/Access/Systems/IdCardConsoleSystem.cs index 4e63c93a83..e02664f2bb 100644 --- a/Content.Server/Access/Systems/IdCardConsoleSystem.cs +++ b/Content.Server/Access/Systems/IdCardConsoleSystem.cs @@ -129,7 +129,7 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem _idCard.TryChangeJobTitle(targetId, newJobTitle, player: player); if (_prototype.TryIndex(newJobProto, out var job) - && _prototype.TryIndex(job.Icon, out var jobIcon)) + && _prototype.TryIndex(job.Icon, out var jobIcon)) { _idCard.TryChangeJobIcon(targetId, jobIcon, player: player); _idCard.TryChangeJobDepartment(targetId, job); diff --git a/Content.Server/Access/Systems/PresetIdCardSystem.cs b/Content.Server/Access/Systems/PresetIdCardSystem.cs index 3e775b9c35..426e523243 100644 --- a/Content.Server/Access/Systems/PresetIdCardSystem.cs +++ b/Content.Server/Access/Systems/PresetIdCardSystem.cs @@ -82,9 +82,7 @@ public sealed class PresetIdCardSystem : EntitySystem _cardSystem.TryChangeJobTitle(uid, job.LocalizedName); _cardSystem.TryChangeJobDepartment(uid, job); - if (_prototypeManager.TryIndex(job.Icon, out var jobIcon)) - { + if (_prototypeManager.TryIndex(job.Icon, out var jobIcon)) _cardSystem.TryChangeJobIcon(uid, jobIcon); - } } } diff --git a/Content.Server/Revolutionary/RevolutionarySystem.cs b/Content.Server/Revolutionary/RevolutionarySystem.cs new file mode 100644 index 0000000000..597c4896b9 --- /dev/null +++ b/Content.Server/Revolutionary/RevolutionarySystem.cs @@ -0,0 +1,5 @@ +using Content.Shared.Revolutionary; + +namespace Content.Server.Revolutionary; + +public sealed class RevolutionarySystem : SharedRevolutionarySystem; diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index f175565a5a..557a1f9566 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -257,10 +257,8 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem _cardSystem.TryChangeFullName(cardId, characterName, card); _cardSystem.TryChangeJobTitle(cardId, jobPrototype.LocalizedName, card); - if (_prototypeManager.TryIndex(jobPrototype.Icon, out var jobIcon)) - { + if (_prototypeManager.TryIndex(jobPrototype.Icon, out var jobIcon)) _cardSystem.TryChangeJobIcon(cardId, jobIcon, card); - } var extendedAccess = false; if (station != null) diff --git a/Content.Shared/Access/SharedAgentIDCardSystem.cs b/Content.Shared/Access/SharedAgentIDCardSystem.cs index d027a3937f..91aa626fe3 100644 --- a/Content.Shared/Access/SharedAgentIDCardSystem.cs +++ b/Content.Shared/Access/SharedAgentIDCardSystem.cs @@ -1,3 +1,5 @@ +using Content.Shared.StatusIcon; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; namespace Content.Shared.Access.Systems @@ -23,12 +25,12 @@ namespace Content.Shared.Access.Systems [Serializable, NetSerializable] public sealed class AgentIDCardBoundUserInterfaceState : BoundUserInterfaceState { - public readonly HashSet Icons; + public readonly HashSet> Icons; public string CurrentName { get; } public string CurrentJob { get; } public string CurrentJobIconId { get; } - public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, string currentJobIconId, HashSet icons) + public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, string currentJobIconId, HashSet> icons) { Icons = icons; CurrentName = currentName; @@ -62,9 +64,9 @@ namespace Content.Shared.Access.Systems [Serializable, NetSerializable] public sealed class AgentIDCardJobIconChangedMessage : BoundUserInterfaceMessage { - public string JobIconId { get; } + public ProtoId JobIconId { get; } - public AgentIDCardJobIconChangedMessage(string jobIconId) + public AgentIDCardJobIconChangedMessage(ProtoId jobIconId) { JobIconId = jobIconId; } diff --git a/Content.Shared/Antag/IAntagStatusIconComponent.cs b/Content.Shared/Antag/IAntagStatusIconComponent.cs deleted file mode 100644 index 981937c916..0000000000 --- a/Content.Shared/Antag/IAntagStatusIconComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Content.Shared.StatusIcon; -using Robust.Shared.Prototypes; - -namespace Content.Shared.Antag; - -public interface IAntagStatusIconComponent -{ - public ProtoId StatusIcon { get; set; } - - public bool IconVisibleToGhost { get; set; } -} - diff --git a/Content.Shared/Antag/ShowAntagIconsComponent.cs b/Content.Shared/Antag/ShowAntagIconsComponent.cs new file mode 100644 index 0000000000..c451b69c3e --- /dev/null +++ b/Content.Shared/Antag/ShowAntagIconsComponent.cs @@ -0,0 +1,9 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Antag; + +/// +/// Determines whether Someone can see antags icons +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class ShowAntagIconsComponent: Component; diff --git a/Content.Shared/Overlays/ShowHealthBarsComponent.cs b/Content.Shared/Overlays/ShowHealthBarsComponent.cs index 48e3162269..1297d56838 100644 --- a/Content.Shared/Overlays/ShowHealthBarsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthBarsComponent.cs @@ -1,5 +1,7 @@ using Content.Shared.Damage.Prototypes; +using Content.Shared.StatusIcon; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; namespace Content.Shared.Overlays; @@ -15,4 +17,7 @@ public sealed partial class ShowHealthBarsComponent : Component /// [DataField("damageContainers", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List DamageContainers = new(); + + [DataField] + public ProtoId HealthStatusIcon = "HealthIconFine"; } diff --git a/Content.Shared/Revolutionary/Components/HeadRevolutionaryComponent.cs b/Content.Shared/Revolutionary/Components/HeadRevolutionaryComponent.cs index d2c8374fef..ef2bad65e0 100644 --- a/Content.Shared/Revolutionary/Components/HeadRevolutionaryComponent.cs +++ b/Content.Shared/Revolutionary/Components/HeadRevolutionaryComponent.cs @@ -9,7 +9,7 @@ namespace Content.Shared.Revolutionary.Components; /// Component used for marking a Head Rev for conversion and winning/losing. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedRevolutionarySystem))] -public sealed partial class HeadRevolutionaryComponent : Component, IAntagStatusIconComponent +public sealed partial class HeadRevolutionaryComponent : Component { /// /// The status icon corresponding to the head revolutionary. @@ -24,7 +24,4 @@ public sealed partial class HeadRevolutionaryComponent : Component, IAntagStatus public TimeSpan StunTime = TimeSpan.FromSeconds(3); public override bool SessionSpecific => true; - - [DataField] - public bool IconVisibleToGhost { get; set; } = true; } diff --git a/Content.Shared/Revolutionary/Components/RevolutionaryComponent.cs b/Content.Shared/Revolutionary/Components/RevolutionaryComponent.cs index 73f533cf69..1f6b45ddea 100644 --- a/Content.Shared/Revolutionary/Components/RevolutionaryComponent.cs +++ b/Content.Shared/Revolutionary/Components/RevolutionaryComponent.cs @@ -10,7 +10,7 @@ namespace Content.Shared.Revolutionary.Components; /// Used for marking regular revs as well as storing icon prototypes so you can see fellow revs. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedRevolutionarySystem))] -public sealed partial class RevolutionaryComponent : Component, IAntagStatusIconComponent +public sealed partial class RevolutionaryComponent : Component { /// /// The status icon prototype displayed for revolutionaries @@ -25,7 +25,4 @@ public sealed partial class RevolutionaryComponent : Component, IAntagStatusIcon public SoundSpecifier RevStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/headrev_start.ogg"); public override bool SessionSpecific => true; - - [DataField] - public bool IconVisibleToGhost { get; set; } = true; } diff --git a/Content.Shared/Revolutionary/Components/ShowRevIconsComponent.cs b/Content.Shared/Revolutionary/Components/ShowRevIconsComponent.cs deleted file mode 100644 index 11e20db3f8..0000000000 --- a/Content.Shared/Revolutionary/Components/ShowRevIconsComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Robust.Shared.GameStates; - -namespace Content.Shared.Revolutionary.Components; - -/// -/// Determines whether Someone can see rev/headrev icons on revs. -/// -[RegisterComponent, NetworkedComponent] -public sealed partial class ShowRevIconsComponent: Component -{ -} diff --git a/Content.Shared/Revolutionary/SharedRevolutionarySystem.cs b/Content.Shared/Revolutionary/SharedRevolutionarySystem.cs index ddaf73fcc9..bbf91193cc 100644 --- a/Content.Shared/Revolutionary/SharedRevolutionarySystem.cs +++ b/Content.Shared/Revolutionary/SharedRevolutionarySystem.cs @@ -1,4 +1,3 @@ -using Content.Shared.Ghost; using Content.Shared.IdentityManagement; using Content.Shared.Mindshield.Components; using Content.Shared.Popups; @@ -6,10 +5,11 @@ using Content.Shared.Revolutionary.Components; using Content.Shared.Stunnable; using Robust.Shared.GameStates; using Robust.Shared.Player; +using Content.Shared.Antag; namespace Content.Shared.Revolutionary; -public sealed class SharedRevolutionarySystem : EntitySystem +public abstract class SharedRevolutionarySystem : EntitySystem { [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedStunSystem _sharedStun = default!; @@ -23,7 +23,7 @@ public sealed class SharedRevolutionarySystem : EntitySystem SubscribeLocalEvent(OnRevCompGetStateAttempt); SubscribeLocalEvent(DirtyRevComps); SubscribeLocalEvent(DirtyRevComps); - SubscribeLocalEvent(DirtyRevComps); + SubscribeLocalEvent(DirtyRevComps); } /// @@ -52,7 +52,7 @@ public sealed class SharedRevolutionarySystem : EntitySystem /// private void OnRevCompGetStateAttempt(EntityUid uid, HeadRevolutionaryComponent comp, ref ComponentGetStateAttemptEvent args) { - args.Cancelled = !CanGetState(args.Player, comp.IconVisibleToGhost); + args.Cancelled = !CanGetState(args.Player); } /// @@ -60,30 +60,24 @@ public sealed class SharedRevolutionarySystem : EntitySystem /// private void OnRevCompGetStateAttempt(EntityUid uid, RevolutionaryComponent comp, ref ComponentGetStateAttemptEvent args) { - args.Cancelled = !CanGetState(args.Player, comp.IconVisibleToGhost); + args.Cancelled = !CanGetState(args.Player); } /// /// The criteria that determine whether a Rev/HeadRev component should be sent to a client. /// /// The Player the component will be sent to. - /// Whether the component permits the icon to be visible to observers. /// - private bool CanGetState(ICommonSession? player, bool visibleToGhosts) + private bool CanGetState(ICommonSession? player) { //Apparently this can be null in replays so I am just returning true. - if (player is null) + if (player?.AttachedEntity is not {} uid) return true; - var uid = player.AttachedEntity; - if (HasComp(uid) || HasComp(uid)) return true; - if (visibleToGhosts && HasComp(uid)) - return true; - - return HasComp(uid); + return HasComp(uid); } /// /// Dirties all the Rev components so they are sent to clients. diff --git a/Content.Shared/Roles/JobPrototype.cs b/Content.Shared/Roles/JobPrototype.cs index 2959b56497..0b3bfb4438 100644 --- a/Content.Shared/Roles/JobPrototype.cs +++ b/Content.Shared/Roles/JobPrototype.cs @@ -97,8 +97,8 @@ namespace Content.Shared.Roles [DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? JobEntity = null; - [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Icon { get; private set; } = "JobIconUnknown"; + [DataField] + public ProtoId Icon { get; private set; } = "JobIconUnknown"; [DataField("special", serverOnly: true)] public JobSpecial[] Special { get; private set; } = Array.Empty(); diff --git a/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs b/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs index 66310505a1..ee67e3296f 100644 --- a/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs +++ b/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.StatusIcon; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Shared.SSDIndicator; @@ -16,6 +17,6 @@ public sealed partial class SSDIndicatorComponent : Component public bool IsSSD = true; [ViewVariables(VVAccess.ReadWrite)] - [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Icon = "SSDIcon"; + [DataField] + public ProtoId Icon = "SSDIcon"; } diff --git a/Content.Shared/StatusIcon/Components/StatusIconComponent.cs b/Content.Shared/StatusIcon/Components/StatusIconComponent.cs index 385f9760c6..c56be7c96a 100644 --- a/Content.Shared/StatusIcon/Components/StatusIconComponent.cs +++ b/Content.Shared/StatusIcon/Components/StatusIconComponent.cs @@ -24,16 +24,4 @@ public sealed partial class StatusIconComponent : Component /// /// [ByRefEvent] -public record struct GetStatusIconsEvent(List StatusIcons, bool InContainer); - -/// -/// Event raised on the Client-side to determine whether to display a status icon on an entity. -/// -/// The player that will see the icons -[ByRefEvent] -public record struct CanDisplayStatusIconsEvent(EntityUid? User = null) -{ - public EntityUid? User = User; - - public bool Cancelled = false; -} +public record struct GetStatusIconsEvent(List StatusIcons); diff --git a/Content.Shared/StatusIcon/StatusIconPrototype.cs b/Content.Shared/StatusIcon/StatusIconPrototype.cs index 2bd13b9361..29a1b60114 100644 --- a/Content.Shared/StatusIcon/StatusIconPrototype.cs +++ b/Content.Shared/StatusIcon/StatusIconPrototype.cs @@ -1,3 +1,5 @@ +using Content.Shared.Stealth.Components; +using Content.Shared.Whitelist; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; @@ -15,26 +17,45 @@ public partial class StatusIconData : IComparable /// /// The icon that's displayed on the entity. /// - [DataField("icon", required: true)] + [DataField(required: true)] public SpriteSpecifier Icon = default!; /// /// A priority for the order in which the icons will be displayed. /// - [DataField("priority")] + [DataField] public int Priority = 10; + /// + /// Whether or not to hide the icon to ghosts + /// + [DataField] + public bool VisibleToGhosts = true; + + /// + /// Whether or not to hide the icon when we are inside a container like a locker or a crate. + /// + [DataField] + public bool HideInContainer = true; + + /// + /// Whether or not to hide the icon when the entity has an active + /// + [DataField] + public bool HideOnStealth = true; + + /// + /// Specifies what entities and components/tags this icon can be shown to. + /// + [DataField] + public EntityWhitelist? ShowTo; + /// /// A preference for where the icon will be displayed. None | Left | Right /// - [DataField("locationPreference")] + [DataField] public StatusIconLocationPreference LocationPreference = StatusIconLocationPreference.None; - public int CompareTo(StatusIconData? other) - { - return Priority.CompareTo(other?.Priority ?? int.MaxValue); - } - /// /// The layer the icon is displayed on. Mod is drawn above Base. Base | Mod /// @@ -52,6 +73,11 @@ public partial class StatusIconData : IComparable /// [DataField] public bool IsShaded = false; + + public int CompareTo(StatusIconData? other) + { + return Priority.CompareTo(other?.Priority ?? int.MaxValue); + } } /// diff --git a/Content.Shared/Zombies/InitialInfectedComponent.cs b/Content.Shared/Zombies/InitialInfectedComponent.cs index 3200dd7f5e..3149de63bd 100644 --- a/Content.Shared/Zombies/InitialInfectedComponent.cs +++ b/Content.Shared/Zombies/InitialInfectedComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.Antag; using Content.Shared.StatusIcon; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -6,11 +5,8 @@ using Robust.Shared.Prototypes; namespace Content.Shared.Zombies; [RegisterComponent, NetworkedComponent] -public sealed partial class InitialInfectedComponent : Component, IAntagStatusIconComponent +public sealed partial class InitialInfectedComponent : Component { - [DataField("initialInfectedStatusIcon")] - public ProtoId StatusIcon { get; set; } = "InitialInfectedFaction"; - [DataField] - public bool IconVisibleToGhost { get; set; } = true; + public ProtoId StatusIcon = "InitialInfectedFaction"; } diff --git a/Content.Shared/Zombies/ShowZombieIconsComponent.cs b/Content.Shared/Zombies/ShowZombieIconsComponent.cs deleted file mode 100644 index a2bc85c074..0000000000 --- a/Content.Shared/Zombies/ShowZombieIconsComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Robust.Shared.GameStates; - -namespace Content.Shared.Zombies; - -/// -/// Makes it so an entity can view ZombieAntagIcons. -/// -[RegisterComponent, NetworkedComponent] -public sealed partial class ShowZombieIconsComponent: Component -{ - -} diff --git a/Content.Shared/Zombies/ZombieComponent.cs b/Content.Shared/Zombies/ZombieComponent.cs index 3673a2c51d..2cd0cdb96d 100644 --- a/Content.Shared/Zombies/ZombieComponent.cs +++ b/Content.Shared/Zombies/ZombieComponent.cs @@ -14,7 +14,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy namespace Content.Shared.Zombies; [RegisterComponent, NetworkedComponent] -public sealed partial class ZombieComponent : Component, IAntagStatusIconComponent +public sealed partial class ZombieComponent : Component { /// /// The baseline infection chance you have if you are completely nude @@ -97,9 +97,6 @@ public sealed partial class ZombieComponent : Component, IAntagStatusIconCompone [DataField("zombieStatusIcon")] public ProtoId StatusIcon { get; set; } = "ZombieFaction"; - [DataField] - public bool IconVisibleToGhost { get; set; } = true; - /// /// Healing each second /// diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index 4a83593bc3..8b0f60ca58 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -84,8 +84,7 @@ - type: Stripping - type: SolutionScanner - type: IgnoreUIRange - - type: ShowRevIcons - - type: ShowZombieIcons + - type: ShowAntagIcons - type: Inventory templateId: aghost - type: InventorySlots diff --git a/Resources/Prototypes/StatusEffects/health.yml b/Resources/Prototypes/StatusIcon/StatusEffects/health.yml similarity index 100% rename from Resources/Prototypes/StatusEffects/health.yml rename to Resources/Prototypes/StatusIcon/StatusEffects/health.yml diff --git a/Resources/Prototypes/StatusEffects/hunger.yml b/Resources/Prototypes/StatusIcon/StatusEffects/hunger.yml similarity index 100% rename from Resources/Prototypes/StatusEffects/hunger.yml rename to Resources/Prototypes/StatusIcon/StatusEffects/hunger.yml diff --git a/Resources/Prototypes/StatusEffects/ssd.yml b/Resources/Prototypes/StatusIcon/StatusEffects/ssd.yml similarity index 100% rename from Resources/Prototypes/StatusEffects/ssd.yml rename to Resources/Prototypes/StatusIcon/StatusEffects/ssd.yml diff --git a/Resources/Prototypes/StatusIcon/antag.yml b/Resources/Prototypes/StatusIcon/antag.yml index 0dbdfce4f9..0da545b8a2 100644 --- a/Resources/Prototypes/StatusIcon/antag.yml +++ b/Resources/Prototypes/StatusIcon/antag.yml @@ -1,6 +1,11 @@ - type: statusIcon id: ZombieFaction priority: 11 + showTo: + components: + - ShowAntagIcons + - Zombie + - InitialInfected icon: sprite: /Textures/Interface/Misc/job_icons.rsi state: Zombie @@ -8,6 +13,10 @@ - type: statusIcon id: InitialInfectedFaction priority: 11 + showTo: + components: + - ShowAntagIcons + - InitialInfected icon: sprite: /Textures/Interface/Misc/job_icons.rsi state: InitialInfected @@ -15,6 +24,10 @@ - type: statusIcon id: RevolutionaryFaction priority: 11 + showTo: + components: + - ShowAntagIcons + - Revolutionary icon: sprite: /Textures/Interface/Misc/job_icons.rsi state: Revolutionary @@ -22,6 +35,10 @@ - type: statusIcon id: HeadRevolutionaryFaction priority: 11 + showTo: + components: + - ShowAntagIcons + - Revolutionary icon: sprite: /Textures/Interface/Misc/job_icons.rsi state: HeadRevolutionary diff --git a/Resources/Prototypes/StatusEffects/job.yml b/Resources/Prototypes/StatusIcon/job.yml similarity index 100% rename from Resources/Prototypes/StatusEffects/job.yml rename to Resources/Prototypes/StatusIcon/job.yml diff --git a/Resources/Prototypes/StatusEffects/security.yml b/Resources/Prototypes/StatusIcon/security.yml similarity index 100% rename from Resources/Prototypes/StatusEffects/security.yml rename to Resources/Prototypes/StatusIcon/security.yml From 1e04b3c9f492e82bf28da9e9e97bcad65bb01c67 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 16:13:28 +0000 Subject: [PATCH 39/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index cab645fa8d..f2d3131827 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -3847,3 +3847,11 @@ id: 6674 time: '2024-06-03T13:04:07.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28072 +- author: AJCM-git + changes: + - message: Ninja stealth mode, stealth boxes and everything with stealth won't show + up in equipment HUDs like the medical or security HUD anymore. + type: Fix + id: 6675 + time: '2024-06-03T16:12:21.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28270 From 619d82ed426c50a72d71ca195d901c11b09adea9 Mon Sep 17 00:00:00 2001 From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:22:26 -0400 Subject: [PATCH 40/63] Small code cleanup to health bar (#28554) --- Content.Client/Commands/ShowHealthBarsCommand.cs | 2 +- Content.Client/Overlays/EntityHealthBarOverlay.cs | 2 +- Content.Shared/Overlays/ShowHealthBarsComponent.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Content.Client/Commands/ShowHealthBarsCommand.cs b/Content.Client/Commands/ShowHealthBarsCommand.cs index ef918313a0..0811f96663 100644 --- a/Content.Client/Commands/ShowHealthBarsCommand.cs +++ b/Content.Client/Commands/ShowHealthBarsCommand.cs @@ -35,7 +35,7 @@ public sealed class ShowHealthBarsCommand : LocalizedCommands var showHealthBarsComponent = new ShowHealthBarsComponent { DamageContainers = args.ToList(), - HealthStatusIcon = "", + HealthStatusIcon = null, NetSyncEnabled = false }; diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index 55978d98f7..4f92843739 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -33,7 +33,7 @@ public sealed class EntityHealthBarOverlay : Overlay public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; public HashSet DamageContainers = new(); - public ProtoId StatusIcon; + public ProtoId? StatusIcon; public EntityHealthBarOverlay(IEntityManager entManager, IPrototypeManager prototype) { diff --git a/Content.Shared/Overlays/ShowHealthBarsComponent.cs b/Content.Shared/Overlays/ShowHealthBarsComponent.cs index 1297d56838..4229e27af6 100644 --- a/Content.Shared/Overlays/ShowHealthBarsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthBarsComponent.cs @@ -19,5 +19,5 @@ public sealed partial class ShowHealthBarsComponent : Component public List DamageContainers = new(); [DataField] - public ProtoId HealthStatusIcon = "HealthIconFine"; + public ProtoId? HealthStatusIcon = "HealthIconFine"; } From b5e8a696225a3c790939b67a832067caa1354c67 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Mon, 3 Jun 2024 12:24:32 -0400 Subject: [PATCH 41/63] Add a test for sliceable cargo bounty exploits (#28357) --- Content.IntegrationTests/Tests/CargoTest.cs | 79 +++++++++++++++++++ .../Cargo/Systems/CargoSystem.Bounty.cs | 17 +++- .../Prototypes/Catalog/Bounties/bounties.yml | 6 ++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/Content.IntegrationTests/Tests/CargoTest.cs b/Content.IntegrationTests/Tests/CargoTest.cs index 09f179cf4f..8e1d536054 100644 --- a/Content.IntegrationTests/Tests/CargoTest.cs +++ b/Content.IntegrationTests/Tests/CargoTest.cs @@ -3,8 +3,13 @@ using System.Linq; using System.Numerics; using Content.Server.Cargo.Components; using Content.Server.Cargo.Systems; +using Content.Server.Nutrition.Components; +using Content.Server.Nutrition.EntitySystems; using Content.Shared.Cargo.Prototypes; +using Content.Shared.IdentityManagement; using Content.Shared.Stacks; +using Content.Shared.Tag; +using Content.Shared.Whitelist; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Prototypes; @@ -149,6 +154,80 @@ public sealed class CargoTest await pair.CleanReturnAsync(); } + /// + /// Tests to see if any items that are valid for cargo bounties can be sliced into items that + /// are also valid for the same bounty entry. + /// + [Test] + public async Task NoSliceableBountyArbitrageTest() + { + await using var pair = await PoolManager.GetServerClient(); + var server = pair.Server; + + var testMap = await pair.CreateTestMap(); + + var entManager = server.ResolveDependency(); + var mapManager = server.ResolveDependency(); + var protoManager = server.ResolveDependency(); + var componentFactory = server.ResolveDependency(); + var whitelist = entManager.System(); + var cargo = entManager.System(); + var sliceableSys = entManager.System(); + + var bounties = protoManager.EnumeratePrototypes().ToList(); + + await server.WaitAssertion(() => + { + var mapId = testMap.MapId; + var grid = mapManager.CreateGridEntity(mapId); + var coord = new EntityCoordinates(grid.Owner, 0, 0); + + var sliceableEntityProtos = protoManager.EnumeratePrototypes() + .Where(p => !p.Abstract) + .Where(p => !pair.IsTestPrototype(p)) + .Where(p => p.TryGetComponent(out _, componentFactory)) + .Select(p => p.ID) + .ToList(); + + foreach (var proto in sliceableEntityProtos) + { + var ent = entManager.SpawnEntity(proto, coord); + var sliceable = entManager.GetComponent(ent); + + // Check each bounty + foreach (var bounty in bounties) + { + // Check each entry in the bounty + foreach (var entry in bounty.Entries) + { + // See if the entity counts as part of this bounty entry + if (!cargo.IsValidBountyEntry(ent, entry)) + continue; + + // Spawn a slice + var slice = entManager.SpawnEntity(sliceable.Slice, coord); + + // See if the slice also counts for this bounty entry + if (!cargo.IsValidBountyEntry(slice, entry)) + { + entManager.DeleteEntity(slice); + continue; + } + + entManager.DeleteEntity(slice); + + // If for some reason it can only make one slice, that's okay, I guess + Assert.That(sliceable.TotalCount, Is.EqualTo(1), $"{proto} counts as part of cargo bounty {bounty.ID} and slices into {sliceable.TotalCount} slices which count for the same bounty!"); + } + } + + entManager.DeleteEntity(ent); + } + mapManager.DeleteMap(mapId); + }); + + await pair.CleanReturnAsync(); + } [TestPrototypes] private const string StackProto = @" diff --git a/Content.Server/Cargo/Systems/CargoSystem.Bounty.cs b/Content.Server/Cargo/Systems/CargoSystem.Bounty.cs index 0fcfd160bb..554b349b9b 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Bounty.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Bounty.cs @@ -300,6 +300,21 @@ public sealed partial class CargoSystem return IsBountyComplete(GetBountyEntities(container), entries, out bountyEntities); } + /// + /// Determines whether the meets the criteria for the bounty . + /// + /// true if is a valid item for the bounty entry, otherwise false + public bool IsValidBountyEntry(EntityUid entity, CargoBountyItemEntry entry) + { + if (!_whitelistSys.IsValid(entry.Whitelist, entity)) + return false; + + if (entry.Blacklist != null && _whitelistSys.IsValid(entry.Blacklist, entity)) + return false; + + return true; + } + public bool IsBountyComplete(HashSet entities, IEnumerable entries, out HashSet bountyEntities) { bountyEntities = new(); @@ -313,7 +328,7 @@ public sealed partial class CargoSystem var temp = new HashSet(); foreach (var entity in entities) { - if (!_whitelistSys.IsValid(entry.Whitelist, entity) || (entry.Blacklist != null && _whitelistSys.IsValid(entry.Blacklist, entity))) + if (!IsValidBountyEntry(entity, entry)) continue; count += _stackQuery.CompOrNull(entity)?.Count ?? 1; diff --git a/Resources/Prototypes/Catalog/Bounties/bounties.yml b/Resources/Prototypes/Catalog/Bounties/bounties.yml index bedfe44287..08bb2a1422 100644 --- a/Resources/Prototypes/Catalog/Bounties/bounties.yml +++ b/Resources/Prototypes/Catalog/Bounties/bounties.yml @@ -42,6 +42,9 @@ whitelist: tags: - Bread + blacklist: + tags: + - Slice - type: cargoBounty id: BountyCarrot @@ -533,6 +536,9 @@ whitelist: tags: - Meat + blacklist: + components: + - SliceableFood - type: cargoBounty id: BountyFruit From ee8224bce22c5d5ca76faaa43b2fc8441f356610 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Mon, 3 Jun 2024 12:59:59 -0400 Subject: [PATCH 42/63] Tip 51 does not exist (#28555) --- Resources/Locale/en-US/tips.ftl | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Locale/en-US/tips.ftl b/Resources/Locale/en-US/tips.ftl index 52912d1ba4..90a0616452 100644 --- a/Resources/Locale/en-US/tips.ftl +++ b/Resources/Locale/en-US/tips.ftl @@ -48,6 +48,7 @@ tips-dataset-47 = As a Salvage Specialist, you can use your proto-kinetic accele tips-dataset-48 = As a Salvage Specialist, never forget to mine ore! Ore can be sold to cargo for a pretty penny, be used for construction, and also be used by Scientists for fancy technology. tips-dataset-49 = As a Salvage Specialist, try asking science for a tethergun. It can be used to grab items off of salvage wrecks extremely efficiently! tips-dataset-50 = As a Salvage Specialist, try asking science for a grappling hook. It can be used to propel yourself onto wrecks, or if stuck in space you don't have to rely on the proto-kinetic accelerator. +tips-dataset-51 = Tip #51 does not exist and has never existed. Ignore any rumors to the contrary. tips-dataset-52 = As a Salvage Specialist, consider cooperating with the Cargo Technicians. They can order you a wide variety of useful items, including ones that may be hard to get otherwise, such laser guns and shuttle building materials. tips-dataset-53 = As a Cargo Technician, consider asking science for a Ripley APLU. When paired with a hydraulic clamp, you can grab valuable maintenance objects like fuel tanks much more easily, and make deliveries in a swift manner. tips-dataset-54 = As a Cargo Technician, try to maintain a surplus of materials. They are extremely useful for Scientists and Station Engineers to have immediate access to. From a4d16017589e82822c9880b146b8d3dab9621093 Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Mon, 3 Jun 2024 21:47:06 +0300 Subject: [PATCH 43/63] Accent trait limit (#28046) --- .../Lobby/UI/HumanoidProfileEditor.xaml.cs | 113 +++++++++++++----- .../UI/Roles/TraitPreferenceSelector.xaml | 2 +- .../UI/Roles/TraitPreferenceSelector.xaml.cs | 9 +- Content.Server/Traits/TraitSystem.cs | 30 ++--- .../Preferences/HumanoidCharacterProfile.cs | 32 ++++- .../Traits/TraitCategoryPrototype.cs | 26 ++++ Content.Shared/Traits/TraitPrototype.cs | 90 +++++++------- .../ui/humanoid-profile-editor.ftl | 11 +- Resources/Locale/en-US/traits/traits.ftl | 18 ++- Resources/Prototypes/Traits/categories.yml | 8 ++ Resources/Prototypes/Traits/disabilities.yml | 58 +++++---- .../Prototypes/Traits/inconveniences.yml | 18 --- Resources/Prototypes/Traits/neutral.yml | 33 ----- Resources/Prototypes/Traits/speech.yml | 88 ++++++++++++++ 14 files changed, 365 insertions(+), 171 deletions(-) create mode 100644 Content.Shared/Traits/TraitCategoryPrototype.cs create mode 100644 Resources/Prototypes/Traits/categories.yml delete mode 100644 Resources/Prototypes/Traits/inconveniences.yml delete mode 100644 Resources/Prototypes/Traits/neutral.yml create mode 100644 Resources/Prototypes/Traits/speech.yml diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs index 53c332c185..ac43fa11a8 100644 --- a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs @@ -7,6 +7,7 @@ using Content.Client.Lobby.UI.Loadouts; using Content.Client.Lobby.UI.Roles; using Content.Client.Message; using Content.Client.Players.PlayTimeTracking; +using Content.Client.Stylesheets; using Content.Client.UserInterface.Systems.Guidebook; using Content.Shared.CCVar; using Content.Shared.Clothing; @@ -466,38 +467,96 @@ namespace Content.Client.Lobby.UI var traits = _prototypeManager.EnumeratePrototypes().OrderBy(t => Loc.GetString(t.Name)).ToList(); TabContainer.SetTabTitle(3, Loc.GetString("humanoid-profile-editor-traits-tab")); - if (traits.Count > 0) - { - foreach (var trait in traits) - { - var selector = new TraitPreferenceSelector(trait); - - if (Profile?.TraitPreferences.Contains(trait.ID) == true) - { - selector.Preference = true; - } - else - { - selector.Preference = false; - } - - selector.PreferenceChanged += preference => - { - Profile = Profile?.WithTraitPreference(trait.ID, preference); - SetDirty(); - }; - - TraitsList.AddChild(selector); - } - } - else + if (traits.Count < 1) { TraitsList.AddChild(new Label { - // TODO: Localise - Text = "No traits available :(", + Text = Loc.GetString("humanoid-profile-editor-no-traits"), FontColorOverride = Color.Gray, }); + return; + } + + //Setup model + Dictionary> model = new(); + List defaultTraits = new(); + model.Add("default", defaultTraits); + + foreach (var trait in traits) + { + if (trait.Category == null) + { + defaultTraits.Add(trait.ID); + continue; + } + + if (!model.ContainsKey(trait.Category)) + { + model.Add(trait.Category, new()); + } + model[trait.Category].Add(trait.ID); + } + + //Create UI view from model + foreach (var (categoryId, traitId) in model) + { + TraitCategoryPrototype? category = null; + if (categoryId != "default") + { + category = _prototypeManager.Index(categoryId); + // Label + TraitsList.AddChild(new Label + { + Text = Loc.GetString(category.Name), + Margin = new Thickness(0, 10, 0, 0), + StyleClasses = { StyleBase.StyleClassLabelHeading }, + }); + } + + List selectors = new(); + var selectionCount = 0; + + foreach (var traitProto in traitId) + { + var trait = _prototypeManager.Index(traitProto); + var selector = new TraitPreferenceSelector(trait); + + selector.Preference = Profile?.TraitPreferences.Contains(trait.ID) == true; + if (selector.Preference) + selectionCount += trait.Cost; + + selector.PreferenceChanged += preference => + { + Profile = Profile?.WithTraitPreference(trait.ID, categoryId, preference); + SetDirty(); + RefreshTraits(); // If too many traits are selected, they will be reset to the real value. + }; + selectors.Add(selector); + } + + // Selection counter + if (category is { MaxTraitPoints: >= 0 }) + { + TraitsList.AddChild(new Label + { + Text = Loc.GetString("humanoid-profile-editor-trait-count-hint", ("current", selectionCount) ,("max", category.MaxTraitPoints)), + FontColorOverride = Color.Gray + }); + } + + foreach (var selector in selectors) + { + if (selector == null) + continue; + + if (category is { MaxTraitPoints: >= 0 } && + selector.Cost + selectionCount > category.MaxTraitPoints) + { + selector.Checkbox.Label.FontColorOverride = Color.Red; + } + + TraitsList.AddChild(selector); + } } } diff --git a/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml b/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml index 18dabe3090..266b4b8eee 100644 --- a/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml +++ b/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml @@ -2,6 +2,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + diff --git a/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml.cs b/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml.cs index 498a5ca4e5..a52a3fa2db 100644 --- a/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml.cs +++ b/Content.Client/Lobby/UI/Roles/TraitPreferenceSelector.xaml.cs @@ -9,6 +9,8 @@ namespace Content.Client.Lobby.UI.Roles; [GenerateTypedNameReferences] public sealed partial class TraitPreferenceSelector : Control { + public int Cost; + public bool Preference { get => Checkbox.Pressed; @@ -20,7 +22,12 @@ public sealed partial class TraitPreferenceSelector : Control public TraitPreferenceSelector(TraitPrototype trait) { RobustXamlLoader.Load(this); - Checkbox.Text = Loc.GetString(trait.Name); + + var text = trait.Cost != 0 ? $"[{trait.Cost}] " : ""; + text += Loc.GetString(trait.Name); + + Cost = trait.Cost; + Checkbox.Text = text; Checkbox.OnToggled += OnCheckBoxToggled; if (trait.Description is { } desc) diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index 22ee0e4861..f7531f7e2c 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -38,27 +38,21 @@ public sealed class TraitSystem : EntitySystem continue; // Add all components required by the prototype - foreach (var entry in traitPrototype.Components.Values) - { - if (HasComp(args.Mob, entry.Component.GetType())) - continue; - - var comp = (Component) _serializationManager.CreateCopy(entry.Component, notNullableOverride: true); - comp.Owner = args.Mob; - EntityManager.AddComponent(args.Mob, comp); - } + EntityManager.AddComponents(args.Mob, traitPrototype.Components, false); // Add item required by the trait - if (traitPrototype.TraitGear != null) - { - if (!TryComp(args.Mob, out HandsComponent? handsComponent)) - continue; + if (traitPrototype.TraitGear == null) + continue; - var coords = Transform(args.Mob).Coordinates; - var inhandEntity = EntityManager.SpawnEntity(traitPrototype.TraitGear, coords); - _sharedHandsSystem.TryPickup(args.Mob, inhandEntity, checkActionBlocker: false, - handsComp: handsComponent); - } + if (!TryComp(args.Mob, out HandsComponent? handsComponent)) + continue; + + var coords = Transform(args.Mob).Coordinates; + var inhandEntity = EntityManager.SpawnEntity(traitPrototype.TraitGear, coords); + _sharedHandsSystem.TryPickup(args.Mob, + inhandEntity, + checkActionBlocker: false, + handsComp: handsComponent); } } } diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs index f47a3ac3db..bd55bbb40a 100644 --- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs +++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs @@ -346,13 +346,43 @@ namespace Content.Shared.Preferences }; } - public HumanoidCharacterProfile WithTraitPreference(string traitId, bool pref) + public HumanoidCharacterProfile WithTraitPreference(string traitId, string? categoryId, bool pref) { + var prototypeManager = IoCManager.Resolve(); + var traitProto = prototypeManager.Index(traitId); + + TraitCategoryPrototype? categoryProto = null; + if (categoryId != null && categoryId != "default") + categoryProto = prototypeManager.Index(categoryId); + var list = new HashSet(_traitPreferences); if (pref) { list.Add(traitId); + + if (categoryProto == null || categoryProto.MaxTraitPoints < 0) + { + return new(this) + { + _traitPreferences = list, + }; + } + + var count = 0; + foreach (var trait in list) + { + var traitProtoTemp = prototypeManager.Index(trait); + count += traitProtoTemp.Cost; + } + + if (count > categoryProto.MaxTraitPoints && traitProto.Cost != 0) + { + return new(this) + { + _traitPreferences = _traitPreferences, + }; + } } else { diff --git a/Content.Shared/Traits/TraitCategoryPrototype.cs b/Content.Shared/Traits/TraitCategoryPrototype.cs new file mode 100644 index 0000000000..1da624173a --- /dev/null +++ b/Content.Shared/Traits/TraitCategoryPrototype.cs @@ -0,0 +1,26 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Traits; + +/// +/// Traits category with general settings. Allows you to limit the number of taken traits in one category +/// +[Prototype] +public sealed partial class TraitCategoryPrototype : IPrototype +{ + [ViewVariables] + [IdDataField] + public string ID { get; private set; } = default!; + + /// + /// Name of the trait category displayed in the UI + /// + [DataField] + public LocId Name { get; private set; } = string.Empty; + + /// + /// The maximum number of traits that can be taken in this category. If -1, you can take as many traits as you like. + /// + [DataField] + public int MaxTraitPoints = -1; +} diff --git a/Content.Shared/Traits/TraitPrototype.cs b/Content.Shared/Traits/TraitPrototype.cs index 34feb8da22..c79d3cbf30 100644 --- a/Content.Shared/Traits/TraitPrototype.cs +++ b/Content.Shared/Traits/TraitPrototype.cs @@ -1,55 +1,63 @@ using Content.Shared.Whitelist; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -// don't worry about it +namespace Content.Shared.Traits; -namespace Content.Shared.Traits +/// +/// Describes a trait. +/// +[Prototype] +public sealed partial class TraitPrototype : IPrototype { + [ViewVariables] + [IdDataField] + public string ID { get; private set; } = default!; + /// - /// Describes a trait. + /// The name of this trait. /// - [Prototype("trait")] - public sealed partial class TraitPrototype : IPrototype - { - [ViewVariables] - [IdDataField] - public string ID { get; private set; } = default!; + [DataField] + public LocId Name { get; private set; } = string.Empty; - /// - /// The name of this trait. - /// - [DataField("name")] - public string Name { get; private set; } = ""; + /// + /// The description of this trait. + /// + [DataField] + public LocId? Description { get; private set; } - /// - /// The description of this trait. - /// - [DataField("description")] - public string? Description { get; private set; } + /// + /// Don't apply this trait to entities this whitelist IS NOT valid for. + /// + [DataField] + public EntityWhitelist? Whitelist; - /// - /// Don't apply this trait to entities this whitelist IS NOT valid for. - /// - [DataField("whitelist")] - public EntityWhitelist? Whitelist; + /// + /// Don't apply this trait to entities this whitelist IS valid for. (hence, a blacklist) + /// + [DataField] + public EntityWhitelist? Blacklist; - /// - /// Don't apply this trait to entities this whitelist IS valid for. (hence, a blacklist) - /// - [DataField("blacklist")] - public EntityWhitelist? Blacklist; + /// + /// The components that get added to the player, when they pick this trait. + /// + [DataField] + public ComponentRegistry Components { get; private set; } = default!; - /// - /// The components that get added to the player, when they pick this trait. - /// - [DataField("components")] - public ComponentRegistry Components { get; private set; } = default!; + /// + /// Gear that is given to the player, when they pick this trait. + /// + [DataField] + public EntProtoId? TraitGear; - /// - /// Gear that is given to the player, when they pick this trait. - /// - [DataField("traitGear", required: false, customTypeSerializer:typeof(PrototypeIdSerializer))] - public string? TraitGear; - } + /// + /// Trait Price. If negative number, points will be added. + /// + [DataField] + public int Cost = 0; + + /// + /// Adds a trait to a category, allowing you to limit the selection of some traits to the settings of that category. + /// + [DataField] + public ProtoId? Category; } diff --git a/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl b/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl index c7a24d5405..bfdbeb2f14 100644 --- a/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl +++ b/Resources/Locale/en-US/preferences/ui/humanoid-profile-editor.ftl @@ -42,7 +42,7 @@ humanoid-profile-editor-department-jobs-label = {$departmentName} jobs humanoid-profile-editor-antags-tab = Antags humanoid-profile-editor-antag-preference-yes-button = Yes humanoid-profile-editor-antag-preference-no-button = No -humanoid-profile-editor-traits-tab = Traits + humanoid-profile-editor-job-priority-high-button = High humanoid-profile-editor-job-priority-medium-button = Medium humanoid-profile-editor-job-priority-low-button = Low @@ -50,3 +50,12 @@ humanoid-profile-editor-job-priority-never-button = Never humanoid-profile-editor-naming-rules-warning = Warning: Offensive or LRP IC names and descriptions will lead to admin intervention on this server. Read our \[Rules\] for more. humanoid-profile-editor-markings-tab = Markings humanoid-profile-editor-flavortext-tab = Description + +# Traits +humanoid-profile-editor-traits-tab = Traits +humanoid-profile-editor-no-traits = No traits available + +humanoid-profile-editor-trait-count-hint = Points available: [{$current}/{$max}] + +trait-category-disabilities = Disabilities +trait-category-speech = Speech traits \ No newline at end of file diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index cbf65308f3..e3aed1c8b2 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -12,7 +12,7 @@ trait-pacifist-desc = You cannot attack or hurt any living beings. permanent-blindness-trait-examined = [color=lightblue]{CAPITALIZE(POSS-ADJ($target))} eyes are glassy and unfocused. It doesn't seem like {SUBJECT($target)} can see you well, if at all.[/color] -trait-lightweight-name = Lightweight Drunk +trait-lightweight-name = Lightweight drunk trait-lightweight-desc = Alcohol has a stronger effect on you trait-muted-name = Muted @@ -24,23 +24,29 @@ trait-paracusia-desc = You hear sounds that aren't really there trait-unrevivable-name = Unrevivable trait-unrevivable-desc = You are unable to be revived by defibrillators. -trait-pirate-accent-name = Pirate Accent +trait-pirate-accent-name = Pirate accent trait-pirate-accent-desc = You can't stop speaking like a pirate! trait-accentless-name = Accentless trait-accentless-desc = You don't have the accent that your species would usually have -trait-frontal-lisp-name = Frontal Lisp +trait-frontal-lisp-name = Frontal lisp trait-frontal-lisp-desc = You thpeak with a lithp -trait-socialanxiety-name = Social Anxiety +trait-socialanxiety-name = Social anxiety trait-socialanxiety-desc = You are anxious when you speak and stutter. -trait-southern-name = Southern Drawl +trait-southern-name = Southern drawl trait-southern-desc = You have a different way of speakin'. trait-snoring-name = Snoring trait-snoring-desc = You will snore while sleeping. trait-liar-name = Pathological liar -trait-liar-desc = You can hardly bring yourself to tell the truth. Sometimes you lie anyway. \ No newline at end of file +trait-liar-desc = You can hardly bring yourself to tell the truth. Sometimes you lie anyway. + +trait-cowboy-name = Cowboy accent +trait-cowboy-desc = You speak with a distinct cowboy accent! + +trait-italian-name = Italian accent +trait-italian-desc = Mamma mia! You seem to have lived in space italy! \ No newline at end of file diff --git a/Resources/Prototypes/Traits/categories.yml b/Resources/Prototypes/Traits/categories.yml new file mode 100644 index 0000000000..a3621648a4 --- /dev/null +++ b/Resources/Prototypes/Traits/categories.yml @@ -0,0 +1,8 @@ +- type: traitCategory + id: Disabilities + name: trait-category-disabilities + +- type: traitCategory + id: SpeechTraits + name: trait-category-speech + maxTraitPoints: 2 diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index be1e981549..6e0026e44e 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -3,6 +3,7 @@ name: trait-blindness-name description: trait-blindness-desc traitGear: WhiteCane + category: Disabilities whitelist: components: - Blindable @@ -14,6 +15,7 @@ name: trait-poor-vision-name description: trait-poor-vision-desc traitGear: ClothingEyesGlasses + category: Disabilities whitelist: components: - Blindable @@ -25,6 +27,7 @@ id: Narcolepsy name: trait-narcolepsy-name description: trait-narcolepsy-desc + category: Disabilities components: - type: Narcolepsy timeBetweenIncidents: 300, 600 @@ -34,13 +37,43 @@ id: Pacifist name: trait-pacifist-name description: trait-pacifist-desc + category: Disabilities components: - type: Pacified +- type: trait + id: Unrevivable + name: trait-unrevivable-name + description: trait-unrevivable-desc + category: Disabilities + components: + - type: Unrevivable + +- type: trait + id: Muted + name: trait-muted-name + description: trait-muted-desc + category: Disabilities + blacklist: + components: + - BorgChassis + components: + - type: Muted + +- type: trait + id: LightweightDrunk + name: trait-lightweight-name + description: trait-lightweight-desc + category: Disabilities + components: + - type: LightweightDrunk + boozeStrengthMultiplier: 2 + - type: trait id: Paracusia name: trait-paracusia-name description: trait-paracusia-desc + category: Disabilities components: - type: Paracusia minTimeBetweenIncidents: 0.1 @@ -49,33 +82,10 @@ sounds: collection: Paracusia -- type: trait - id: Unrevivable - name: trait-unrevivable-name - description: trait-unrevivable-desc - components: - - type: Unrevivable - -- type: trait - id: Muted - name: trait-muted-name - description: trait-muted-desc - blacklist: - components: - - BorgChassis - components: - - type: Muted - -- type: trait - id: FrontalLisp - name: trait-frontal-lisp-name - description: trait-frontal-lisp-desc - components: - - type: FrontalLisp - - type: trait id: Snoring name: trait-snoring-name description: trait-snoring-desc + category: Disabilities components: - type: Snoring diff --git a/Resources/Prototypes/Traits/inconveniences.yml b/Resources/Prototypes/Traits/inconveniences.yml deleted file mode 100644 index 657781d1b5..0000000000 --- a/Resources/Prototypes/Traits/inconveniences.yml +++ /dev/null @@ -1,18 +0,0 @@ -- type: trait - id: LightweightDrunk - name: trait-lightweight-name - description: trait-lightweight-desc - components: - - type: LightweightDrunk - boozeStrengthMultiplier: 2 - -- type: trait - id: SocialAnxiety - name: trait-socialanxiety-name - description: trait-socialanxiety-desc - components: - - type: StutteringAccent - matchRandomProb: 0.1 - fourRandomProb: 0 - threeRandomProb: 0 - cutRandomProb: 0 diff --git a/Resources/Prototypes/Traits/neutral.yml b/Resources/Prototypes/Traits/neutral.yml deleted file mode 100644 index 78d2bba049..0000000000 --- a/Resources/Prototypes/Traits/neutral.yml +++ /dev/null @@ -1,33 +0,0 @@ -- type: trait - id: PirateAccent - name: trait-pirate-accent-name - description: trait-pirate-accent-desc - components: - - type: PirateAccent - -- type: trait - id: Accentless - name: trait-accentless-name - description: trait-accentless-desc - components: - - type: Accentless - removes: - - type: LizardAccent - - type: MothAccent - - type: ReplacementAccent - accent: dwarf - -- type: trait - id: Southern - name: trait-southern-name - description: trait-southern-desc - components: - - type: SouthernAccent - -- type: trait - id: Liar - name: trait-liar-name - description: trait-liar-desc - components: - - type: ReplacementAccent - accent: liar diff --git a/Resources/Prototypes/Traits/speech.yml b/Resources/Prototypes/Traits/speech.yml new file mode 100644 index 0000000000..9448e160b5 --- /dev/null +++ b/Resources/Prototypes/Traits/speech.yml @@ -0,0 +1,88 @@ +# Free + +- type: trait + id: Accentless + name: trait-accentless-name + description: trait-accentless-desc + category: SpeechTraits + components: + - type: Accentless + removes: + - type: LizardAccent + - type: MothAccent + - type: ReplacementAccent + accent: dwarf + +# 1 Cost + +- type: trait + id: SouthernAccent + name: trait-southern-name + description: trait-southern-desc + category: SpeechTraits + cost: 1 + components: + - type: SouthernAccent + +- type: trait + id: PirateAccent + name: trait-pirate-accent-name + description: trait-pirate-accent-desc + category: SpeechTraits + cost: 1 + components: + - type: PirateAccent + +- type: trait + id: CowboyAccent + name: trait-cowboy-name + description: trait-cowboy-desc + category: SpeechTraits + cost: 1 + components: + - type: ReplacementAccent + accent: cowboy + +- type: trait + id: ItalianAccent + name: trait-italian-name + description: trait-italian-desc + category: SpeechTraits + cost: 1 + components: + - type: ReplacementAccent + accent: italian + +- type: trait + id: Liar + name: trait-liar-name + description: trait-liar-desc + category: SpeechTraits + cost: 1 + components: + - type: ReplacementAccent + accent: liar + +# 2 Cost + +- type: trait + id: SocialAnxiety + name: trait-socialanxiety-name + description: trait-socialanxiety-desc + category: SpeechTraits + cost: 2 + components: + - type: StutteringAccent + matchRandomProb: 0.1 + fourRandomProb: 0 + threeRandomProb: 0 + cutRandomProb: 0 + +- type: trait + id: FrontalLisp + name: trait-frontal-lisp-name + description: trait-frontal-lisp-desc + category: SpeechTraits + cost: 2 + components: + - type: FrontalLisp From 3e2eb6cc7a6f82b5aedc853ad74ceeb1e8ce8838 Mon Sep 17 00:00:00 2001 From: RenQ <164364533+ImRenQ@users.noreply.github.com> Date: Mon, 3 Jun 2024 21:48:01 +0300 Subject: [PATCH 44/63] "Death gasp" for a moth (#28409) --- Resources/Audio/Effects/Gasp/attributions.yml | 6 ++++++ Resources/Audio/Effects/Gasp/moth_DeathGasp.ogg | Bin 0 -> 18078 bytes .../Prototypes/SoundCollections/deathgasp.yml | 5 +++++ .../Prototypes/Voice/speech_emote_sounds.yml | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 Resources/Audio/Effects/Gasp/moth_DeathGasp.ogg diff --git a/Resources/Audio/Effects/Gasp/attributions.yml b/Resources/Audio/Effects/Gasp/attributions.yml index fe8f817c5a..8d84b770f3 100644 --- a/Resources/Audio/Effects/Gasp/attributions.yml +++ b/Resources/Audio/Effects/Gasp/attributions.yml @@ -24,3 +24,9 @@ license: "CC-BY-SA-3.0" copyright: "Taken from tgstation at https://github.com/tgstation/tgstation/commit/f7a49c4068f1277e6857baf0892d355f1c055974" source: "https://github.com/tgstation/tgstation/tree/f7a49c4068f1277e6857baf0892d355f1c055974/sound/voice/human" + +- files: + - moth_DeathGasp.ogg + license: "CC-BY-SA-3.0" + copyright: "Taken from tgstation at https://github.com/tgstation/tgstation/commit/948ad3dd5b22803a01cd74c27f37e509dc61395b" + source: "https://github.com/tgstation/tgstation/blob/948ad3dd5b22803a01cd74c27f37e509dc61395b/sound/voice/moth/moth_death.ogg" diff --git a/Resources/Audio/Effects/Gasp/moth_DeathGasp.ogg b/Resources/Audio/Effects/Gasp/moth_DeathGasp.ogg new file mode 100644 index 0000000000000000000000000000000000000000..df23cfa472ac1043b1fc1eacde71a493402f9133 GIT binary patch literal 18078 zcmagG1z1(V*Dt&e-5^~DX*j^4Bt=qDQo2F9yH#33>F$=2?oR1OS_J7vKtQ^_jsD;J zzTf@6=idEn=9xWfX04gEerxSDbG9m&o2vi_z<(}gw11VSG1~DEDu|oClaZzKLlfjh z$$z@IL;hA8APNs7|JU^}@_~ZcTWWy!;{N}24Iutw!~@bbEgdY_6`aheZ7hw{|FWl+ zrsn44=H%q(){MeiVN-`H4fwI{jY+W$Aky~kN{t1^oX2I zX{%8|b5f=Vrz}Cs*8&C9s3A(rg6N&6jK+5PHTl+dqc8?EY%OE}RFIeyO(3E2Lt*rZ zCWsU)K2kdM(-fpRVX%D3`hdaRPwg+qy^|aJ`svP>oQS8p%r)O6FyS>5GICtg>c(ZQ zD0-gGqk>y$|0&S_u7et!iv$Xp37!Pn1N%>~{3Iuk)xTv?1HRxgfmhLl(v^fmm6Rjn z^a{spN(8*)Pb5`T<<-E;RZqjsbk@yv*3C;RDNv`uORFJJ=X;>ud7vR_(0}d=uch;c z`|r}JAwU+LV8R;gGcEb&Rl(1Q0YN1QfXRbOsL^9+VKF(<`DRvSmZ^0X#dWqrRcu35 zSbw{K#zlIV4UlD-lK=m?&9o9s|L?b$ML!E52I{iUk+RQ`UQ(I9&xsB7uZH^p(57O_ zY&}jqubg@MoS%XBE0-4oadIPn;M2#zooVNI3v%Lm58l#H-;fJnJk!3##Hl zBmd{i?=N1!h0vs%C0O~QJ&7{>s}^5yVWin;&$0eV0y})lUZ+m^mU1#8h?BCBRY;gR z`88NIm8r2XDfO=fZAQt~KwH8FlY6p~zoj^jN@Jzu{j0shPem;)oB-R%w$gBV$qd1M zmJ=zcg>#zVSgmgOX$}fkok)w9&7EE8vLWAF0-j=z3u7(j@I* z1pT4ye}|74Xg9;}q`m1MsJ$Xkj0kD+X=15dB5`7~xcXtaRN)aXWeWWjmC2a$Tt56= zIW+(T;QdAMe-(eB{13&sF(E92%+DG5UV)P7<4{@aawRnog>j zPP>`T)tTzldui4E$6@}t&C;yv|L~j#7oio5Sd)rD`ftz4Vvbl9h@g{>q1TFGe3xJz zoKl#au~YaNlM&WT#p)Qgn|I+{f&=G|t`!|j#DZ{6gd8d`(YO2EjXO97? z(>(H%JfLFZ0e}nu=s+U};DtCvN!ST%qH%4~BWDYuWOtJW6yQC<62zu;i4tcLZio@= z!a7-2W+r+e=O50%A3=@XnXfCoA%F&kJtRO00DQUnxw=W6Mx_U`UW{^~r^odRGUdfi zNWq)%WB`S`|bX*mV4U(O zY%@xEkZXfdSw^rRO=VON4H_`Wg_7=%2g{>W8HM#x1`LaDr1^gnX9fW34hZ-s!OUYK z3E(jS%MSEou{^Sb46+20V}z!&1oE@-JR>~3N~&r@1ZvZ&YV*YMYIO|q1oHBKRMiM1 z)riz46XexuZO3>_=Ty~x601$una&e?Yb3ZXJ(1S}A7?uiFT{*0|&(tlXV6aHnz zr#4&1tK_1lq-Lt6s;1>;s&%fWG2BwyjDmbIL}VIf>gs9Q^R`KC1%SMORLXcic*-1iVBPBY>UcDbv|zweJ&cTGA}AC z8LTQVF0b?{;l@3-_q?Q%$)g5AXvF$ZE6qS_~SN(dR zHkI!6I_@=bdgjB1@{4zy3Y(hj_L>}r>uf1=igw#rhB_+-s}A>?IBHyJl+;{*#_6qT zfa|c;chAr{53I5kYA?MW1Q|?R2#(oPHiE;d?I^&u-V;_)LxG4q^AvEVMWv}l#d}qD ztX(C05=v@bdhw=9{CZj>c1!#bIhT1?uTnoMSl+B!!dh>iBA-$>;)62O3 z9DU4szSr^k>DrlVPB|8OUnGbP$OASA2F0>zSP^^$AOH%@7NH6rOAoaRp7Jhrt|}J_ zjq_`n9?CdH87rE&DVAPp)d=bSv{-x@3s~HQGHQ07qKtKR+>EkyW&V`WK6Ng!j3qp7 zLffjacS<|#kue_kR<6mYGU04gU z%F88|mEo!*)Uo55p#(?d;_FDmdI?o*;k_wzz0@G9fd}D#Wo#tHfvl4KV`OAX<71SE z(_$Z3`A5h|!|GyW>84hIRw zwyo1C9*6(6aw98v?~GCDgK(D0_!v<5<`3;K!MF({kX4Lw7&t=5rZGRk3M8Z`ht_WX zaJJz+o6;_MkRc1cA)F%{Pu0PwA=JN~*YihOVn1OrDWVQ~dfyQp%rJPMGLVJh?kHCpNlLLskbSlg#trupMYpb>%70N+)^ zf?$Cs0TRG`FWVn1^5P~Q2+A@$)LCVv;V(?Kv8(Ckf1P z@<|_35AY@Xkbi`M1n{vJBnWO%J``!r5&xZ-{C5rg|7Q_}V4n3z9ei8&l2V}k%gSHk z|9v#J`A?Fb^zZS1aPS~(S-8Sv34j5kOb?9%hysDvwbLK*Z=QsWZPfwZl`sawNg zwKGOxwV?jN2r*+6$~&Wt2`t+=0KQTcjzRIc)t%$Ze{D?zCfgE!wf(R$PzG(0^?(+d z7cwBK9xy@^0Gi=nTR_zRYQuZF^$%JgptkN3oW#4unh(ULB{;I#sJpP|0QsL z!5DxKrgCv0=YMT+_@Iox>0O-i10q4yJP`gu^=}QG=0RP5JJb9d`;ZHQ5Jh~5!gSm8 zIfJw|JS&}uiWdDcfG-vRIDWUNvT2i9{oOm=({KO!Hr2U|v03;ZYRnhT{ zOBV@g9iJNm3!^WGDYh7L@jk!6CbsdAami!xH#z=tqJXOyC3w&@Gw;e5(-_YfvijRSE1?B3J0TQ zmpgmbw{zu@xNjCH%4Q9VoH9O|4#=jbsOZFsOH4c4U(Ok4DhCSo1hrwFFUab*Z#<6Y z;cDfOKmBfDy;gM}Px2#WPTAI>zV2Gza5v=VyMtTy+z96!_wI%$WiRETLuvE;sEPZu zmqmQky+R7&`N2|&da9*rh~D$STh`3;+HzDMsWds8ClG`4wp}&~PN79!)rvm|gFa#d zhZAkLHyr~WR<({P4Y$X%XTB(#0t4NLJgfE4%Fru-;QUNmJ!wDfx_!@Nni11 zpzs<4t3v`;Z?g(Ik+r;2lO?kcQ=Yr$PDJySV`Zy@V`W1FpNIskGB9XJ(c$`wV32Y? zuf7fF_JOm)l=uO4M)OA`1VF?m6jtnn>l17dH`U5IME-jyUcq$8TaT`H_oQsjl?+KT zqa#2!N|p)dCqjx>DhIf5kD%{2GG1;6^9Q<>b~ia^Vcc&m$UJTj%)&EP^URz{=nu!Q zbn1(33m z+XDD`u=RFp_v4^h-QZZa!~s;(F`|TzwR`WAw-D{M(nlUDiuJ9~VOca+-%zcz={oP5 zt*X?s;XTVgH0tWlvfiqP@pJrU5co5-`4kXQAEsVGD7uHN*69atVQt;wIFHVeTRgdV zwWPWT#3>L#qCbyvjLAcBSas8HLW)feLD}I zpA#znm|)Cg+`21yaY4cnplZtcB2=*Fv*lc<3?G9LOkwOp>L?bK^w`;A1YJ1LADZIP z*K!@3S!0>8X*r{UqL^xg#;6e75+F92Jjq(zQdr!sEFHt{O0SW)B_U>xa6@B- zf*!g>cF4ixiCS{%MHBFiyaJL;+9I&l7fQnXbNgU{%I%j0@J4+&rs)m84?>LI8=a$( zd0%`s+X0`4qlfRE(bcRTr@Dgf%x_<1Nrl*Q-YIU z25nv*m7@Hk8bj}+6)u0dEmr1~ut`@c8;!fD&Ijn_#X0=Bx)$E(EiYUDz=Y*yo9fhV z(7YrPc>TWi${U3!Zxxo&xRs$p6>mw;GKh-cZSB$XCK}>jy|s2oS|V+Y^BTeU^!aw{ zp70agaITC>Rxg*d*X`HN@lPS8qUMI9u;5Q%AQ=wc-k-$)qWZrQ+{Ag*t&Y?|fW?&U>jf%5dbpq%!v5rGXlzg8pq=BZ5l$C@!pFi-eZL{<0YO~%HX;lcpY~pL5DfgR zt)=OFkFev;E*s!k-~3gF%5ji28W+GW>H4@!Qq6U{%qNc6vD?9dMYoxy_X3y6e@05! zr4*ogg~e5kxP}^2;L30-aH|)Tx-?H|!x=OQYeaBJ3PS6gplM6;Y4aN9eaF~XkC>>O zAJKmK?k?3VNhtG-GC2}%nMk`o3$cA0c_^5dp>uHl=#go(pJVzvcY2z&X00|SW{5plBy@W&okWQ?7 zC>xt>Fr~?_ezOTXMpQdxR6+)*m_VZ;Td|`Z)s^;7{`i?Qrtj*exMK1rUxr&p0*jW? zxFTrs&tk?M>%ggBs{7%+uuDq1x3qh{;9HTc_d?zU&N@Fm&IoOAOgr~g^kOxW*EBVt zzngw%@zv+Rj4l-qsm~&qzns}ShZdum$~0GdO489B`Y*i#&guNWWWHE{(p@h5u_t!? zT-W1*$|b30V+`d9SfB9QIpU-n?5xf$XsPT4%g2gk`)Udoij^KbM<1E6CQ;l8S)TyJ zQr(`_6Y!z^2B>SFj86#ZTDp9j``~n#qTP?zp>-mu2M4J5haonojE~V)tZVV97)2AA z3~Q&W6}|<<5{W6;;9)-s$U_vuIoa&kaTV4@eDWE-SsNyP*2hNjr?jh4$FiZ%3`D|BH;-g!sNN>Si#x)aYuYPXQtd1R3>ujW!}7r2y5K z&mz%!kB}&wvx@%kp_WRH!o}X`@e|gh9rxSzva}@#G$+UF*5Mfm#qH`xRPeg8jGl9k zj!l!n_ggJQNsqkRE&Txs)XNk1EJRyUPiB`TRo`IV%g+_O(twHRZ9eXvI+hXab4&Nr zuHETldxS+ZO5g7|F^_UDjP-(X%S9e%o7DDgXk8*2H@plc>X69~5pyEW7Gd(xxSDQY zRCNjwA?s6_Bqv#YH$R!CIi-%D&l{c0FVqZYwEPlL_s)tUnWu6NndM7i_DD+V8VU|I zNkPBc^lQ8Uy3Dm#*T&AoVja*Xb~*~?0X^|oc)u>bz|+Pi%zvzudb<^D#n##6E~iu8 zr0=3hZR&XJqL%ynZ=gr8>L~Q?Wz(Pngo+Wzr#I7*jF0H>&uHS=zBP&adNSo(&Eo>x z&##7zHj4TMq(2@;HXqFqZ*#Ara|pji0q#Cxan>TPSXu1s4akU?&%Y;;UMjy4{*oa| z^P14`8LAiq#N<))$mOBUvHXaL&!)d+q-}G?)8^7%4yWqpW_j=H zo~Wg%G)`ARj3j^d1_c3*h0umeDQ;NR-NKVXHQVB9Yn88W{S?n67cXk>xy#iDX)tK` ziw^gNEma-#HmD+Y)GX4qd3!&0iZA$epq13`C~efEXYt(WqPPHWWBdv9nH>0UF=PB8phtb za9yvCGM%?bij?2>S0V3E##R+JoGp^3kP?8eNgVkPov%zJvEKS=dF^}8OWOP_i5S~3 zLcmj@N8~{o_^8IsE%t4--t&-#H7=`Iz07i`o8C(Tq7A{AnN-i9e8wy^`&o!YgY^LD zh^6&}dR~n8^owrt31yYs7x6aavK+vd0B`qU$L}~VJgI}qr$d%^$MDM(T6q*#ZeElF zGThjXnony;3s4y+m8eweUbi2&w)3BuoMg8Q^~xvBw#bAL@b-qQSd9pZm0JH{FkHS3 zJxZ}Tt8Z4fB*&b*wku$pwgN7?gL8eH##3Fprn6^9{mlE7%yFgmq^qO$Kv zJEPvj&ue1~7oP+_+l{zEW8@jl%s8ceJ33S&H{0CN14p*gL4K0Kiznv-GykqJuQE5a zbQyW9!o@^{uKi}mS%Z5ZU!4{PT-o&a9+H;~G?{23#=gwB%gYQ%;h%_2C!HPz7R?{R z4IUlyifudo(&F;1$W2-)Nml3Gls=@ygq#))B}yc~-}ykxGMVy|4*M|q)-N4lZ`1qF z_a%SGn@k%p3X5-Re|DSME6WcVlkf)-=xO@G9+&% zaqj%4cQ>>C(X-vBZrLVtdp_ecHmZGWJ-0Krlt( zrHy?s9d5ISd=bpUn!R%7If2z&Pvcr(;e|(`B>_A?dF45Re|Tr;_C3_<5(DvK((lSPQmn^2>wJ|Xo#l$49N%ORWW>v-^?C{Cs(5Qrt3dfxJt11Qfr{!N;xr;!C`!LOT`3?l$ z29N*qwr;bUFpo{|Dbtq#Mk)%<@Tu zpQokiYL5F5%I~7TaLQ+Wt9zgQevb*8L3lxnA}Ra*AG>t}ob1|n!`mp-)3Y8YwC`!W zL!coc)qE^Z=U0o^EM|h&OL(aL_Q|nbQ3_Q}cEZ68VY)+YS(&d%%g zZu?aM)vU$#f%G6f(Dtf^%MB9$7;Q(I;o0c7pIyE4=UN6>{3@#$Ss&0O*peN7k?nB! z$fKd=qeh<_+R1sxH{K+js$`HSgyfLv$=gR3f6ehK;%XQ8`ed2`Rd$H5Cx_S)Ro+SK z-9gY=y?}HXp9LGLu&iy7`48!?c%?etiIqt6>6HNVH{;PEs<$~AAq~yj&MNldgXV5F zYHEC*PBRp~M^bQ4mvwLVI+`hF<+pAMCdh!78~E?~@!fIRIXYIZhpS zfno;vc1~OFLGUE3{_FSC_XYMt>}wz7FZF-CKmjtCYGAGaFG0X@t!ih^%hLm9r-3mX z##VtV3V`6HGm>}!-JA4kQ*)I&_^cC2TVy?h{GH+1O6t=|%Yp76i3|rrjLwQeHO3p2 z-QDoo+Hm&o6G2oO(5#oAJI4o`GZPv=PWh3VELa%!P3j>naCZZi{@rFhCMT&1BqMg3Gv2dk49}B zAR7J|Yv+OzPZ5S-GeCT{>~CJncbOtZXrL1^=zlhg+`*hGy|R@`m7LbvW1EQp{O4Ew zg#SLPKm@CUG~*iFQ$L1=E4vD+8cT~ybITan80guUm^t9g^lY4P1|~KRI1`MUi=GY6 z1!rVoXJg=ibBnyfimpINQ4kM}m3gb;e@>xf6#Ub_ErUOX6(EU^V37Stg$hmoL0YFL zpf4<77j+(WyRz=_xF$D4qbf+Q2Y$GlaVj$sDPzN2R=L3N*z zVK+r3uChNJkx(cKaf&7}lj=ybisRKv2`j(RmFvaj5n%vydM%I2FKR5ikASw9SdcmdB2jc$ODXG7cF=*)`b3_47WS+v)pPMFd?}?gEvka+ zwvPf^ms8ejfhr+X;e|fVg{FEg88+W~n#U&#V2Gt-@mNm^arVhF>sN1+Ch?yBuc7M=3 z$uq7!Ptk#eg-nxxD=!z?(D(Cn-RZUi5t5;f*J;?I_IEtF?^rE&DCSZ=tfdTtT>PL-N$;B288=rzxxz-P+8y990=^d5-h_{Gb)NK zb8)TqE2?T^U&@~-7`wLqI5ZgP?*9m^mVdWJ326E*gU$@psVm`(avE$6UZ;gW@m-X0 zJ(ZgUe4Cm&k$^4jNpstm%Wxkoz}rnVsRl9jK0Qd)+|pLGWwOIvsGqbgHLKH1CPF4Z zKqbbgiucfYST>2I-t)b~e6?$X^RFL$N3nKRj-rjj6qN}2ucqCS;E@h1vg*7W3Wxe| zlc!Jl6KpPRLtPtUipN9x0+WBPxIMRlOU|c4dWS;bowa4}2FjTOW$!d6(Zr>=lT`=D z2jFI7lqd@eKNy2{XP6WRH7lG^dov1dhlK#H>$nFTf&=WIhW-{pQR@5Y`uy53j^T53g zGyh!r$|UlA%7SIGWCp(PQBR}CbXl_nP+`uiL$192%E2sJKnR?0$<|dHmE~ubR2fCO zRYZ1vVMRkxxjJnNY=F?bhSEG%)SdmFeA9z^tz+@yP`!=+X-xSCnDFXPrFi8}^^Nki z%Aa1;CijVz*XkN_PgPDweHhz}{Mzg5QaYhqr-Z;3-t&;c8_^RXZI_nDBmH+to7T6F=3`zpovrwsse zz(g^LG~hc?tO2&aKi!@FSCIyQHdDgGa`!t@=Eu=kyN@)Pca?8+x-lb9)A;}y>=^2e`PAW zG;UiS8#?Cfr^N$!w5?La452ZS5@@5kAMhC04PvC^8>C{G4SW+9lLe1He1plDuBGDERvFCxRHa6uR|=|Bj;qHd}+dr-cX)|BoqWi|2c2;d%}bN|FW# zQg~UzF)udzmb$N3sG6c$jSE$ZM$%E-b zaPhNeld}D+txC}X9ZX}G*}AWta4=K+JowJl;j(-CL`oXcD-dR$>d6x70)HKKsen!J zSK18IxUq7NJLY|rOROnQQZL`R+zw45Vn4h>0zg2)&_eVQ!mlh{NEv0L@f!=P#b+7~ zb%%F{8P7aN_3T5O7hm=^vmeB~*d&S)@zG@A1*~JPvX=?C@og%i`9i zEYrYwkr|HmvrWLyd7r~EvhP`X|MX_RCyup9EPr@wUeg<0@jg-HlVGhZ0B_KM8?hO3 zl@*dFtn*&6JHvSo^_f?jB)NANyKLnf^zoW~TAr*}w*u*)?ADdnCTV5eJ%y*J8N7rK zT86Fp>nDd*MMu()Rw3G|6)`+hCk7%4*Xh5XjYyC$U~tNv8w!05I-Gmc{qbbQ5A%&w zdk025XEt=ctnHG7*}e~NXCK8PN}7g^icO7sQbTiK2;+4t+^=DP0ma4Do~FEMERgw| z5_vGS8BGbtR08q$WyAxS=$D`J(40F%UkV;bjk1xL3GuFIbCGZB%0l8)h)mpm%(z_| zpIn<nc{trHq(iIu%)d?T~c2s=<(B^OmyHkMT&EW<@iSQ0%>t(UxfIL`AiOtRMSl zj90S9<-dcMn@*^l9NNU_-%QJ@9EAkMqn|Kae=2(GKjp4y%X@yXy+RZoD>3nAnq*bg zuVe64&>8JHN7@+eyAEv<#Qi@&l0$ThfR{@;(lGzKPTI@f<23kt3zo+00>es4C2}C< zHwL#z|G|J-8-t#3_36d(0@4zlpkPCDpdqdc2!g4xL-#ZCeU-b+0cLV9`sXfL(lHSX z&o+^OvX2%+rgU%2G}<^ij7MRi6H!ZF;V4SSRL3~{>M%VERg-a-N8M@o*hdYwDZ(O- z`nbTFbV*lDgqf?N_R<@-ap~D7H?P}|plf*eeS=g_nuzKql1yuj*meU$u;o&457U`4 zKC^YFzU3bd=%M@+-QT0$ggV%?OaCi*jX{dg7B4aqJ-h+}B$yJ8jd`4ruRXtk$3*j7 zp;iCFO`+d;#DEowhwQ-c+GfLlhAJb|0@yaYUnK+*Tii}?g@*Q!P#3hauZUa^%%$Vs zNeqxU$)6}%+O>1s%s5Up7`#x?kg+E>O>i>U!DSM^-ZCpBs4#L}OuK zzMOAklJfxke+4k;pKhryx@LL=EB2HBY<%-R@t3=i{W7)?3b1KCDbpG#)aC1@zg>h3 zOrk6hMsG2j`iBP@;hH-`xH0w)r%IUKFRUm!o!GEOdA`C(!Yn02yuk_;EirFYH^6t0 z?dhVWeb2kxr_tWB`Lktd%6>mo4K2x2nJGo45It&JkDrbd;{GPy zjW{JLlg&IfL<+;_BZ};aDrAauXUl=WC@~vtw;SE}=FUuBZ}7d#&)fUcA8HJOSFS^E zxFI)$m`iC}ZwO+2F?$w=Q*ks9?e5>YJAO~)$Wk+wto(qrr>BnYF#Z12kscJfwnJZX zDC5igp@QryvfMPLG0|ssDGDu%A5YEmekU^To-HpW0ymU~)qDv?_;?}H-$rDX5n@i9 z$M|dHob~HdM)u4Tezw5G^`)mK03@ia#QyKg%frW9rEj_ShsZxcI(p|U+63mMX2!QjgIN5ri!PO6VzHqR`w?^d@N{TR7H=6cUBVHmU(p+8voigBe$~U-4CHh=8fl;PH|D){P9=X=zl0f zX`3%4?ieJZ=SDvvG0EjphXlPK?D_6^4iL|gF0Dnx0)Hr5ha2Wcug1_{aCOaVv_B#M zbmz{-HAY&PH;;O}@~X*~0v73h9Frj|LFCAWdb%@Kx9%Uis%7yKADYTqSZYG3ueNji z917wX+s>RdjCluy%3V!dDvP%}k!+yIL@l8>d-h7b7yOA`AxL|7@^pGQsiS6ndv0Il+R)t;i;HyU}Mvc+wc_4cY;R}HD z!uDFVZ)eB!)V-HbYhd^Oia)f>MoqsFT$9q)CG}#uXbumv+0c0*isakycaL$@TE!cK ze|wV|U7s4euKBw`?|%2vf*=@@&8f}2dECRTjr23r(2pP>HgDF8HZ$g&5&>e}@RH?A z{u&v;105>vV2`*eH$Lk+a|DnbS}x~GczSl8y=QMCt*TX9jYUH`Lz9d^@?;p2V9%H~ z+s^#fB(^tv&w`j`?Pmy~7QH#l;f+pT>T&zFm@6!p0WEs#bb1?}(Ngj#tiiJ>P%Z!GGzMv}KoKh~5%%IfBB77w6@4k34C$=+*FNN(C^ zkVyf;=O<#8`0XZEuc^I`HUmA$(I8mRA+qN2lB>rtFMFt(yu=_=)XProJWs`xg^b(?|hi?mxQEFAJ7%^TZJUykW$v#siAl?XhqkAIF_P$8<2 zKEyP3yBkgr2fL*i7dgMUHfa-+#niDzBe3wZ#R4eG?UE6rqMf1)39P@+9<0%@ zFWu67*9qtTK9X)11#GTf3n@zpMKYnTC*r(QR;=*gMDTC8>9mo3xwHWwr zu?oZbO4iDg=Zs}j`qtlNg zKH8Qhce2~Yvbs>rybtUbBT);ZHawVq8PxCUC(C$eYEz-ORgMJi?+zeqIS4k;V7#|= zq9a1B&tg12^rna*#A!ERG>OKbFX`wOT%;|Bv><;-b;l)^ge`$zYvyvfCv~5nY#r*q zMJ6w~%N)-F+-64K8s;li3movxjd^}FcC{k+JU{o2r=-Ybh>x-!%k<`J=VoZ^Bre;1 z>X(mPgxBvhLtpwSljy_Z(3V%sm56x>=j{ROCPRZB^1nj|-|qiDba?o1f{>9_Opk?y z9nQi4=ip@Gfb(#$!?`(`*}2%5*f`lAP8?wDoSZCd>|E@OoLrpr+}s>YZ0vAG4mLOo z3mYdJ6FWN#<3lf2HaH_I2OErygM)L9Y%E^)jJ)IEq`6TMMZq#28oki$i zWs{2?{$rPd>dyZ0&xK0RHtr-V4AO{_i&fDO_5eeSC(zV&BH((gZq5I*vb59IV^9k;+hQG2ynQ*NF*4Gn;g=2&dIddd3kS? zO%kvc-P-#cF-=g`l)dDx;l7g)jlx@B-2(j=(C^W98+S@(Td?)gSR`zcV19+C+d4%d z60-!_in6Y9^CVl$f8f9#ko>+S$G@jyqKrYNt6pSlJiU>|C~&nUmx&M2g${9bY4-Ub z4)oaYbY-Kyy>d?CvK02dz%73@g&Jv-`pmxz{TZ~J3q7-Y<0g=y5y5%^f{}%wXs!LK zRC%L+SAPnY+p*fa1GJ!S>DI@=YW5Q@n=MyMSDjMmeuY zC5@^NxJR5;;UaDKyKEm(fm|pI|4+%yFRx<>Ctl6u5@}vvQoL2cc7LbA!J%;*A3n8M z0Uy?#Q`QREfOc3B#02WjjCXRKP1h*VJFrv;(dZb$yU*+#$U!IVn_~<{=p7LXIi+zudVBHhu2I zTiwe$_&Uq75Q4FN;E6L{`9`?T3fJW2pU&Cd0E?H-XI~ow3(D0O{;@`w6VcjddapxA0KkIE7V5sUQ`i)VTsKPEr3fN@ z1DX4|wC80kc*0_xah%E<2pIlb1Nq-;KaW_#K5tn=rY z)hHzl?ktgg^Ia!HRsFxNSn#N+TfE;px~{FhByGRA%I1O4PWtz}pn7)TgR)BuEJ(`g z8R^{ox}Vs3=SLh>T6;xjp>03{R4pCW&seDp4cDE)!W{lYmZ)=bjMdvgfEK8$i(+N{ zo@fPiqpxXLc};iCdkB8w_#y`1pGgVasXitbOw&Q25Vi9j_?vqHE4f$v_U)sv@6r%kQ~ zIDeWN^=(Rqr)5JARM5ku^#{;1^q^&r?flGs&qK5gD1oA4@zOj&ZoW7GFE8~;GlMX{4`VHJ$RBT_(GiV&(}^jK zTP7F41&Wz$+c$qj^eK4VZ0+JDIvZfb`zxD0zF@SLdc*0fJBfkX^m}wqD5jwzSHX$U zYnn#VKKqjob_l;GwMO37?d^DFm0VimL<}LfN0$Bikx`7;E$RNT+wHXAoXL(2kGmzY z5*=Pa={s;+M7<5=O1l-MG3;s3zl%&|)1iLs$b#6-h1s}O+P)zQqp#=Rn1);UAujhf z941Ap!mv3l*c@T8RzTI1ns`-W){cpfMnG7L3m%TA$GVn=*bhIT-+0CQ7tTY5 zg&Z$ufB(DKgp1>8`i(6~Q5^T0&&&ZNjSRCv zxM@A~xs%^9KPxo~(%or;7G?PS8T?(5`X#?>h$(Yp;^Dq;D9$tJP?9YZ)n4LDC%;`& zgghYUoCupjt?Eo;!|ln{#PoN&lW}y1dSRh69w2~MpKhr0{q}tpQS5+SxEc77-?G!G zvobD${OZnLes$#|Tr6Vf;j^0A_{YEShNVN*Ru!)7?iirvxnlmcZtX4-v(%pUtt7cM z;wr`Eo7jgzuZq-9l0~JK9utl60wqw%m}MoOn}La9 zr@_jrYd^kQZyyki@u*5Fv4Y6u`EDH?dRD$Ex7P$Sr|jdKYKjj(#)WuOiT#j)Zplzp z_OoO2Lj_N4%o?ldHV)3ugi-f18Lf{as=O&@jnwJ|+smbJ&8b=oIX0}wA12N6Re*i3 zJTdh{?}Z5kp7R%EzebLkpnXK9qx2AI_U(N9>X`VS44vG^KG+X2#@*3_R7A|F(uGme z0R8rqQb(iC;;Ag;8abupx_AMF5IWWA6(Q`vl9*1P zI6XG=Wmr6cbR_zuICOAjMwBWry&&b*YFM`%%DbzW_$XqBCshP(SY$g3{-?$3Bw zU*v3(V0TMe;+J+Ge(>K^k%ea88f2VmAjQm6^tI#zOjyH}sf)$yi$#ZlIEO#9IKF=^ zP(uxXhE^K(HQqDEE_8987Dad9j}m{pTAQ>z+E?LRlE3(UeOo`upVCRMmIEvZ4^<*v z-%K8II2!wLHY8S3=QH`5+SwV#J0z#1=<%8VPKk5Wucf1W96h0oI1E=xu$c95@$SSJ zm|p0NWZT97Vnhwfc2(7G_Oh)J-SdkHhh8iH3H` zqsR(BL7FnF|EG^VowJfaSQ%z68 zInw}P_D#O;(@t_Qu^Y4d?m_$XzGja=-^s$~tQe^U=AMdleYbW!Ss~WH>W$D1EMMOH zM7tr>9eTyLrpYR9J%_fC>3K(!Ga-}+hB~bd+~nGC`S>xi*0p7af7e5}xG&}~o0(fT zY%{<23JokbzMmeB-@7Lofr7h=)9!{u`y<)1s091+|uZ0Xe7Y~9G~jhjC$A<3Q7YI4SphGtA+m8|{2F}E1?O#RoT&;q0u!Q1>t&#zSO zE5KC!hc+hmHbwyE{b+05V9~p5Ngr?de)e{=DPF<(k;kSB_$5%`VH~|nqE))aq}~Du z;R@5lx6cwIecyEO&{NCir4v8R+SQqO`yhea=W^|}Wz2ibz;!D1G%E%NUz#<+H6z%7 z_f56ln}{C9iyN*QNEozSDdWfW-8t@Dj4n;r+eR_SMW+vWr1_P0^B>gr;^{ww-F7+U z>rNLR0Rh70(v1r@eW#)NS%E#R%Jen#b?6EQB8F&Q14z z&z&bmH%x^?LIMj-bk8uShHa#fIc0cRVNytF)Fju~r0-@N{ zlYqW&xVz^RHrY;by%hS?QmDZzW9%~&%z*=uQbo!#4NAofrtgf&6oKAwE|gZD$wbY~ zpN~9ttJPR7q4zG|-g!ocL0z96jfjL8(>H#+oMNhiK+$54dJCO}zg?Jeug=_lZHhbM zVn2C);-NWZKqy6r*C9B8ECaO0* z;cEkcyyz2oT5EOJz3jjiw#MldR{tN&(Wj=(g-Q4|(AH-SrBuTTPfY{YGe&w}`3E3K zEqS2YNE+!PT`FMpO4eRuKbqICVe>-Kg?e=x$2R-)Baf`bN^b+diPn=i)7;VwZQS6g zb2E<-qXQY=>i@% zcjGoj>Hxh+BRUIUtVeFK!QTvkm-S~rep@%TGRiSL4zFbaUO+>WY_}q}x`?0cT)_N@ z0pByTkEDfO3s3fE(@l3x*n--1`W0GTspJFT;3-k_&D}L>yO@9S?GUmNpt#gB^@Jf& zy2O6OuzW``E#JEo7LPjx<3%iiVXCrI%wGj_zj7K2stNj*WofC2`1|6pz*bAtgOO{f zR6cuP7ZS{CGkIk;`4a=2uqohEAxbK3$30U(j0AM(RF?NXDqS2>wROwxiXTY}%?pb| z0grx?UZvWfL$(8PnvRG@v)Qr zJBr|SjIK*Eu}5K}J|tZ)RDP9(xIKlI@n>9}R4mW=t$9lV0Wevc&y{VdqLuXYpf#+m z9VEsl03cOg#a-aZad*u6c^Kc1*5UZ`9j;_uTWeNC7wBp4VukS5S`_H=7ee%ehN#QqK?a;@*G6yYT|Fif4nYq=z#Jn1P70?MeByGsbGhEqiz2ff4EQO6#iRDR{w1Du`z+tCt|w0`G4O-ARSNs_t6CS z-vI#nSn`*T+1NN(8CW=A3~=yUIXDNLfgSt=0?y4u$HBtP#38@~qK--66!*CkSC|Np zM_ktC_4L^-Tg0yXJ6bU38`6oOUXH!U9We&)c0HU2rjUp=5DI1HBYjb;sI_iGHn2(|Ni`$-ZXmU8YF#UUrEAX0)-LB_2w}}>B_|_)MWuY_VpyR6RtQp zs6P*ryl$NHjeg>De{)htpoF@U&gav$u?=7cwQ&0(yj`tLqjRkpcs&3^*0mj&Zs-rq z#s_y&6}QfpId`Pe2Xj0-n2|_QTDT%h4Qcbxt%8Fo?5D4{^yVW3*ZRDarvVol_quK> z`;Xoe&Id8N@(I)021wl{5CNC1+blj&A6V63n-;^{_IIV7Nb^(y)h6gRPzbK~4|XoX znEB_i3MhOiKze;Fv66;H*HNqX&}+G!KaZv~v%^?Y?Xf_eUc0mxxATWEVP2b2@K7#q zubk`5dRhKd+ui57?=mWqmdZnZ0WA;D$S9S)l^u>*uu|8MVg?L-DjBf$!t36C%hdT8 zsBX9K@{}g>mA4={xJwjfOZ4BlxbF3!*NBz8LZH*mLg_d-`$m2~vMk#x=Td%&so&^&^`0_w#D>crc$?Jf8BQfY9k@Tyd|sqx=Rz0Y`odz0CsE&=!6Sct$Q zgbwkd5U)Z8gi8hplRJnw@leE>tBevhEF-nrv0C{LuToXx z8OgOwiQn=0K|9VwUY_hIS9am_PB{x1JkYjGbm)_`XLeJ!u~x=J%JZEbe~D%Jttohf zT7Q!u-y~5_B)DLswU#m%30S9e=k0P^+`z3Th5wol(ah55=vhY5f#IfJ3CnOd=QcX_ zo4&L__(O^LMfY7@d#ewoY)|ahHl~=0ow55w4<0^|cF&zACDcETX_=&vDnjN|L;#pa z&b+w3tG;GxVg6>(;~nk{k(BKs212-WT3J$u?5svO`YKHN>g9+O^1P0EILW{_^XZJ; zFX&aKlZr``0t%t;jV>CZ)Bh7g0lfYgAEf242{B%y7QC6c@>#Se^c)K!)5@#;g;r!X zQw~4^yj}PyUD|jr#&FH(mBr46Is88K9Cz5@!F-9Ih!$WgR-=8dOkw~Kp8flp?-FwH z-|HJ2>(c(kouc9BokKq$sT1@ZuTi;t%%9J%k>qy9@lt>SkRSj3O7-@K8JD`n<+r|P zI%|(DyyYAM{2U7tIf|wKDQ}BR`$+)>z&}0JOr)kmOIk`y%A!6Z^>cxo@52#c^c)Ku z)8t627)mkI#%95tBWY4`B|GXa_68QxwR zg&<))fA@MWW`@P|Kpkif5~02ZlUYF7wbPe*HURVxcZ>wP?& Date: Mon, 3 Jun 2024 20:48:44 +0200 Subject: [PATCH 45/63] Make borgs shown in logprobe (#27788) --- Content.Shared/Access/Systems/AccessReaderSystem.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Content.Shared/Access/Systems/AccessReaderSystem.cs b/Content.Shared/Access/Systems/AccessReaderSystem.cs index 3670e24bd3..efdbff3bb8 100644 --- a/Content.Shared/Access/Systems/AccessReaderSystem.cs +++ b/Content.Shared/Access/Systems/AccessReaderSystem.cs @@ -6,7 +6,9 @@ using Content.Shared.Emag.Components; using Content.Shared.Emag.Systems; using Content.Shared.Hands.EntitySystems; using Content.Shared.Inventory; +using Content.Shared.NameIdentifier; using Content.Shared.PDA; +using Content.Shared.Silicons.Borgs.Components; using Content.Shared.StationRecords; using Robust.Shared.Containers; using Robust.Shared.GameStates; @@ -393,6 +395,9 @@ public sealed class AccessReaderSystem : EntitySystem ent.Comp.AccessLog.Dequeue(); string? name = null; + if (TryComp(accessor, out var nameIdentifier)) + name = nameIdentifier.FullIdentifier; + // TODO pass the ID card on IsAllowed() instead of using this expensive method // Set name if the accessor has a card and that card has a name and allows itself to be recorded if (_idCardSystem.TryFindIdCard(accessor, out var idCard) From b1c123efae5fdcc1ba8d968c32ef85321afb939c Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 3 Jun 2024 18:49:52 +0000 Subject: [PATCH 46/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 51 ++++++++++++++----------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f2d3131827..0ae775e193 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,32 +1,4 @@ Entries: -- author: PJB3005 - changes: - - message: Fixed pressure damage calculations to what they were always supposed - to be. This means pressure damage now starts happening at more extreme values - (20 kPa for low pressure damage instead of 50 kPa) and high pressure damage - is scaled different. It also fixed the HUD alerts so that the "warning" alerts - show up before you actually start taking damage. - type: Fix - - message: Air alarms now start complaining about low pressure much earlier, when - the pressure drops so much that you can't breathe oxygen tank. - type: Tweak - id: 6176 - time: '2024-03-18T05:16:31.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26217 -- author: HappyRoach - changes: - - message: The correct magazines now appear in the WT550 safe. - type: Fix - id: 6177 - time: '2024-03-18T06:10:28.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26208 -- author: vanx - changes: - - message: You can now wear most guns in the suit slot, and see them on yourself! - type: Tweak - id: 6178 - time: '2024-03-18T06:16:09.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26152 - author: Dutch-VanDerLinde changes: - message: Romerol now properly works on the dead. @@ -3855,3 +3827,26 @@ id: 6675 time: '2024-06-03T16:12:21.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/28270 +- author: TheShuEd + changes: + - message: Added italian and cowboy accents + type: Add + - message: Now you can't choose all the accents at once. + type: Fix + id: 6676 + time: '2024-06-03T18:47:06.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28046 +- author: RenQ + changes: + - message: The moths now have their own "death grasp" + type: Add + id: 6677 + time: '2024-06-03T18:48:01.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28409 +- author: lzk228 + changes: + - message: Borgs ID now will be shown in LogProbe instead of Unknown. + type: Tweak + id: 6678 + time: '2024-06-03T18:48:44.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/27788 From af7f70bade908658416be91c5571cab1160e18ec Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Mon, 3 Jun 2024 15:40:46 -0400 Subject: [PATCH 47/63] Add integration test for LocalizedDatasets (#28485) --- .../LocalizedDatasetPrototypeTest.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Content.IntegrationTests/Tests/Localization/LocalizedDatasetPrototypeTest.cs diff --git a/Content.IntegrationTests/Tests/Localization/LocalizedDatasetPrototypeTest.cs b/Content.IntegrationTests/Tests/Localization/LocalizedDatasetPrototypeTest.cs new file mode 100644 index 0000000000..b30c0a370e --- /dev/null +++ b/Content.IntegrationTests/Tests/Localization/LocalizedDatasetPrototypeTest.cs @@ -0,0 +1,35 @@ +using System.Linq; +using Content.Shared.Dataset; +using Robust.Shared.Localization; +using Robust.Shared.Prototypes; + +namespace Content.IntegrationTests.Tests.Localization; + +[TestFixture] +public sealed class LocalizedDatasetPrototypeTest +{ + [Test] + public async Task ValidProtoIdsTest() + { + await using var pair = await PoolManager.GetServerClient(); + + var server = pair.Server; + var protoMan = server.ResolveDependency(); + var localizationMan = server.ResolveDependency(); + + var protos = protoMan.EnumeratePrototypes().OrderBy(p => p.ID); + + // Check each prototype + foreach (var proto in protos) + { + // Check each value in the prototype + foreach (var locId in proto.Values) + { + // Make sure the localization manager has a string for the LocId + Assert.That(localizationMan.HasString(locId), $"LocalizedDataset {proto.ID} with prefix \"{proto.Values.Prefix}\" specifies {proto.Values.Count} entries, but no localized string was found matching {locId}!"); + } + } + + await pair.CleanReturnAsync(); + } +} From 98ab251f9212699a816aaaf31792ffcda768e8c9 Mon Sep 17 00:00:00 2001 From: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com> Date: Mon, 3 Jun 2024 15:55:43 -0500 Subject: [PATCH 48/63] Remove duplicate entities (#28561) --- .../Entities/Structures/Doors/Airlocks/access.yml | 9 --------- Resources/migration.yml | 3 +++ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/access.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/access.yml index d798d0c3be..e92da80c4b 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/access.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/access.yml @@ -73,15 +73,6 @@ containers: board: [ DoorElectronicsHydroponics ] -- type: entity - parent: AirlockCommandLocked - id: AirlockServiceCaptainLocked - suffix: Captain, Locked - components: - - type: ContainerFill - containers: - board: [ DoorElectronicsCaptain ] - - type: entity parent: AirlockExternal id: AirlockExternalLocked diff --git a/Resources/migration.yml b/Resources/migration.yml index cf1a0f7a60..65e914aed6 100644 --- a/Resources/migration.yml +++ b/Resources/migration.yml @@ -345,3 +345,6 @@ CrateJanitorExplosive: ClosetJanitorBombFilled # 2024-05-27 DoorRemoteFirefight: null + +# 2024-06-03 +AirlockServiceCaptainLocked: AirlockCaptainLocked From 5e51a1d73c3a90438969b8100a32e43e44a5a5fb Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:05:51 +1200 Subject: [PATCH 49/63] Add StorageInteractionTest (#28541) --- .../Tests/Chemistry/DispenserTest.cs | 2 +- .../Interaction/ComputerContruction.cs | 10 +- .../Interaction/GrilleWindowConstruction.cs | 13 +- .../Interaction/MachineConstruction.cs | 7 +- .../Construction/Interaction/PanelScrewing.cs | 12 +- .../Interaction/PlaceableDeconstruction.cs | 4 +- .../Interaction/WallConstruction.cs | 9 +- .../Interaction/WindowConstruction.cs | 8 +- .../Construction/Interaction/WindowRepair.cs | 2 +- .../Tests/DoAfter/DoAfterCancellationTests.cs | 39 +- .../EncryptionKeys/RemoveEncryptionKeys.cs | 16 +- .../InteractionTest.EntitySpecifier.cs | 6 +- .../Interaction/InteractionTest.Helpers.cs | 353 +++++++++++++----- .../Tests/Interaction/InteractionTest.cs | 29 +- .../Tests/Payload/ModularGrenadeTests.cs | 14 +- .../Tests/Storage/StorageInteractionTest.cs | 75 ++++ .../Tests/Tiles/TileConstructionTests.cs | 16 +- .../Tests/Weldable/WeldableTests.cs | 2 +- 18 files changed, 427 insertions(+), 190 deletions(-) create mode 100644 Content.IntegrationTests/Tests/Storage/StorageInteractionTest.cs diff --git a/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs b/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs index a5449308be..52b7e555a9 100644 --- a/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs +++ b/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs @@ -18,7 +18,7 @@ public sealed class DispenserTest : InteractionTest ToggleNeedPower(); // Insert beaker - await Interact("Beaker"); + await InteractUsing("Beaker"); Assert.That(Hands.ActiveHandEntity, Is.Null); // Open BUI diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/ComputerContruction.cs b/Content.IntegrationTests/Tests/Construction/Interaction/ComputerContruction.cs index 5412469ac5..8af5edaf31 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/ComputerContruction.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/ComputerContruction.cs @@ -16,10 +16,8 @@ public sealed class ComputerConstruction : InteractionTest await StartConstruction(Computer); // Initial interaction (ghost turns into real entity) - await Interact(Steel, 5); - ClientAssertPrototype(ComputerFrame, ClientTarget); - Target = CTestSystem.Ghosts[ClientTarget!.Value.GetHashCode()]; - ClientTarget = null; + await InteractUsing(Steel, 5); + ClientAssertPrototype(ComputerFrame, Target); // Perform construction steps await Interact( @@ -41,7 +39,7 @@ public sealed class ComputerConstruction : InteractionTest await StartDeconstruction(ComputerId); // Initial interaction turns id computer into generic computer - await Interact(Screw); + await InteractUsing(Screw); AssertPrototype(ComputerFrame); // Perform deconstruction steps @@ -71,7 +69,7 @@ public sealed class ComputerConstruction : InteractionTest await SpawnTarget(ComputerId); // Initial interaction turns id computer into generic computer - await Interact(Screw); + await InteractUsing(Screw); AssertPrototype(ComputerFrame); // Perform partial deconstruction steps diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/GrilleWindowConstruction.cs b/Content.IntegrationTests/Tests/Construction/Interaction/GrilleWindowConstruction.cs index 0de39d2757..ef6a7b09ae 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/GrilleWindowConstruction.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/GrilleWindowConstruction.cs @@ -17,17 +17,14 @@ public sealed class GrilleWindowConstruction : InteractionTest { // Construct Grille await StartConstruction(Grille); - await Interact(Rod, 10); - ClientAssertPrototype(Grille, ClientTarget); - - Target = CTestSystem.Ghosts[ClientTarget!.Value.GetHashCode()]; + await InteractUsing(Rod, 10); + ClientAssertPrototype(Grille, Target); var grille = Target; // Construct Window await StartConstruction(Window); - await Interact(Glass, 10); - ClientAssertPrototype(Window, ClientTarget); - Target = CTestSystem.Ghosts[ClientTarget!.Value.GetHashCode()]; + await InteractUsing(Glass, 10); + ClientAssertPrototype(Window, Target); // Deconstruct Window await Interact(Screw, Wrench); @@ -35,7 +32,7 @@ public sealed class GrilleWindowConstruction : InteractionTest // Deconstruct Grille Target = grille; - await Interact(Cut); + await InteractUsing(Cut); AssertDeleted(); } diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs b/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs index f52f820a4c..06874f39ed 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs @@ -14,9 +14,8 @@ public sealed class MachineConstruction : InteractionTest public async Task ConstructProtolathe() { await StartConstruction(MachineFrame); - await Interact(Steel, 5); - ClientAssertPrototype(Unfinished, ClientTarget); - Target = CTestSystem.Ghosts[ClientTarget!.Value.GetHashCode()]; + await InteractUsing(Steel, 5); + ClientAssertPrototype(Unfinished, Target); await Interact(Wrench, Cable); AssertPrototype(MachineFrame); await Interact(ProtolatheBoard, Bin1, Bin1, Manipulator1, Manipulator1, Beaker, Beaker, Screw); @@ -51,7 +50,7 @@ public sealed class MachineConstruction : InteractionTest AssertPrototype(MachineFrame); // Change it into an autolathe - await Interact("AutolatheMachineCircuitboard"); + await InteractUsing("AutolatheMachineCircuitboard"); AssertPrototype(MachineFrame); await Interact(Bin1, Bin1, Bin1, Manipulator1, Glass, Screw); AssertPrototype("Autolathe"); diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/PanelScrewing.cs b/Content.IntegrationTests/Tests/Construction/Interaction/PanelScrewing.cs index b6d960e288..636d58bf96 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/PanelScrewing.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/PanelScrewing.cs @@ -19,21 +19,21 @@ public sealed class PanelScrewing : InteractionTest // Open & close panel Assert.That(comp.Open, Is.False); - await Interact(Screw); + await InteractUsing(Screw); Assert.That(comp.Open, Is.True); - await Interact(Screw); + await InteractUsing(Screw); Assert.That(comp.Open, Is.False); // Interrupted DoAfters - await Interact(Screw, awaitDoAfters: false); + await InteractUsing(Screw, awaitDoAfters: false); await CancelDoAfters(); Assert.That(comp.Open, Is.False); - await Interact(Screw); + await InteractUsing(Screw); Assert.That(comp.Open, Is.True); - await Interact(Screw, awaitDoAfters: false); + await InteractUsing(Screw, awaitDoAfters: false); await CancelDoAfters(); Assert.That(comp.Open, Is.True); - await Interact(Screw); + await InteractUsing(Screw); Assert.That(comp.Open, Is.False); } } diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/PlaceableDeconstruction.cs b/Content.IntegrationTests/Tests/Construction/Interaction/PlaceableDeconstruction.cs index bc0cb9bcef..783c14c068 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/PlaceableDeconstruction.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/PlaceableDeconstruction.cs @@ -13,9 +13,9 @@ public sealed class PlaceableDeconstruction : InteractionTest { await StartDeconstruction("Table"); Assert.That(Comp().IsPlaceable); - await Interact(Wrench); + await InteractUsing(Wrench); AssertPrototype("TableFrame"); - await Interact(Wrench); + await InteractUsing(Wrench); AssertDeleted(); await AssertEntityLookup((Steel, 1), (Rod, 2)); } diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/WallConstruction.cs b/Content.IntegrationTests/Tests/Construction/Interaction/WallConstruction.cs index 67a2f8025d..292bf0c55a 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/WallConstruction.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/WallConstruction.cs @@ -12,11 +12,10 @@ public sealed class WallConstruction : InteractionTest public async Task ConstructWall() { await StartConstruction(Wall); - await Interact(Steel, 2); + await InteractUsing(Steel, 2); Assert.That(Hands.ActiveHandEntity, Is.Null); - ClientAssertPrototype(Girder, ClientTarget); - Target = CTestSystem.Ghosts[ClientTarget!.Value.GetHashCode()]; - await Interact(Steel, 2); + ClientAssertPrototype(Girder, Target); + await InteractUsing(Steel, 2); Assert.That(Hands.ActiveHandEntity, Is.Null); AssertPrototype(WallSolid); } @@ -25,7 +24,7 @@ public sealed class WallConstruction : InteractionTest public async Task DeconstructWall() { await StartDeconstruction(WallSolid); - await Interact(Weld); + await InteractUsing(Weld); AssertPrototype(Girder); await Interact(Wrench, Screw); AssertDeleted(); diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/WindowConstruction.cs b/Content.IntegrationTests/Tests/Construction/Interaction/WindowConstruction.cs index 46bb892ed9..2ece6b3e39 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/WindowConstruction.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/WindowConstruction.cs @@ -11,8 +11,8 @@ public sealed class WindowConstruction : InteractionTest public async Task ConstructWindow() { await StartConstruction(Window); - await Interact(Glass, 5); - ClientAssertPrototype(Window, ClientTarget); + await InteractUsing(Glass, 5); + ClientAssertPrototype(Window, Target); } [Test] @@ -28,8 +28,8 @@ public sealed class WindowConstruction : InteractionTest public async Task ConstructReinforcedWindow() { await StartConstruction(RWindow); - await Interact(RGlass, 5); - ClientAssertPrototype(RWindow, ClientTarget); + await InteractUsing(RGlass, 5); + ClientAssertPrototype(RWindow, Target); } [Test] diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/WindowRepair.cs b/Content.IntegrationTests/Tests/Construction/Interaction/WindowRepair.cs index abd4bc265b..6eea519af3 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/WindowRepair.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/WindowRepair.cs @@ -24,7 +24,7 @@ public sealed class WindowRepair : InteractionTest Assert.That(comp.Damage.GetTotal(), Is.GreaterThan(FixedPoint2.Zero)); // Repair the entity - await Interact(Weld); + await InteractUsing(Weld); Assert.That(comp.Damage.GetTotal(), Is.EqualTo(FixedPoint2.Zero)); // Validate that we can still deconstruct the entity (i.e., that welding deconstruction is not blocked). diff --git a/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs b/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs index 0ebd17d887..1aaf4a5184 100644 --- a/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs +++ b/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs @@ -16,31 +16,31 @@ public sealed class DoAfterCancellationTests : InteractionTest public async Task CancelWallDeconstruct() { await StartDeconstruction(WallConstruction.WallSolid); - await Interact(Weld, awaitDoAfters: false); + await InteractUsing(Weld, awaitDoAfters: false); // Failed do-after has no effect await CancelDoAfters(); AssertPrototype(WallConstruction.WallSolid); // Second attempt works fine - await Interact(Weld); + await InteractUsing(Weld); AssertPrototype(WallConstruction.Girder); // Repeat for wrenching interaction AssertAnchored(); - await Interact(Wrench, awaitDoAfters: false); + await InteractUsing(Wrench, awaitDoAfters: false); await CancelDoAfters(); AssertAnchored(); AssertPrototype(WallConstruction.Girder); - await Interact(Wrench); + await InteractUsing(Wrench); AssertAnchored(false); // Repeat for screwdriver interaction. AssertExists(); - await Interact(Screw, awaitDoAfters: false); + await InteractUsing(Screw, awaitDoAfters: false); await CancelDoAfters(); AssertExists(); - await Interact(Screw); + await InteractUsing(Screw); AssertDeleted(); } @@ -48,17 +48,16 @@ public sealed class DoAfterCancellationTests : InteractionTest public async Task CancelWallConstruct() { await StartConstruction(WallConstruction.Wall); - await Interact(Steel, 5, awaitDoAfters: false); + await InteractUsing(Steel, 5, awaitDoAfters: false); await CancelDoAfters(); - await Interact(Steel, 5); - ClientAssertPrototype(WallConstruction.Girder, ClientTarget); - Target = CTestSystem.Ghosts[ClientTarget!.Value.GetHashCode()]; - await Interact(Steel, 5, awaitDoAfters: false); + await InteractUsing(Steel, 5); + ClientAssertPrototype(WallConstruction.Girder, Target); + await InteractUsing(Steel, 5, awaitDoAfters: false); await CancelDoAfters(); AssertPrototype(WallConstruction.Girder); - await Interact(Steel, 5); + await InteractUsing(Steel, 5); AssertPrototype(WallConstruction.WallSolid); } @@ -66,11 +65,11 @@ public sealed class DoAfterCancellationTests : InteractionTest public async Task CancelTilePry() { await SetTile(Floor); - await Interact(Pry, awaitDoAfters: false); + await InteractUsing(Pry, awaitDoAfters: false); await CancelDoAfters(); await AssertTile(Floor); - await Interact(Pry); + await InteractUsing(Pry); await AssertTile(Plating); } @@ -78,7 +77,7 @@ public sealed class DoAfterCancellationTests : InteractionTest public async Task CancelRepeatedTilePry() { await SetTile(Floor); - await Interact(Pry, awaitDoAfters: false); + await InteractUsing(Pry, awaitDoAfters: false); await RunTicks(1); Assert.That(ActiveDoAfters.Count(), Is.EqualTo(1)); await AssertTile(Floor); @@ -89,7 +88,7 @@ public sealed class DoAfterCancellationTests : InteractionTest await AssertTile(Floor); // Third do after will work fine - await Interact(Pry); + await InteractUsing(Pry); Assert.That(ActiveDoAfters.Count(), Is.EqualTo(0)); await AssertTile(Plating); } @@ -102,7 +101,7 @@ public sealed class DoAfterCancellationTests : InteractionTest Assert.That(comp.IsWelded, Is.False); - await Interact(Weld, awaitDoAfters: false); + await InteractUsing(Weld, awaitDoAfters: false); await RunTicks(1); Assert.Multiple(() => { @@ -120,7 +119,7 @@ public sealed class DoAfterCancellationTests : InteractionTest }); // Third do after will work fine - await Interact(Weld); + await InteractUsing(Weld); Assert.Multiple(() => { Assert.That(ActiveDoAfters.Count(), Is.EqualTo(0)); @@ -128,7 +127,7 @@ public sealed class DoAfterCancellationTests : InteractionTest }); // Repeat test for un-welding - await Interact(Weld, awaitDoAfters: false); + await InteractUsing(Weld, awaitDoAfters: false); await RunTicks(1); Assert.Multiple(() => { @@ -141,7 +140,7 @@ public sealed class DoAfterCancellationTests : InteractionTest Assert.That(ActiveDoAfters.Count(), Is.EqualTo(0)); Assert.That(comp.IsWelded, Is.True); }); - await Interact(Weld); + await InteractUsing(Weld); Assert.Multiple(() => { Assert.That(ActiveDoAfters.Count(), Is.EqualTo(0)); diff --git a/Content.IntegrationTests/Tests/EncryptionKeys/RemoveEncryptionKeys.cs b/Content.IntegrationTests/Tests/EncryptionKeys/RemoveEncryptionKeys.cs index 9e3dbd8863..f5e8c22242 100644 --- a/Content.IntegrationTests/Tests/EncryptionKeys/RemoveEncryptionKeys.cs +++ b/Content.IntegrationTests/Tests/EncryptionKeys/RemoveEncryptionKeys.cs @@ -22,7 +22,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest }); // Remove the key - await Interact(Screw); + await InteractUsing(Screw); Assert.Multiple(() => { Assert.That(comp.KeyContainer.ContainedEntities, Has.Count.EqualTo(0)); @@ -34,7 +34,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest await AssertEntityLookup(("EncryptionKeyCommon", 1)); // Re-insert a key. - await Interact("EncryptionKeyCentCom"); + await InteractUsing("EncryptionKeyCentCom"); Assert.Multiple(() => { Assert.That(comp.KeyContainer.ContainedEntities, Has.Count.EqualTo(1)); @@ -59,7 +59,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest }); // cannot remove keys without opening panel - await Interact(Pry); + await InteractUsing(Pry); Assert.Multiple(() => { Assert.That(comp.KeyContainer.ContainedEntities, Has.Count.GreaterThan(0)); @@ -68,7 +68,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest }); // Open panel - await Interact(Screw); + await InteractUsing(Screw); Assert.Multiple(() => { Assert.That(panel.Open, Is.True); @@ -79,7 +79,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest }); // Now remove the keys - await Interact(Pry); + await InteractUsing(Pry); Assert.Multiple(() => { Assert.That(comp.KeyContainer.ContainedEntities, Has.Count.EqualTo(0)); @@ -87,7 +87,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest }); // Reinsert a key - await Interact("EncryptionKeyCentCom"); + await InteractUsing("EncryptionKeyCentCom"); Assert.Multiple(() => { Assert.That(comp.KeyContainer.ContainedEntities, Has.Count.EqualTo(1)); @@ -97,7 +97,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest }); // Remove it again - await Interact(Pry); + await InteractUsing(Pry); Assert.Multiple(() => { Assert.That(comp.KeyContainer.ContainedEntities, Has.Count.EqualTo(0)); @@ -106,7 +106,7 @@ public sealed class RemoveEncryptionKeys : InteractionTest // Prying again will start deconstructing the machine. AssertPrototype("TelecomServerFilled"); - await Interact(Pry); + await InteractUsing(Pry); AssertPrototype("MachineFrame"); } } diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs index 37dca72137..053152dbe1 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.EntitySpecifier.cs @@ -33,7 +33,7 @@ public abstract partial class InteractionTest public int Quantity; /// - /// If true, a check has been performed to see if the prototype ia an entity prototype with a stack component, + /// If true, a check has been performed to see if the prototype is an entity prototype with a stack component, /// in which case the specifier was converted into a stack-specifier /// public bool Converted; @@ -100,7 +100,7 @@ public abstract partial class InteractionTest if (!ProtoMan.TryIndex(spec.Prototype, out var entProto)) { - Assert.Fail($"Unkown prototype: {spec.Prototype}"); + Assert.Fail($"Unknown prototype: {spec.Prototype}"); return default; } @@ -120,7 +120,7 @@ public abstract partial class InteractionTest /// /// Convert an entity-uid to a matching entity specifier. Useful when doing entity lookups & checking that the - /// right quantity of entities/materials werre produced. Returns null if passed an entity with a null prototype. + /// right quantity of entities/materials were produced. Returns null if passed an entity with a null prototype. /// protected EntitySpecifier? ToEntitySpecifier(EntityUid uid) { diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs index 19ca83a971..f4826cb249 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Helpers.cs @@ -14,6 +14,7 @@ using Content.Shared.Construction.Prototypes; using Content.Shared.Gravity; using Content.Shared.Item; using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.GameObjects; using Robust.Shared.Input; @@ -44,8 +45,9 @@ public abstract partial class InteractionTest return; var comp = CEntMan.GetComponent(clientTarget!.Value); - ClientTarget = clientTarget; - ConstructionGhostId = comp.Owner.Id; + Target = CEntMan.GetNetEntity(clientTarget.Value); + Assert.That(Target.Value.IsClientSide()); + ConstructionGhostId = clientTarget.Value.GetHashCode(); }); await RunTicks(1); @@ -129,21 +131,20 @@ public abstract partial class InteractionTest /// /// Place an entity prototype into the players hand. Deletes any currently held entity. /// - /// - /// Automatically enables welders. - /// - protected async Task PlaceInHands(string id, int quantity = 1, bool enableWelder = true) + /// The entity or stack prototype to spawn and place into the users hand + /// The number of entities to spawn. If the prototype is a stack, this sets the stack count. + /// Whether or not to automatically enable any toggleable items + protected async Task PlaceInHands(string id, int quantity = 1, bool enableToggleable = true) { - return await PlaceInHands((id, quantity), enableWelder); + return await PlaceInHands((id, quantity), enableToggleable); } /// /// Place an entity prototype into the players hand. Deletes any currently held entity. /// - /// - /// Automatically enables welders. - /// - protected async Task PlaceInHands(EntitySpecifier entity, bool enableWelder = true) + /// The entity type & quantity to spawn and place into the users hand + /// Whether or not to automatically enable any toggleable items + protected async Task PlaceInHands(EntitySpecifier entity, bool enableToggleable = true) { if (Hands.ActiveHand == null) { @@ -165,7 +166,7 @@ public abstract partial class InteractionTest Assert.That(HandSys.TryPickup(playerEnt, item, Hands.ActiveHand, false, false, Hands)); // turn on welders - if (enableWelder && SEntMan.TryGetComponent(item, out itemToggle) && !itemToggle.Activated) + if (enableToggleable && SEntMan.TryGetComponent(item, out itemToggle) && !itemToggle.Activated) { Assert.That(ItemToggleSys.TryActivate(item, playerEnt, itemToggle: itemToggle)); } @@ -173,7 +174,7 @@ public abstract partial class InteractionTest await RunTicks(1); Assert.That(Hands.ActiveHandEntity, Is.EqualTo(item)); - if (enableWelder && itemToggle != null) + if (enableToggleable && itemToggle != null) Assert.That(itemToggle.Activated); return SEntMan.GetNetEntity(item); @@ -254,21 +255,20 @@ public abstract partial class InteractionTest /// /// Place an entity prototype into the players hand and interact with the given entity (or target position) /// - /// - /// Empty strings imply empty hands. - /// - protected async Task Interact(string id, int quantity = 1, bool shouldSucceed = true, bool awaitDoAfters = true) + /// The entity or stack prototype to spawn and place into the users hand + /// The number of entities to spawn. If the prototype is a stack, this sets the stack count. + /// Whether or not to wait for any do-afters to complete + protected async Task InteractUsing(string id, int quantity = 1, bool awaitDoAfters = true) { - await Interact((id, quantity), shouldSucceed, awaitDoAfters); + await InteractUsing((id, quantity), awaitDoAfters); } /// - /// Place an entity prototype into the players hand and interact with the given entity (or target position) + /// Place an entity prototype into the players hand and interact with the given entity (or target position). /// - /// - /// Empty strings imply empty hands. - /// - protected async Task Interact(EntitySpecifier entity, bool shouldSucceed = true, bool awaitDoAfters = true) + /// The entity type & quantity to spawn and place into the users hand + /// Whether or not to wait for any do-afters to complete + protected async Task InteractUsing(EntitySpecifier entity, bool awaitDoAfters = true) { // For every interaction, we will also examine the entity, just in case this breaks something, somehow. // (e.g., servers attempt to assemble construction examine hints). @@ -278,38 +278,80 @@ public abstract partial class InteractionTest } await PlaceInHands(entity); - await Interact(shouldSucceed, awaitDoAfters); + await Interact(awaitDoAfters); } /// /// Interact with an entity using the currently held entity. /// - protected async Task Interact(bool shouldSucceed = true, bool awaitDoAfters = true) + /// Whether or not to wait for any do-afters to complete + protected async Task Interact(bool awaitDoAfters = true) { - var clientTarget = ClientTarget; - - if ((clientTarget?.IsValid() != true || CEntMan.Deleted(clientTarget)) && (Target == null || Target.Value.IsValid())) + if (Target == null || !Target.Value.IsClientSide()) { - await Server.WaitPost(() => InteractSys.UserInteraction(SEntMan.GetEntity(Player), SEntMan.GetCoordinates(TargetCoords), SEntMan.GetEntity(Target))); - await RunTicks(1); + await Interact(Target, TargetCoords, awaitDoAfters); + return; } - else - { - // The entity is client-side, so attempt to start construction - var clientEnt = ClientTarget ?? CEntMan.GetEntity(Target); - await Client.WaitPost(() => CConSys.TryStartConstruction(clientEnt!.Value)); - await RunTicks(5); - } + // The target is a client-side entity, so we will just attempt to start construction under the assumption that + // it is a construction ghost. + + await Client.WaitPost(() => CConSys.TryStartConstruction(CTarget!.Value)); + await RunTicks(5); if (awaitDoAfters) - await AwaitDoAfters(shouldSucceed); + await AwaitDoAfters(); - await CheckTargetChange(shouldSucceed && awaitDoAfters); + await CheckTargetChange(); + } + + /// + protected async Task Interact(NetEntity? target, NetCoordinates coordinates, bool awaitDoAfters = true) + { + Assert.That(SEntMan.TryGetEntity(target, out var sTarget) || target == null); + var coords = SEntMan.GetCoordinates(coordinates); + Assert.That(coords.IsValid(SEntMan)); + await Interact(sTarget, coords, awaitDoAfters); } /// - /// Variant of that performs several interactions using different entities. + /// Interact with an entity using the currently held entity. + /// + protected async Task Interact(EntityUid? target, EntityCoordinates coordinates, bool awaitDoAfters = true) + { + Assert.That(SEntMan.TryGetEntity(Player, out var player)); + + await Server.WaitPost(() => InteractSys.UserInteraction(player!.Value, coordinates, target)); + await RunTicks(1); + + if (awaitDoAfters) + await AwaitDoAfters(); + + await CheckTargetChange(); + } + + /// + /// Activate an entity. + /// + protected async Task Activate(NetEntity? target = null, bool awaitDoAfters = true) + { + target ??= Target; + Assert.That(target, Is.Not.Null); + Assert.That(SEntMan.TryGetEntity(target!.Value, out var sTarget)); + Assert.That(SEntMan.TryGetEntity(Player, out var player)); + + await Server.WaitPost(() => InteractSys.InteractionActivate(player!.Value, sTarget!.Value)); + await RunTicks(1); + + if (awaitDoAfters) + await AwaitDoAfters(); + + await CheckTargetChange(); + } + + /// + /// Variant of that performs several interactions using different entities. + /// Useful for quickly finishing multiple construction steps. /// /// /// Empty strings imply empty hands. @@ -318,7 +360,7 @@ public abstract partial class InteractionTest { foreach (var spec in specifiers) { - await Interact(spec); + await InteractUsing(spec); } } @@ -338,7 +380,7 @@ public abstract partial class InteractionTest /// /// Wait for any currently active DoAfters to finish. /// - protected async Task AwaitDoAfters(bool shouldSucceed = true, int maxExpected = 1) + protected async Task AwaitDoAfters(int maxExpected = 1) { if (!ActiveDoAfters.Any()) return; @@ -353,13 +395,12 @@ public abstract partial class InteractionTest await RunTicks(10); } - if (!shouldSucceed) - return; - foreach (var doAfter in doAfters) { Assert.That(!doAfter.Cancelled); } + + await RunTicks(5); } /// @@ -398,39 +439,28 @@ public abstract partial class InteractionTest /// Check if the test's target entity has changed. E.g., construction interactions will swap out entities while /// a structure is being built. /// - protected async Task CheckTargetChange(bool shouldSucceed) + protected async Task CheckTargetChange() { if (Target == null) return; - var target = Target.Value; + var originalTarget = Target.Value; await RunTicks(5); - if (ClientTarget != null && CEntMan.IsClientSide(ClientTarget.Value)) + if (Target.Value.IsClientSide() && CTestSystem.Ghosts.TryGetValue(ConstructionGhostId, out var newWeh)) { - Assert.That(CEntMan.Deleted(ClientTarget.Value), Is.EqualTo(shouldSucceed), - $"Construction ghost was {(shouldSucceed ? "not deleted" : "deleted")}."); - - if (shouldSucceed) - { - Assert.That(CTestSystem.Ghosts.TryGetValue(ConstructionGhostId, out var newWeh), - $"Failed to get construction entity from ghost Id"); - - await Client.WaitPost(() => CLogger.Debug($"Construction ghost {ConstructionGhostId} became entity {newWeh}")); - Target = newWeh; - } + CLogger.Debug($"Construction ghost {ConstructionGhostId} became entity {newWeh}"); + Target = newWeh; } if (STestSystem.EntChanges.TryGetValue(Target.Value, out var newServerWeh)) { - await Server.WaitPost( - () => SLogger.Debug($"Construction entity {Target.Value} changed to {newServerWeh}")); - + SLogger.Debug($"Construction entity {Target.Value} changed to {newServerWeh}"); Target = newServerWeh; } - if (Target != target) - await CheckTargetChange(shouldSucceed); + if (Target != originalTarget) + await CheckTargetChange(); } #region Asserts @@ -444,16 +474,10 @@ public abstract partial class InteractionTest return; } - var meta = SEntMan.GetComponent(SEntMan.GetEntity(target.Value)); + var meta = CEntMan.GetComponent(CEntMan.GetEntity(target.Value)); Assert.That(meta.EntityPrototype?.ID, Is.EqualTo(prototype)); } - protected void ClientAssertPrototype(string? prototype, EntityUid? target) - { - var netEnt = CTestSystem.Ghosts[target.GetHashCode()]; - AssertPrototype(prototype, netEnt); - } - protected void AssertPrototype(string? prototype, NetEntity? target = null) { target ??= Target; @@ -699,6 +723,8 @@ public abstract partial class InteractionTest protected IEnumerable ActiveDoAfters => DoAfters.DoAfters.Values.Where(x => !x.Cancelled && !x.Completed); + #region Component + /// /// Convenience method to get components on the target. Returns SERVER-SIDE components. /// @@ -708,9 +734,23 @@ public abstract partial class InteractionTest if (target == null) Assert.Fail("No target specified"); - return SEntMan.GetComponent(SEntMan.GetEntity(target!.Value)); + return SEntMan.GetComponent(ToServer(target!.Value)); } + /// + protected bool TryComp(NetEntity? target, [NotNullWhen(true)] out T? comp) where T : IComponent + { + return SEntMan.TryGetComponent(ToServer(target), out comp); + } + + /// + protected bool TryComp([NotNullWhen(true)] out T? comp) where T : IComponent + { + return SEntMan.TryGetComponent(STarget, out comp); + } + + #endregion + /// /// Set the tile at the target position to some prototype. /// @@ -833,23 +873,70 @@ public abstract partial class InteractionTest return true; } + protected bool IsUiOpen(Enum key) + { + if (!TryComp(Player, out UserInterfaceUserComponent? user)) + return false; + + foreach (var keys in user.OpenInterfaces.Values) + { + if (keys.Contains(key)) + return true; + } + + return false; + } + #endregion #region UI /// - /// Presses and releases a button on some client-side window. Will fail if the button cannot be found. + /// Attempts to find, and then presses and releases a control on some client-side window. + /// Will fail if the control cannot be found. /// - protected async Task ClickControl(string name) where TWindow : BaseWindow + protected async Task ClickControl(string name, BoundKeyFunction? function = null) + where TWindow : BaseWindow + where TControl : Control { - await ClickControl(GetControl(name)); + var window = GetWindow(); + var control = GetControlFromField(name, window); + await ClickControl(control, function); } /// - /// Simulates a click and release at the center of some UI Constrol. + /// Attempts to find, and then presses and releases a control on some client-side widget. + /// Will fail if the control cannot be found. /// - protected async Task ClickControl(Control control) + protected async Task ClickWidgetControl(string name, BoundKeyFunction? function = null) + where TWidget : UIWidget, new() + where TControl : Control { + var widget = GetWidget(); + var control = GetControlFromField(name, widget); + await ClickControl(control, function); + } + + /// + protected async Task ClickControl(string name, BoundKeyFunction? function = null) + where TWindow : BaseWindow + { + await ClickControl(name, function); + } + + /// + protected async Task ClickWidgetControl(string name, BoundKeyFunction? function = null) + where TWidget : UIWidget, new() + { + await ClickWidgetControl(name, function); + } + + /// + /// Simulates a click and release at the center of some UI control. + /// + protected async Task ClickControl(Control control, BoundKeyFunction? function = null) + { + function ??= EngineKeyFunctions.UIClick; var screenCoords = new ScreenCoordinates( control.GlobalPixelPosition + control.PixelSize / 2, control.Window?.Id ?? default); @@ -858,7 +945,7 @@ public abstract partial class InteractionTest var relativePixelPos = screenCoords.Position - control.GlobalPixelPosition; var args = new GUIBoundKeyEventArgs( - EngineKeyFunctions.UIClick, + function.Value, BoundKeyState.Down, screenCoords, default, @@ -869,7 +956,7 @@ public abstract partial class InteractionTest await RunTicks(1); args = new GUIBoundKeyEventArgs( - EngineKeyFunctions.UIClick, + function.Value, BoundKeyState.Up, screenCoords, default, @@ -881,31 +968,26 @@ public abstract partial class InteractionTest } /// - /// Attempts to find a control on some client-side window. Will fail if the control cannot be found. + /// Attempt to retrieve a control by looking for a field on some other control. /// - protected TControl GetControl(string name) - where TWindow : BaseWindow + /// + /// Will fail if the control cannot be found. + /// + protected TControl GetControlFromField(string name, Control parent) where TControl : Control - { - var control = GetControl(name); - Assert.That(control.GetType().IsAssignableTo(typeof(TControl))); - return (TControl) control; - } - - protected Control GetControl(string name) where TWindow : BaseWindow { const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; - var field = typeof(TWindow).GetField(name, flags); - var prop = typeof(TWindow).GetProperty(name, flags); + var parentType = parent.GetType(); + var field = parentType.GetField(name, flags); + var prop = parentType.GetProperty(name, flags); if (field == null && prop == null) { - Assert.Fail($"Window {typeof(TWindow).Name} does not have a field or property named {name}"); + Assert.Fail($"Window {parentType.Name} does not have a field or property named {name}"); return default!; } - var window = GetWindow(); - var fieldOrProp = field?.GetValue(window) ?? prop?.GetValue(window); + var fieldOrProp = field?.GetValue(parent) ?? prop?.GetValue(parent); if (fieldOrProp is not Control control) { @@ -913,7 +995,59 @@ public abstract partial class InteractionTest return default!; } - return control; + Assert.That(control.GetType().IsAssignableTo(typeof(TControl))); + return (TControl) control; + } + + /// + /// Attempt to retrieve a control that matches some predicate by iterating through a control's children. + /// + /// + /// Will fail if the control cannot be found. + /// + protected TControl GetControlFromChildren(Func predicate, Control parent, bool recursive = true) + where TControl : Control + { + if (TryGetControlFromChildren(predicate, parent, out var control, recursive)) + return control; + + Assert.Fail($"Failed to find a {nameof(TControl)} that satisfies the predicate in {parent.Name}"); + return default!; + } + + /// + /// Attempt to retrieve a control of a given type by iterating through a control's children. + /// + protected TControl GetControlFromChildren(Control parent, bool recursive = false) + where TControl : Control + { + return GetControlFromChildren(static _ => true, parent, recursive); + } + + /// + /// Attempt to retrieve a control that matches some predicate by iterating through a control's children. + /// + protected bool TryGetControlFromChildren( + Func predicate, + Control parent, + [NotNullWhen(true)] out TControl? control, + bool recursive = true) + where TControl : Control + { + foreach (var ctrl in parent.Children) + { + if (ctrl is TControl cast && predicate(cast)) + { + control = cast; + return true; + } + + if (recursive && TryGetControlFromChildren(predicate, ctrl, out control)) + return true; + } + + control = null; + return false; } /// @@ -944,7 +1078,6 @@ public abstract partial class InteractionTest return window != null; } - /// /// Attempts to find a currently open client-side window. /// @@ -962,6 +1095,34 @@ public abstract partial class InteractionTest return window != null; } + + /// + /// Attempts to find client-side UI widget. + /// + protected UIWidget GetWidget() + where TWidget : UIWidget, new() + { + if (TryFindWidget(out TWidget? widget)) + return widget; + + Assert.Fail($"Could not find a {typeof(TWidget).Name} widget"); + return default!; + } + + /// + /// Attempts to find client-side UI widget. + /// + private bool TryFindWidget([NotNullWhen(true)] out TWidget? uiWidget) + where TWidget : UIWidget, new() + { + uiWidget = null; + var screen = UiMan.ActiveScreen; + if (screen == null) + return false; + + return screen.TryGetWidget(out uiWidget); + } + #endregion #region Power diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs index e5f794feaa..089addfaef 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs @@ -1,8 +1,10 @@ #nullable enable +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; using Content.Client.Construction; using Content.Client.Examine; +using Content.Client.Gameplay; using Content.IntegrationTests.Pair; using Content.Server.Body.Systems; using Content.Server.Hands.Systems; @@ -24,6 +26,7 @@ using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.UnitTesting; using Content.Shared.Item.ItemToggle; +using Robust.Client.State; namespace Content.IntegrationTests.Tests.Interaction; @@ -64,15 +67,12 @@ public abstract partial class InteractionTest /// The player entity that performs all these interactions. Defaults to an admin-observer with 1 hand. /// protected NetEntity Player; - - protected EntityUid SPlayer => ToServer(Player); - protected EntityUid CPlayer => ToClient(Player); + protected EntityUid SPlayer; + protected EntityUid CPlayer; protected ICommonSession ClientSession = default!; protected ICommonSession ServerSession = default!; - public EntityUid? ClientTarget; - /// /// The current target entity. This is the default entity for various helper functions. /// @@ -108,6 +108,7 @@ public abstract partial class InteractionTest protected InteractionTestSystem STestSystem = default!; protected SharedTransformSystem Transform = default!; protected ISawmill SLogger = default!; + protected SharedUserInterfaceSystem SUiSys = default!; // CLIENT dependencies protected IEntityManager CEntMan = default!; @@ -119,6 +120,7 @@ public abstract partial class InteractionTest protected ExamineSystem ExamineSys = default!; protected InteractionTestSystem CTestSystem = default!; protected ISawmill CLogger = default!; + protected SharedUserInterfaceSystem CUiSys = default!; // player components protected HandsComponent Hands = default!; @@ -168,6 +170,7 @@ public abstract partial class InteractionTest STestSystem = SEntMan.System(); Stack = SEntMan.System(); SLogger = Server.ResolveDependency().RootSawmill; + SUiSys = Client.System(); // client dependencies CEntMan = Client.ResolveDependency(); @@ -179,6 +182,7 @@ public abstract partial class InteractionTest CConSys = CEntMan.System(); ExamineSys = CEntMan.System(); CLogger = Client.ResolveDependency().RootSawmill; + CUiSys = Client.System(); // Setup map. await Pair.CreateTestMap(); @@ -204,15 +208,16 @@ public abstract partial class InteractionTest old = cPlayerMan.LocalEntity; Player = SEntMan.GetNetEntity(SEntMan.SpawnEntity(PlayerPrototype, SEntMan.GetCoordinates(PlayerCoords))); - var serverPlayerEnt = SEntMan.GetEntity(Player); - Server.PlayerMan.SetAttachedEntity(ServerSession, serverPlayerEnt); - Hands = SEntMan.GetComponent(serverPlayerEnt); - DoAfters = SEntMan.GetComponent(serverPlayerEnt); + SPlayer = SEntMan.GetEntity(Player); + Server.PlayerMan.SetAttachedEntity(ServerSession, SPlayer); + Hands = SEntMan.GetComponent(SPlayer); + DoAfters = SEntMan.GetComponent(SPlayer); }); // Check player got attached. await RunTicks(5); - Assert.That(CEntMan.GetNetEntity(cPlayerMan.LocalEntity), Is.EqualTo(Player)); + CPlayer = ToClient(Player); + Assert.That(cPlayerMan.LocalEntity, Is.EqualTo(CPlayer)); // Delete old player entity. await Server.WaitPost(() => @@ -235,6 +240,10 @@ public abstract partial class InteractionTest } }); + // Change UI state to in-game. + var state = Client.ResolveDependency(); + await Client.WaitPost(() => state.RequestStateChange()); + // Final player asserts/checks. await Pair.ReallyBeIdle(5); Assert.Multiple(() => diff --git a/Content.IntegrationTests/Tests/Payload/ModularGrenadeTests.cs b/Content.IntegrationTests/Tests/Payload/ModularGrenadeTests.cs index 70179fdec1..4db79373d3 100644 --- a/Content.IntegrationTests/Tests/Payload/ModularGrenadeTests.cs +++ b/Content.IntegrationTests/Tests/Payload/ModularGrenadeTests.cs @@ -22,32 +22,32 @@ public sealed class ModularGrenadeTests : InteractionTest Target = SEntMan.GetNetEntity(await FindEntity("ModularGrenade")); await Drop(); - await Interact(Cable); + await InteractUsing(Cable); // Insert & remove trigger AssertComp(false); - await Interact(Trigger); + await InteractUsing(Trigger); AssertComp(); await FindEntity(Trigger, LookupFlags.Uncontained, shouldSucceed: false); - await Interact(Pry); + await InteractUsing(Pry); AssertComp(false); // Trigger was dropped to floor, not deleted. await FindEntity(Trigger, LookupFlags.Uncontained); // Re-insert - await Interact(Trigger); + await InteractUsing(Trigger); AssertComp(); // Insert & remove payload. - await Interact(Payload); + await InteractUsing(Payload); await FindEntity(Payload, LookupFlags.Uncontained, shouldSucceed: false); - await Interact(Pry); + await InteractUsing(Pry); var ent = await FindEntity(Payload, LookupFlags.Uncontained); await Delete(ent); // successfully insert a second time - await Interact(Payload); + await InteractUsing(Payload); ent = await FindEntity(Payload); var sys = SEntMan.System(); Assert.That(sys.IsEntityInContainer(ent)); diff --git a/Content.IntegrationTests/Tests/Storage/StorageInteractionTest.cs b/Content.IntegrationTests/Tests/Storage/StorageInteractionTest.cs new file mode 100644 index 0000000000..34402dd5e6 --- /dev/null +++ b/Content.IntegrationTests/Tests/Storage/StorageInteractionTest.cs @@ -0,0 +1,75 @@ +using Content.Client.UserInterface.Systems.Hotbar.Widgets; +using Content.Client.UserInterface.Systems.Storage.Controls; +using Content.IntegrationTests.Tests.Interaction; +using Content.Shared.Input; +using Content.Shared.PDA; +using Content.Shared.Storage; +using Robust.Client.UserInterface; +using Robust.Shared.Containers; +using Robust.Shared.GameObjects; + +namespace Content.IntegrationTests.Tests.Storage; + +public sealed class StorageInteractionTest : InteractionTest +{ + /// + /// Check that players can interact with items in storage if the storage UI is open + /// + [Test] + public async Task UiInteractTest() + { + var sys = Server.System(); + + await SpawnTarget("ClothingBackpack"); + var backpack = ToServer(Target); + + // Initially no BUI is open. + Assert.That(IsUiOpen(StorageComponent.StorageUiKey.Key), Is.False); + Assert.That(IsUiOpen(PdaUiKey.Key), Is.False); + + // Activating the backpack opens the UI + await Activate(); + Assert.That(IsUiOpen(StorageComponent.StorageUiKey.Key), Is.True); + Assert.That(IsUiOpen(PdaUiKey.Key), Is.False); + + // Pick up a PDA + var pda = await PlaceInHands("PassengerPDA"); + var sPda = ToServer(pda); + Assert.That(sys.IsEntityInContainer(sPda), Is.True); + Assert.That(sys.TryGetContainingContainer((sPda, null), out var container)); + Assert.That(container!.Owner, Is.EqualTo(SPlayer)); + + // Insert the PDA into the backpack + await Interact(); + Assert.That(sys.TryGetContainingContainer((sPda, null), out container)); + Assert.That(container!.Owner, Is.EqualTo(backpack)); + + // Use "e" / ActivateInWorld to open the PDA UI while it is still in the backpack. + var ctrl = GetStorageControl(pda); + await ClickControl(ctrl, ContentKeyFunctions.ActivateItemInWorld); + await RunTicks(10); + Assert.That(IsUiOpen(StorageComponent.StorageUiKey.Key), Is.True); + Assert.That(IsUiOpen(PdaUiKey.Key), Is.True); + + // Click on the pda to pick it up and remove it from the backpack. + await ClickControl(ctrl, ContentKeyFunctions.MoveStoredItem); + await RunTicks(10); + Assert.That(sys.TryGetContainingContainer((sPda, null), out container)); + Assert.That(container!.Owner, Is.EqualTo(SPlayer)); + + // UIs should still be open + Assert.That(IsUiOpen(StorageComponent.StorageUiKey.Key), Is.True); + Assert.That(IsUiOpen(PdaUiKey.Key), Is.True); + } + + /// + /// Retrieve the control that corresponds to the given entity in the currently open storage UI. + /// + private ItemGridPiece GetStorageControl(NetEntity target) + { + var uid = ToClient(target); + var hotbar = GetWidget(); + var storageContainer = GetControlFromField(nameof(HotbarGui.StorageContainer), hotbar); + return GetControlFromChildren(c => c.Entity == uid, storageContainer); + } +} diff --git a/Content.IntegrationTests/Tests/Tiles/TileConstructionTests.cs b/Content.IntegrationTests/Tests/Tiles/TileConstructionTests.cs index 083e817d69..6ea8b6882a 100644 --- a/Content.IntegrationTests/Tests/Tiles/TileConstructionTests.cs +++ b/Content.IntegrationTests/Tests/Tiles/TileConstructionTests.cs @@ -15,10 +15,10 @@ public sealed class TileConstructionTests : InteractionTest await AssertTile(Plating, PlayerCoords); AssertGridCount(1); await SetTile(null); - await Interact(Rod); + await InteractUsing(Rod); await AssertTile(Lattice); Assert.That(Hands.ActiveHandEntity, Is.Null); - await Interact(Cut); + await InteractUsing(Cut); await AssertTile(null); await AssertEntityLookup((Rod, 1)); AssertGridCount(1); @@ -43,14 +43,14 @@ public sealed class TileConstructionTests : InteractionTest // Place Lattice var oldPos = TargetCoords; TargetCoords = SEntMan.GetNetCoordinates(new EntityCoordinates(MapData.MapUid, 1, 0)); - await Interact(Rod); + await InteractUsing(Rod); TargetCoords = oldPos; await AssertTile(Lattice); AssertGridCount(1); // Cut lattice Assert.That(Hands.ActiveHandEntity, Is.Null); - await Interact(Cut); + await InteractUsing(Cut); await AssertTile(null); AssertGridCount(0); @@ -76,25 +76,25 @@ public sealed class TileConstructionTests : InteractionTest // Space -> Lattice var oldPos = TargetCoords; TargetCoords = SEntMan.GetNetCoordinates(new EntityCoordinates(MapData.MapUid, 1, 0)); - await Interact(Rod); + await InteractUsing(Rod); TargetCoords = oldPos; await AssertTile(Lattice); AssertGridCount(1); // Lattice -> Plating - await Interact(Steel); + await InteractUsing(Steel); Assert.That(Hands.ActiveHandEntity, Is.Null); await AssertTile(Plating); AssertGridCount(1); // Plating -> Tile - await Interact(FloorItem); + await InteractUsing(FloorItem); Assert.That(Hands.ActiveHandEntity, Is.Null); await AssertTile(Floor); AssertGridCount(1); // Tile -> Plating - await Interact(Pry); + await InteractUsing(Pry); await AssertTile(Plating); AssertGridCount(1); diff --git a/Content.IntegrationTests/Tests/Weldable/WeldableTests.cs b/Content.IntegrationTests/Tests/Weldable/WeldableTests.cs index 6227f3dee1..e7eadeda0a 100644 --- a/Content.IntegrationTests/Tests/Weldable/WeldableTests.cs +++ b/Content.IntegrationTests/Tests/Weldable/WeldableTests.cs @@ -18,7 +18,7 @@ public sealed class WeldableTests : InteractionTest Assert.That(comp.IsWelded, Is.False); - await Interact(Weld); + await InteractUsing(Weld); Assert.That(comp.IsWelded, Is.True); AssertPrototype(Locker); // Prototype did not change. } From 2bd4f859661f0cbe9d7c357e9038f2671460c443 Mon Sep 17 00:00:00 2001 From: Verm <32827189+Vermidia@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:07:41 -0500 Subject: [PATCH 50/63] Fix Weh Juice and Other emote chems not working (#28562) --- Content.Server/Chat/Systems/ChatSystem.Emote.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Chat/Systems/ChatSystem.Emote.cs b/Content.Server/Chat/Systems/ChatSystem.Emote.cs index 23e1517d75..5897aac61a 100644 --- a/Content.Server/Chat/Systems/ChatSystem.Emote.cs +++ b/Content.Server/Chat/Systems/ChatSystem.Emote.cs @@ -81,7 +81,7 @@ public partial class ChatSystem bool ignoreActionBlocker = false ) { - if (_whitelistSystem.IsWhitelistFailOrNull(emote.Whitelist, source) || _whitelistSystem.IsBlacklistPass(emote.Blacklist, source)) + if (_whitelistSystem.IsWhitelistFail(emote.Whitelist, source) || _whitelistSystem.IsBlacklistPass(emote.Blacklist, source)) return; if (!emote.Available && From c5ff647ca6257862cfd391926470694f909759f4 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:40:03 -0700 Subject: [PATCH 51/63] Replace obsolete EntityWhitelist IsValid usages part 2 (#28506) --- Content.Client/Outline/TargetOutlineSystem.cs | 3 ++- Content.Server/Chat/Systems/ChatSystem.Emote.cs | 1 + .../TileReactions/CreateEntityTileReaction.cs | 5 +++-- .../Construction/ConstructionSystem.Initial.cs | 6 ++++-- .../GameTicking/Rules/LoadMapRuleSystem.cs | 4 +++- .../VariationPass/CutWireVariationPassSystem.cs | 5 ++++- .../Holiday/Christmas/RandomGiftSystem.cs | 6 ++++-- .../Mech/Systems/MechEquipmentSystem.cs | 4 +++- Content.Server/Mech/Systems/MechSystem.cs | 4 +++- .../Ninja/Systems/StunProviderSystem.cs | 4 +++- .../EntitySystems/AnimalHusbandrySystem.cs | 6 ++++-- .../Nutrition/EntitySystems/FoodSystem.cs | 4 +++- .../ObjectiveBlacklistRequirementSystem.cs | 5 ++++- .../Objectives/Systems/RoleRequirementSystem.cs | 4 +++- .../Polymorph/Systems/PolymorphSystem.Collide.cs | 7 +++++-- Content.Server/Sticky/Systems/StickySystem.cs | 7 ++++--- .../Storage/EntitySystems/ItemCounterSystem.cs | 6 ++++-- .../Store/Conditions/BuyerWhitelistCondition.cs | 15 ++++----------- .../Store/Conditions/StoreWhitelistCondition.cs | 15 ++++----------- .../Systems/SurveillanceCameraMicrophoneSystem.cs | 5 +++-- Content.Server/Traits/TraitSystem.cs | 8 ++++---- .../Equipment/Systems/ArtifactCrusherSystem.cs | 4 +++- .../Effects/Systems/DamageNearbyArtifactSystem.cs | 6 ++++-- Content.Shared/Actions/SharedActionsSystem.cs | 4 +++- .../Buckle/SharedBuckleSystem.Buckle.cs | 7 +++++-- .../Conditions/EntityWhitelistCondition.cs | 3 ++- Content.Shared/Inventory/InventorySystem.Equip.cs | 11 ++++------- .../EntitySystems/SharedHandLabelerSystem.cs | 6 ++++-- .../Materials/SharedMaterialReclaimerSystem.cs | 8 ++++---- .../Mech/EntitySystems/SharedMechSystem.cs | 4 +++- .../Systems/SpeedModifierContactsSystem.cs | 4 +++- .../Ninja/Systems/EmagProviderSystem.cs | 3 ++- Content.Shared/Placeable/ItemPlacerSystem.cs | 6 ++++-- Content.Shared/Random/RulesSystem.cs | 5 +++-- Content.Shared/Sound/SharedEmitSoundSystem.cs | 4 +++- .../StepTrigger/Systems/StepTriggerSystem.cs | 4 +++- Content.Shared/Storage/EntitySystems/BinSystem.cs | 6 ++++-- .../EntitySystems/SharedItemMapperSystem.cs | 6 ++++-- .../Teleportation/Systems/SwapTeleporterSystem.cs | 6 ++++-- .../UserInterface/ActivatableUISystem.cs | 6 ++++-- .../Ranged/Systems/SharedGunSystem.Ballistic.cs | 3 ++- .../Ranged/Systems/SharedGunSystem.Clothing.cs | 2 +- 42 files changed, 141 insertions(+), 91 deletions(-) diff --git a/Content.Client/Outline/TargetOutlineSystem.cs b/Content.Client/Outline/TargetOutlineSystem.cs index 2a6867f51f..df57578b1f 100644 --- a/Content.Client/Outline/TargetOutlineSystem.cs +++ b/Content.Client/Outline/TargetOutlineSystem.cs @@ -22,6 +22,7 @@ public sealed class TargetOutlineSystem : EntitySystem [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; private bool _enabled = false; @@ -137,7 +138,7 @@ public sealed class TargetOutlineSystem : EntitySystem // check the entity whitelist if (valid && Whitelist != null) - valid = Whitelist.IsValid(entity); + valid = _whitelistSystem.IsWhitelistPass(Whitelist, entity); // and check the cancellable event if (valid && ValidationEvent != null) diff --git a/Content.Server/Chat/Systems/ChatSystem.Emote.cs b/Content.Server/Chat/Systems/ChatSystem.Emote.cs index 5897aac61a..20a4f18746 100644 --- a/Content.Server/Chat/Systems/ChatSystem.Emote.cs +++ b/Content.Server/Chat/Systems/ChatSystem.Emote.cs @@ -81,6 +81,7 @@ public partial class ChatSystem bool ignoreActionBlocker = false ) { + if (_whitelistSystem.IsWhitelistFail(emote.Whitelist, source) || _whitelistSystem.IsBlacklistPass(emote.Blacklist, source)) return; diff --git a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs index 29f9275bdf..6b106b1fc0 100644 --- a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs @@ -1,4 +1,4 @@ -using Content.Shared.Chemistry.Reaction; +using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Content.Shared.Maps; @@ -47,7 +47,8 @@ public sealed partial class CreateEntityTileReaction : ITileReaction int acc = 0; foreach (var ent in tile.GetEntitiesInTile()) { - if (Whitelist.IsValid(ent)) + var whitelistSystem = entityManager.System(); + if (whitelistSystem.IsWhitelistPass(Whitelist, ent)) acc += 1; if (acc >= MaxOnTile) diff --git a/Content.Server/Construction/ConstructionSystem.Initial.cs b/Content.Server/Construction/ConstructionSystem.Initial.cs index 04d3722c66..5161ac358a 100644 --- a/Content.Server/Construction/ConstructionSystem.Initial.cs +++ b/Content.Server/Construction/ConstructionSystem.Initial.cs @@ -14,6 +14,7 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Inventory; using Content.Shared.Storage; +using Content.Shared.Whitelist; using Robust.Shared.Containers; using Robust.Shared.Map; using Robust.Shared.Player; @@ -30,6 +31,7 @@ namespace Content.Server.Construction [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly EntityLookupSystem _lookupSystem = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; // --- WARNING! LEGACY CODE AHEAD! --- // This entire file contains the legacy code for initial construction. @@ -337,7 +339,7 @@ namespace Content.Server.Construction return false; } - if (constructionPrototype.EntityWhitelist != null && !constructionPrototype.EntityWhitelist.IsValid(user)) + if (_whitelistSystem.IsWhitelistFail(constructionPrototype.EntityWhitelist, user)) { _popup.PopupEntity(Loc.GetString("construction-system-cannot-start"), user, user); return false; @@ -422,7 +424,7 @@ namespace Content.Server.Construction return; } - if (constructionPrototype.EntityWhitelist != null && !constructionPrototype.EntityWhitelist.IsValid(user)) + if (_whitelistSystem.IsWhitelistFail(constructionPrototype.EntityWhitelist, user)) { _popup.PopupEntity(Loc.GetString("construction-system-cannot-start"), user, user); return; diff --git a/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs b/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs index 3a80d82fd9..c60cf2513e 100644 --- a/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs @@ -3,6 +3,7 @@ using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.GridPreloader; using Content.Server.Spawners.Components; +using Content.Shared.Whitelist; using Robust.Server.GameObjects; using Robust.Server.Maps; using Robust.Shared.Map; @@ -19,6 +20,7 @@ public sealed class LoadMapRuleSystem : GameRuleSystem [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly GridPreloaderSystem _gridPreloader = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -99,7 +101,7 @@ public sealed class LoadMapRuleSystem : GameRuleSystem if (xform.GridUid == null || !ent.Comp.MapGrids.Contains(xform.GridUid.Value)) continue; - if (ent.Comp.SpawnerWhitelist != null && !ent.Comp.SpawnerWhitelist.IsValid(uid, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(ent.Comp.SpawnerWhitelist, uid)) continue; args.Coordinates.Add(_transform.GetMapCoordinates(xform)); diff --git a/Content.Server/GameTicking/Rules/VariationPass/CutWireVariationPassSystem.cs b/Content.Server/GameTicking/Rules/VariationPass/CutWireVariationPassSystem.cs index fd94c74ac8..372de4bbb4 100644 --- a/Content.Server/GameTicking/Rules/VariationPass/CutWireVariationPassSystem.cs +++ b/Content.Server/GameTicking/Rules/VariationPass/CutWireVariationPassSystem.cs @@ -1,5 +1,6 @@ using Content.Server.GameTicking.Rules.VariationPass.Components; using Content.Server.Wires; +using Content.Shared.Whitelist; using Robust.Shared.Random; namespace Content.Server.GameTicking.Rules.VariationPass; @@ -11,6 +12,8 @@ namespace Content.Server.GameTicking.Rules.VariationPass; /// public sealed class CutWireVariationPassSystem : VariationPassSystem { + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + protected override void ApplyVariation(Entity ent, ref StationVariationPassEvent args) { var wiresCut = 0; @@ -22,7 +25,7 @@ public sealed class CutWireVariationPassSystem : VariationPassSystem _possibleGiftsSafe = new(); private readonly List _possibleGiftsUnsafe = new(); @@ -40,7 +42,7 @@ public sealed class RandomGiftSystem : EntitySystem private void OnExamined(EntityUid uid, RandomGiftComponent component, ExaminedEvent args) { - if (!component.ContentsViewers.IsValid(args.Examiner, EntityManager) || component.SelectedEntity is null) + if (_whitelistSystem.IsWhitelistFail(component.ContentsViewers, args.Examiner) || component.SelectedEntity is null) return; var name = _prototype.Index(component.SelectedEntity).Name; diff --git a/Content.Server/Mech/Systems/MechEquipmentSystem.cs b/Content.Server/Mech/Systems/MechEquipmentSystem.cs index f51c0444e6..f9fe5e4641 100644 --- a/Content.Server/Mech/Systems/MechEquipmentSystem.cs +++ b/Content.Server/Mech/Systems/MechEquipmentSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.DoAfter; using Content.Shared.Interaction; using Content.Shared.Mech.Components; using Content.Shared.Mech.Equipment.Components; +using Content.Shared.Whitelist; namespace Content.Server.Mech.Systems; @@ -14,6 +15,7 @@ public sealed class MechEquipmentSystem : EntitySystem [Dependency] private readonly MechSystem _mech = default!; [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; /// public override void Initialize() @@ -40,7 +42,7 @@ public sealed class MechEquipmentSystem : EntitySystem if (mechComp.EquipmentContainer.ContainedEntities.Count >= mechComp.MaxEquipmentAmount) return; - if (mechComp.EquipmentWhitelist != null && !mechComp.EquipmentWhitelist.IsValid(args.Used)) + if (_whitelistSystem.IsWhitelistFail(mechComp.EquipmentWhitelist, args.Used)) return; _popup.PopupEntity(Loc.GetString("mech-equipment-begin-install", ("item", uid)), mech); diff --git a/Content.Server/Mech/Systems/MechSystem.cs b/Content.Server/Mech/Systems/MechSystem.cs index 68b973f588..b738d28b46 100644 --- a/Content.Server/Mech/Systems/MechSystem.cs +++ b/Content.Server/Mech/Systems/MechSystem.cs @@ -22,6 +22,7 @@ using Robust.Server.Containers; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.Player; +using Content.Shared.Whitelist; namespace Content.Server.Mech.Systems; @@ -36,6 +37,7 @@ public sealed partial class MechSystem : SharedMechSystem [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; [Dependency] private readonly SharedToolSystem _toolSystem = default!; /// @@ -224,7 +226,7 @@ public sealed partial class MechSystem : SharedMechSystem if (args.Cancelled || args.Handled) return; - if (component.PilotWhitelist != null && !component.PilotWhitelist.IsValid(args.User)) + if (_whitelistSystem.IsWhitelistFail(component.PilotWhitelist, args.User)) { _popup.PopupEntity(Loc.GetString("mech-no-enter", ("item", uid)), args.User); return; diff --git a/Content.Server/Ninja/Systems/StunProviderSystem.cs b/Content.Server/Ninja/Systems/StunProviderSystem.cs index 970ca78e2c..1768606ad2 100644 --- a/Content.Server/Ninja/Systems/StunProviderSystem.cs +++ b/Content.Server/Ninja/Systems/StunProviderSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.Stunnable; using Robust.Shared.Prototypes; using Robust.Shared.Audio.Systems; using Robust.Shared.Timing; +using Content.Shared.Whitelist; namespace Content.Server.Ninja.Systems; @@ -24,6 +25,7 @@ public sealed class StunProviderSystem : SharedStunProviderSystem [Dependency] private readonly SharedNinjaGlovesSystem _gloves = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -42,7 +44,7 @@ public sealed class StunProviderSystem : SharedStunProviderSystem if (args.Handled || comp.BatteryUid == null || !_gloves.AbilityCheck(uid, args, out var target)) return; - if (target == uid || !comp.Whitelist.IsValid(target, EntityManager)) + if (target == uid || _whitelistSystem.IsWhitelistFail(comp.Whitelist, target)) return; if (_timing.CurTime < comp.NextStun) diff --git a/Content.Server/Nutrition/EntitySystems/AnimalHusbandrySystem.cs b/Content.Server/Nutrition/EntitySystems/AnimalHusbandrySystem.cs index cd05413405..e224c7c479 100644 --- a/Content.Server/Nutrition/EntitySystems/AnimalHusbandrySystem.cs +++ b/Content.Server/Nutrition/EntitySystems/AnimalHusbandrySystem.cs @@ -1,4 +1,4 @@ -using Content.Server.Administration.Logs; +using Content.Server.Administration.Logs; using Content.Server.Popups; using Content.Shared.Database; using Content.Shared.IdentityManagement; @@ -9,6 +9,7 @@ using Content.Shared.Nutrition.AnimalHusbandry; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Storage; +using Content.Shared.Whitelist; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; @@ -33,6 +34,7 @@ public sealed class AnimalHusbandrySystem : EntitySystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; private readonly HashSet _failedAttempts = new(); private readonly HashSet _birthQueue = new(); @@ -174,7 +176,7 @@ public sealed class AnimalHusbandrySystem : EntitySystem if (!CanReproduce(partner)) return false; - return component.PartnerWhitelist.IsValid(partner); + return _whitelistSystem.IsWhitelistPass(component.PartnerWhitelist, partner); } /// diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs index 2c7632aadc..1862b4e19f 100644 --- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs @@ -32,6 +32,7 @@ using Robust.Shared.Audio.Systems; using Robust.Shared.Utility; using System.Linq; using Robust.Server.GameObjects; +using Content.Shared.Whitelist; namespace Content.Server.Nutrition.EntitySystems; @@ -57,6 +58,7 @@ public sealed class FoodSystem : EntitySystem [Dependency] private readonly StackSystem _stack = default!; [Dependency] private readonly StomachSystem _stomach = default!; [Dependency] private readonly UtensilSystem _utensil = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public const float MaxFeedDistance = 1.0f; @@ -408,7 +410,7 @@ public sealed class FoodSystem : EntitySystem if (comp.SpecialDigestible == null) continue; // Check if the food is in the whitelist - if (comp.SpecialDigestible.IsValid(food, EntityManager)) + if (_whitelistSystem.IsWhitelistPass(comp.SpecialDigestible, food)) return true; // They can only eat whitelist food and the food isn't in the whitelist. It's not edible. return false; diff --git a/Content.Server/Objectives/Systems/ObjectiveBlacklistRequirementSystem.cs b/Content.Server/Objectives/Systems/ObjectiveBlacklistRequirementSystem.cs index 56b245ce84..8fe7e7e203 100644 --- a/Content.Server/Objectives/Systems/ObjectiveBlacklistRequirementSystem.cs +++ b/Content.Server/Objectives/Systems/ObjectiveBlacklistRequirementSystem.cs @@ -1,5 +1,6 @@ using Content.Server.Objectives.Components; using Content.Shared.Objectives.Components; +using Content.Shared.Whitelist; namespace Content.Server.Objectives.Systems; @@ -8,6 +9,8 @@ namespace Content.Server.Objectives.Systems; /// public sealed class ObjectiveBlacklistRequirementSystem : EntitySystem { + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + public override void Initialize() { base.Initialize(); @@ -22,7 +25,7 @@ public sealed class ObjectiveBlacklistRequirementSystem : EntitySystem foreach (var objective in args.Mind.AllObjectives) { - if (comp.Blacklist.IsValid(objective, EntityManager)) + if (_whitelistSystem.IsBlacklistPass(comp.Blacklist, objective)) { args.Cancelled = true; return; diff --git a/Content.Server/Objectives/Systems/RoleRequirementSystem.cs b/Content.Server/Objectives/Systems/RoleRequirementSystem.cs index 97aee218f0..8421987bae 100644 --- a/Content.Server/Objectives/Systems/RoleRequirementSystem.cs +++ b/Content.Server/Objectives/Systems/RoleRequirementSystem.cs @@ -1,5 +1,6 @@ using Content.Server.Objectives.Components; using Content.Shared.Objectives.Components; +using Content.Shared.Whitelist; namespace Content.Server.Objectives.Systems; @@ -8,6 +9,7 @@ namespace Content.Server.Objectives.Systems; /// public sealed class RoleRequirementSystem : EntitySystem { + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { base.Initialize(); @@ -22,7 +24,7 @@ public sealed class RoleRequirementSystem : EntitySystem // this whitelist trick only works because roles are components on the mind and not entities // if that gets reworked then this will need changing - if (!comp.Roles.IsValid(args.MindId, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(comp.Roles, args.MindId)) args.Cancelled = true; } } diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs index b4240d409a..b29f46e09e 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs @@ -1,6 +1,7 @@ using Content.Server.Polymorph.Components; using Content.Shared.Polymorph; using Content.Shared.Projectiles; +using Content.Shared.Whitelist; using Robust.Shared.Audio; using Robust.Shared.Physics.Events; using Robust.Shared.Prototypes; @@ -9,6 +10,8 @@ namespace Content.Server.Polymorph.Systems; public partial class PolymorphSystem { + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + /// /// Need to do this so we don't get a collection enumeration error in physics by polymorphing /// an entity we're colliding with @@ -39,8 +42,8 @@ public partial class PolymorphSystem return; var other = args.OtherEntity; - if (!component.Whitelist.IsValid(other, EntityManager) - || component.Blacklist != null && component.Blacklist.IsValid(other, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(component.Whitelist, other) || + _whitelistSystem.IsBlacklistPass(component.Blacklist, other)) return; _queuedPolymorphUpdates.Enqueue(new (other, component.Sound, component.Polymorph)); diff --git a/Content.Server/Sticky/Systems/StickySystem.cs b/Content.Server/Sticky/Systems/StickySystem.cs index effe1b72f7..21a7f4d039 100644 --- a/Content.Server/Sticky/Systems/StickySystem.cs +++ b/Content.Server/Sticky/Systems/StickySystem.cs @@ -7,6 +7,7 @@ using Content.Shared.Interaction; using Content.Shared.Sticky; using Content.Shared.Sticky.Components; using Content.Shared.Verbs; +using Content.Shared.Whitelist; using Robust.Shared.Containers; using Robust.Shared.Utility; @@ -20,6 +21,7 @@ public sealed class StickySystem : EntitySystem [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; private const string StickerSlotId = "stickers_container"; @@ -67,9 +69,8 @@ public sealed class StickySystem : EntitySystem return false; // check whitelist and blacklist - if (component.Whitelist != null && !component.Whitelist.IsValid(target)) - return false; - if (component.Blacklist != null && component.Blacklist.IsValid(target)) + if (_whitelistSystem.IsWhitelistFail(component.Whitelist, target) || + _whitelistSystem.IsBlacklistPass(component.Blacklist, target)) return false; var attemptEv = new AttemptEntityStickEvent(target, user); diff --git a/Content.Server/Storage/EntitySystems/ItemCounterSystem.cs b/Content.Server/Storage/EntitySystems/ItemCounterSystem.cs index 415e8d9246..43fcb32d1f 100644 --- a/Content.Server/Storage/EntitySystems/ItemCounterSystem.cs +++ b/Content.Server/Storage/EntitySystems/ItemCounterSystem.cs @@ -1,6 +1,7 @@ -using Content.Shared.Storage; +using Content.Shared.Storage; using Content.Shared.Storage.Components; using Content.Shared.Storage.EntitySystems; +using Content.Shared.Whitelist; using JetBrains.Annotations; using Robust.Shared.Containers; @@ -9,6 +10,7 @@ namespace Content.Server.Storage.EntitySystems [UsedImplicitly] public sealed class ItemCounterSystem : SharedItemCounterSystem { + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; protected override int? GetCount(ContainerModifiedMessage msg, ItemCounterComponent itemCounter) { if (!EntityManager.TryGetComponent(msg.Container.Owner, out StorageComponent? component)) @@ -19,7 +21,7 @@ namespace Content.Server.Storage.EntitySystems var count = 0; foreach (var entity in component.Container.ContainedEntities) { - if (itemCounter.Count.IsValid(entity)) + if (_whitelistSystem.IsWhitelistPass(itemCounter.Count, entity)) count++; } diff --git a/Content.Server/Store/Conditions/BuyerWhitelistCondition.cs b/Content.Server/Store/Conditions/BuyerWhitelistCondition.cs index 859703a72a..ff4a9a19cd 100644 --- a/Content.Server/Store/Conditions/BuyerWhitelistCondition.cs +++ b/Content.Server/Store/Conditions/BuyerWhitelistCondition.cs @@ -23,18 +23,11 @@ public sealed partial class BuyerWhitelistCondition : ListingCondition public override bool Condition(ListingConditionArgs args) { var ent = args.EntityManager; + var whitelistSystem = ent.System(); - if (Whitelist != null) - { - if (!Whitelist.IsValid(args.Buyer, ent)) - return false; - } - - if (Blacklist != null) - { - if (Blacklist.IsValid(args.Buyer, ent)) - return false; - } + if (whitelistSystem.IsWhitelistFail(Whitelist, args.Buyer) || + whitelistSystem.IsBlacklistPass(Blacklist, args.Buyer)) + return false; return true; } diff --git a/Content.Server/Store/Conditions/StoreWhitelistCondition.cs b/Content.Server/Store/Conditions/StoreWhitelistCondition.cs index 20ec5cecce..ced4dfa9c0 100644 --- a/Content.Server/Store/Conditions/StoreWhitelistCondition.cs +++ b/Content.Server/Store/Conditions/StoreWhitelistCondition.cs @@ -26,18 +26,11 @@ public sealed partial class StoreWhitelistCondition : ListingCondition return false; var ent = args.EntityManager; + var whitelistSystem = ent.System(); - if (Whitelist != null) - { - if (!Whitelist.IsValid(args.StoreEntity.Value, ent)) - return false; - } - - if (Blacklist != null) - { - if (Blacklist.IsValid(args.StoreEntity.Value, ent)) - return false; - } + if (whitelistSystem.IsWhitelistFail(Whitelist, args.StoreEntity.Value) || + whitelistSystem.IsBlacklistPass(Blacklist, args.StoreEntity.Value)) + return false; return true; } diff --git a/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraMicrophoneSystem.cs b/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraMicrophoneSystem.cs index 1adab9930d..4deb5238a5 100644 --- a/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraMicrophoneSystem.cs +++ b/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraMicrophoneSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Chat.Systems; using Content.Server.Speech; using Content.Server.Speech.Components; +using Content.Shared.Whitelist; using Robust.Shared.Player; using static Content.Server.Chat.Systems.ChatSystem; @@ -9,7 +10,7 @@ namespace Content.Server.SurveillanceCamera; public sealed class SurveillanceCameraMicrophoneSystem : EntitySystem { [Dependency] private readonly SharedTransformSystem _xforms = default!; - + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { base.Initialize(); @@ -60,7 +61,7 @@ public sealed class SurveillanceCameraMicrophoneSystem : EntitySystem public void CanListen(EntityUid uid, SurveillanceCameraMicrophoneComponent microphone, ListenAttemptEvent args) { // TODO maybe just make this a part of ActiveListenerComponent? - if (microphone.Blacklist.IsValid(args.Source)) + if (_whitelistSystem.IsBlacklistPass(microphone.Blacklist, args.Source)) args.Cancel(); } diff --git a/Content.Server/Traits/TraitSystem.cs b/Content.Server/Traits/TraitSystem.cs index f7531f7e2c..f41512b6ac 100644 --- a/Content.Server/Traits/TraitSystem.cs +++ b/Content.Server/Traits/TraitSystem.cs @@ -2,6 +2,7 @@ using Content.Server.GameTicking; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Traits; +using Content.Shared.Whitelist; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager; @@ -12,6 +13,7 @@ public sealed class TraitSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly ISerializationManager _serializationManager = default!; [Dependency] private readonly SharedHandsSystem _sharedHandsSystem = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -31,10 +33,8 @@ public sealed class TraitSystem : EntitySystem return; } - if (traitPrototype.Whitelist != null && !traitPrototype.Whitelist.IsValid(args.Mob)) - continue; - - if (traitPrototype.Blacklist != null && traitPrototype.Blacklist.IsValid(args.Mob)) + if (_whitelistSystem.IsWhitelistFail(traitPrototype.Whitelist, args.Mob) || + _whitelistSystem.IsBlacklistPass(traitPrototype.Blacklist, args.Mob)) continue; // Add all components required by the prototype diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactCrusherSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactCrusherSystem.cs index 6606f28432..f65ba46f7a 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactCrusherSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactCrusherSystem.cs @@ -8,6 +8,7 @@ using Content.Server.Xenoarchaeology.XenoArtifacts; using Content.Shared.Body.Components; using Content.Shared.Damage; using Content.Shared.Verbs; +using Content.Shared.Whitelist; using Content.Shared.Xenoarchaeology.Equipment; using Robust.Shared.Collections; using Robust.Shared.Random; @@ -25,6 +26,7 @@ public sealed class ArtifactCrusherSystem : SharedArtifactCrusherSystem [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly StackSystem _stack = default!; [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; /// public override void Initialize() @@ -92,7 +94,7 @@ public sealed class ArtifactCrusherSystem : SharedArtifactCrusherSystem var coords = Transform(ent).Coordinates; foreach (var contained in contents) { - if (crusher.CrushingWhitelist.IsValid(contained, EntityManager)) + if (_whitelistSystem.IsWhitelistPass(crusher.CrushingWhitelist, contained)) { var amount = _random.Next(crusher.MinFragments, crusher.MaxFragments); var stacks = _stack.SpawnMultiple(crusher.FragmentStackProtoId, amount, coords); diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/DamageNearbyArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/DamageNearbyArtifactSystem.cs index a2023a18d4..f231120ad5 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/DamageNearbyArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/DamageNearbyArtifactSystem.cs @@ -1,6 +1,7 @@ -using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; +using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; using Content.Server.Xenoarchaeology.XenoArtifacts.Events; using Content.Shared.Damage; +using Content.Shared.Whitelist; using Robust.Shared.Random; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems; @@ -10,6 +11,7 @@ public sealed class BreakWindowArtifactSystem : EntitySystem [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; /// public override void Initialize() @@ -24,7 +26,7 @@ public sealed class BreakWindowArtifactSystem : EntitySystem ents.Add(args.Activator.Value); foreach (var ent in ents) { - if (component.Whitelist != null && !component.Whitelist.IsValid(ent)) + if (_whitelistSystem.IsWhitelistFail(component.Whitelist, ent)) continue; if (!_random.Prob(component.DamageChance)) diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index bf86d2c1e4..0e302f1e02 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.Interaction; using Content.Shared.Inventory.Events; using Content.Shared.Mind; using Content.Shared.Rejuvenate; +using Content.Shared.Whitelist; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.GameStates; @@ -29,6 +30,7 @@ public abstract class SharedActionsSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; [Dependency] private readonly ActionContainerSystem _actionContainer = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -477,7 +479,7 @@ public abstract class SharedActionsSystem : EntitySystem if (!target.IsValid() || Deleted(target)) return false; - if (action.Whitelist != null && !action.Whitelist.IsValid(target, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(action.Whitelist, target)) return false; if (action.CheckCanInteract && !_actionBlockerSystem.CanInteract(user, target)) diff --git a/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs b/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs index 00040211e3..e7bfb53f08 100644 --- a/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs +++ b/Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs @@ -15,6 +15,7 @@ using Content.Shared.Storage.Components; using Content.Shared.Stunnable; using Content.Shared.Throwing; using Content.Shared.Verbs; +using Content.Shared.Whitelist; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Events; using Robust.Shared.Utility; @@ -24,6 +25,8 @@ namespace Content.Shared.Buckle; public abstract partial class SharedBuckleSystem { + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + private void InitializeBuckle() { SubscribeLocalEvent(OnBuckleComponentStartup); @@ -224,8 +227,8 @@ public abstract partial class SharedBuckleSystem } // Does it pass the Whitelist - if (strapComp.Whitelist != null && - !strapComp.Whitelist.IsValid(buckleUid, EntityManager) || strapComp.Blacklist?.IsValid(buckleUid, EntityManager) == true) + if (_whitelistSystem.IsWhitelistFail(strapComp.Whitelist, buckleUid) || + _whitelistSystem.IsBlacklistPass(strapComp.Blacklist, buckleUid)) { if (_netManager.IsServer) _popup.PopupEntity(Loc.GetString("buckle-component-cannot-fit-message"), userUid, buckleUid, PopupType.Medium); diff --git a/Content.Shared/Construction/Conditions/EntityWhitelistCondition.cs b/Content.Shared/Construction/Conditions/EntityWhitelistCondition.cs index 22d86b54fb..b7b3c56ba4 100644 --- a/Content.Shared/Construction/Conditions/EntityWhitelistCondition.cs +++ b/Content.Shared/Construction/Conditions/EntityWhitelistCondition.cs @@ -31,7 +31,8 @@ public sealed partial class EntityWhitelistCondition : IConstructionCondition public bool Condition(EntityUid user, EntityCoordinates location, Direction direction) { - return Whitelist.IsValid(user); + var whitelistSystem = IoCManager.Resolve().System(); + return whitelistSystem.IsWhitelistPass(Whitelist, user); } public ConstructionGuideEntry GenerateGuideEntry() diff --git a/Content.Shared/Inventory/InventorySystem.Equip.cs b/Content.Shared/Inventory/InventorySystem.Equip.cs index 7fd156213b..7acfafee4a 100644 --- a/Content.Shared/Inventory/InventorySystem.Equip.cs +++ b/Content.Shared/Inventory/InventorySystem.Equip.cs @@ -11,6 +11,7 @@ using Content.Shared.Item; using Content.Shared.Movement.Systems; using Content.Shared.Popups; using Content.Shared.Strip.Components; +using Content.Shared.Whitelist; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Timing; @@ -30,6 +31,7 @@ public abstract partial class InventorySystem [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; [ValidatePrototypeId] private const string PocketableItemSize = "Small"; @@ -267,13 +269,8 @@ public abstract partial class InventorySystem return false; } - if (slotDefinition.Whitelist != null && !slotDefinition.Whitelist.IsValid(itemUid)) - { - reason = "inventory-component-can-equip-does-not-fit"; - return false; - } - - if (slotDefinition.Blacklist != null && slotDefinition.Blacklist.IsValid(itemUid)) + if (_whitelistSystem.IsWhitelistFail(slotDefinition.Whitelist, itemUid) || + _whitelistSystem.IsBlacklistPass(slotDefinition.Blacklist, itemUid)) { reason = "inventory-component-can-equip-does-not-fit"; return false; diff --git a/Content.Shared/Labels/EntitySystems/SharedHandLabelerSystem.cs b/Content.Shared/Labels/EntitySystems/SharedHandLabelerSystem.cs index 7dbeee3e77..0763bb101c 100644 --- a/Content.Shared/Labels/EntitySystems/SharedHandLabelerSystem.cs +++ b/Content.Shared/Labels/EntitySystems/SharedHandLabelerSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Interaction; using Content.Shared.Labels.Components; using Content.Shared.Popups; using Content.Shared.Verbs; +using Content.Shared.Whitelist; using Robust.Shared.GameStates; using Robust.Shared.Network; @@ -16,6 +17,7 @@ public abstract class SharedHandLabelerSystem : EntitySystem [Dependency] private readonly SharedLabelSystem _labelSystem = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly INetManager _netManager = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -77,7 +79,7 @@ public abstract class SharedHandLabelerSystem : EntitySystem private void OnUtilityVerb(EntityUid uid, HandLabelerComponent handLabeler, GetVerbsEvent args) { - if (args.Target is not { Valid: true } target || !handLabeler.Whitelist.IsValid(target) || !args.CanAccess) + if (args.Target is not { Valid: true } target || _whitelistSystem.IsWhitelistFail(handLabeler.Whitelist, target) || !args.CanAccess) return; var labelerText = handLabeler.AssignedLabel == string.Empty ? Loc.GetString("hand-labeler-remove-label-text") : Loc.GetString("hand-labeler-add-label-text"); @@ -96,7 +98,7 @@ public abstract class SharedHandLabelerSystem : EntitySystem private void AfterInteractOn(EntityUid uid, HandLabelerComponent handLabeler, AfterInteractEvent args) { - if (args.Target is not { Valid: true } target || !handLabeler.Whitelist.IsValid(target) || !args.CanReach) + if (args.Target is not { Valid: true } target || _whitelistSystem.IsWhitelistFail(handLabeler.Whitelist, target) || !args.CanReach) return; Labeling(uid, target, args.User, handLabeler); diff --git a/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs b/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs index fb1702bb94..9a7da17d48 100644 --- a/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs +++ b/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.Emag.Systems; using Content.Shared.Examine; using Content.Shared.Mobs.Components; using Content.Shared.Stacks; +using Content.Shared.Whitelist; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; @@ -29,6 +30,7 @@ public abstract class SharedMaterialReclaimerSystem : EntitySystem [Dependency] protected readonly SharedAmbientSoundSystem AmbientSound = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] protected readonly SharedContainerSystem Container = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public const string ActiveReclaimerContainerId = "active-material-reclaimer-container"; @@ -91,10 +93,8 @@ public abstract class SharedMaterialReclaimerSystem : EntitySystem if (HasComp(item) && !CanGib(uid, item, component)) // whitelist? We be gibbing, boy! return false; - if (component.Whitelist is {} whitelist && !whitelist.IsValid(item)) - return false; - - if (component.Blacklist is {} blacklist && blacklist.IsValid(item)) + if (_whitelistSystem.IsWhitelistFail(component.Whitelist, item) || + _whitelistSystem.IsBlacklistPass(component.Blacklist, item)) return false; if (Container.TryGetContainingContainer(item, out _) && !Container.TryRemoveFromContainer(item)) diff --git a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs b/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs index 73b7c0847f..2ec48085c4 100644 --- a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs +++ b/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs @@ -15,6 +15,7 @@ using Content.Shared.Movement.Components; using Content.Shared.Movement.Systems; using Content.Shared.Popups; using Content.Shared.Weapons.Melee; +using Content.Shared.Whitelist; using Robust.Shared.Containers; using Robust.Shared.Network; using Robust.Shared.Serialization; @@ -37,6 +38,7 @@ public abstract class SharedMechSystem : EntitySystem [Dependency] private readonly SharedMoverController _mover = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; /// public override void Initialize() @@ -216,7 +218,7 @@ public abstract class SharedMechSystem : EntitySystem if (component.EquipmentContainer.ContainedEntities.Count >= component.MaxEquipmentAmount) return; - if (component.EquipmentWhitelist != null && !component.EquipmentWhitelist.IsValid(toInsert)) + if (_whitelistSystem.IsWhitelistFail(component.EquipmentWhitelist, toInsert)) return; equipmentComponent.EquipmentOwner = uid; diff --git a/Content.Shared/Movement/Systems/SpeedModifierContactsSystem.cs b/Content.Shared/Movement/Systems/SpeedModifierContactsSystem.cs index 400a675cd2..6e1b3a29ae 100644 --- a/Content.Shared/Movement/Systems/SpeedModifierContactsSystem.cs +++ b/Content.Shared/Movement/Systems/SpeedModifierContactsSystem.cs @@ -1,4 +1,5 @@ using Content.Shared.Movement.Components; +using Content.Shared.Whitelist; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; @@ -9,6 +10,7 @@ public sealed class SpeedModifierContactsSystem : EntitySystem { [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly MovementSpeedModifierSystem _speedModifierSystem = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; // TODO full-game-save // Either these need to be processed before a map is saved, or slowed/slowing entities need to update on init. @@ -86,7 +88,7 @@ public sealed class SpeedModifierContactsSystem : EntitySystem if (!TryComp(ent, out var slowContactsComponent)) continue; - if (slowContactsComponent.IgnoreWhitelist != null && slowContactsComponent.IgnoreWhitelist.IsValid(uid)) + if (_whitelistSystem.IsWhitelistPass(slowContactsComponent.IgnoreWhitelist, uid)) continue; walkSpeed += slowContactsComponent.WalkSpeedModifier; diff --git a/Content.Shared/Ninja/Systems/EmagProviderSystem.cs b/Content.Shared/Ninja/Systems/EmagProviderSystem.cs index df9cf8ac82..6838e7982c 100644 --- a/Content.Shared/Ninja/Systems/EmagProviderSystem.cs +++ b/Content.Shared/Ninja/Systems/EmagProviderSystem.cs @@ -17,6 +17,7 @@ public sealed class EmagProviderSystem : EntitySystem [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly SharedNinjaGlovesSystem _gloves = default!; [Dependency] private readonly TagSystem _tags = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -35,7 +36,7 @@ public sealed class EmagProviderSystem : EntitySystem return; // only allowed to emag entities on the whitelist - if (comp.Whitelist != null && !comp.Whitelist.IsValid(target, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(comp.Whitelist, target)) return; // only allowed to emag non-immune entities diff --git a/Content.Shared/Placeable/ItemPlacerSystem.cs b/Content.Shared/Placeable/ItemPlacerSystem.cs index 9be6a4acd5..d1ea88b82a 100644 --- a/Content.Shared/Placeable/ItemPlacerSystem.cs +++ b/Content.Shared/Placeable/ItemPlacerSystem.cs @@ -1,4 +1,5 @@ -using Robust.Shared.Physics.Events; +using Content.Shared.Whitelist; +using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; namespace Content.Shared.Placeable; @@ -11,6 +12,7 @@ public sealed class ItemPlacerSystem : EntitySystem { [Dependency] private readonly CollisionWakeSystem _wake = default!; [Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -22,7 +24,7 @@ public sealed class ItemPlacerSystem : EntitySystem private void OnStartCollide(EntityUid uid, ItemPlacerComponent comp, ref StartCollideEvent args) { - if (comp.Whitelist != null && !comp.Whitelist.IsValid(args.OtherEntity)) + if (_whitelistSystem.IsWhitelistFail(comp.Whitelist, args.OtherEntity)) return; if (TryComp(args.OtherEntity, out var wakeComp)) diff --git a/Content.Shared/Random/RulesSystem.cs b/Content.Shared/Random/RulesSystem.cs index 6b8a58abb7..58d67c268e 100644 --- a/Content.Shared/Random/RulesSystem.cs +++ b/Content.Shared/Random/RulesSystem.cs @@ -1,6 +1,7 @@ using System.Numerics; using Content.Shared.Access.Components; using Content.Shared.Access.Systems; +using Content.Shared.Whitelist; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; @@ -14,7 +15,7 @@ public sealed class RulesSystem : EntitySystem [Dependency] private readonly AccessReaderSystem _reader = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; - + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public bool IsTrue(EntityUid uid, RulesPrototype rules) { var inRange = new HashSet>(); @@ -158,7 +159,7 @@ public sealed class RulesSystem : EntitySystem foreach (var ent in _lookup.GetEntitiesInRange(xform.MapID, worldPos, entity.Range)) { - if (!entity.Whitelist.IsValid(ent, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(entity.Whitelist, ent)) continue; count++; diff --git a/Content.Shared/Sound/SharedEmitSoundSystem.cs b/Content.Shared/Sound/SharedEmitSoundSystem.cs index 0dcdc44c9f..efc18abaa0 100644 --- a/Content.Shared/Sound/SharedEmitSoundSystem.cs +++ b/Content.Shared/Sound/SharedEmitSoundSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Mobs; using Content.Shared.Popups; using Content.Shared.Sound.Components; using Content.Shared.Throwing; +using Content.Shared.Whitelist; using JetBrains.Annotations; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; @@ -34,6 +35,7 @@ public abstract class SharedEmitSoundSystem : EntitySystem [Dependency] private readonly SharedAmbientSoundSystem _ambient = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; [Dependency] protected readonly SharedPopupSystem Popup = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -123,7 +125,7 @@ public abstract class SharedEmitSoundSystem : EntitySystem private void OnEmitSoundOnInteractUsing(Entity ent, ref InteractUsingEvent args) { - if (ent.Comp.Whitelist.IsValid(args.Used, EntityManager)) + if (_whitelistSystem.IsWhitelistPass(ent.Comp.Whitelist, args.Used)) { TryEmitSound(ent, ent.Comp, args.User); } diff --git a/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs b/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs index d81ad754d1..14703f3177 100644 --- a/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs +++ b/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Gravity; using Content.Shared.StepTrigger.Components; +using Content.Shared.Whitelist; using Robust.Shared.Map.Components; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; @@ -12,6 +13,7 @@ public sealed class StepTriggerSystem : EntitySystem [Dependency] private readonly EntityLookupSystem _entityLookup = default!; [Dependency] private readonly SharedGravitySystem _gravity = default!; [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -67,7 +69,7 @@ public sealed class StepTriggerSystem : EntitySystem if (ent == uid) continue; - if (component.Blacklist.IsValid(ent.Value, EntityManager) == true) + if (_whitelistSystem.IsBlacklistPass(component.Blacklist, ent.Value)) { return false; } diff --git a/Content.Shared/Storage/EntitySystems/BinSystem.cs b/Content.Shared/Storage/EntitySystems/BinSystem.cs index 1cc95337ea..8c2cb4c4fc 100644 --- a/Content.Shared/Storage/EntitySystems/BinSystem.cs +++ b/Content.Shared/Storage/EntitySystems/BinSystem.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.Examine; @@ -7,6 +7,7 @@ using Content.Shared.Interaction; using Content.Shared.Item; using Content.Shared.Storage.Components; using Content.Shared.Verbs; +using Content.Shared.Whitelist; using Robust.Shared.Containers; using Robust.Shared.Network; @@ -21,6 +22,7 @@ public sealed class BinSystem : EntitySystem [Dependency] private readonly ISharedAdminLogManager _admin = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public const string BinContainerId = "bin-container"; @@ -130,7 +132,7 @@ public sealed class BinSystem : EntitySystem if (component.Items.Count >= component.MaxItems) return false; - if (component.Whitelist != null && !component.Whitelist.IsValid(toInsert)) + if (_whitelistSystem.IsWhitelistFail(component.Whitelist, toInsert)) return false; _container.Insert(toInsert, component.ItemContainer); diff --git a/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs b/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs index a5e151f4ea..2557f8100c 100644 --- a/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedItemMapperSystem.cs @@ -1,5 +1,6 @@ -using System.Linq; +using System.Linq; using Content.Shared.Storage.Components; +using Content.Shared.Whitelist; using JetBrains.Annotations; using Robust.Shared.Containers; @@ -15,6 +16,7 @@ namespace Content.Shared.Storage.EntitySystems { [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; /// public override void Initialize() @@ -93,7 +95,7 @@ namespace Content.Shared.Storage.EntitySystems var list = new List(); foreach (var mapLayerData in itemMapper.MapLayers.Values) { - var count = containedLayers.Count(ent => mapLayerData.ServerWhitelist.IsValid(ent)); + var count = containedLayers.Count(ent => _whitelistSystem.IsWhitelistPass(mapLayerData.ServerWhitelist, ent)); if (count >= mapLayerData.MinCount && count <= mapLayerData.MaxCount) { list.Add(mapLayerData.Layer); diff --git a/Content.Shared/Teleportation/Systems/SwapTeleporterSystem.cs b/Content.Shared/Teleportation/Systems/SwapTeleporterSystem.cs index bc73baa61a..58c249fec5 100644 --- a/Content.Shared/Teleportation/Systems/SwapTeleporterSystem.cs +++ b/Content.Shared/Teleportation/Systems/SwapTeleporterSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Teleportation.Components; using Content.Shared.Verbs; +using Content.Shared.Whitelist; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Map.Components; @@ -24,6 +25,7 @@ public sealed class SwapTeleporterSystem : EntitySystem [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; private EntityQuery _xformQuery; @@ -51,8 +53,8 @@ public sealed class SwapTeleporterSystem : EntitySystem if (!TryComp(target, out var targetComp)) return; - if (!comp.TeleporterWhitelist.IsValid(target, EntityManager) || - !targetComp.TeleporterWhitelist.IsValid(uid, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(comp.TeleporterWhitelist, target) || + _whitelistSystem.IsWhitelistFail(targetComp.TeleporterWhitelist, uid)) { return; } diff --git a/Content.Shared/UserInterface/ActivatableUISystem.cs b/Content.Shared/UserInterface/ActivatableUISystem.cs index 1bb11f337f..b1006b2a74 100644 --- a/Content.Shared/UserInterface/ActivatableUISystem.cs +++ b/Content.Shared/UserInterface/ActivatableUISystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Popups; using Content.Shared.Verbs; +using Content.Shared.Whitelist; using Robust.Shared.Utility; namespace Content.Shared.UserInterface; @@ -19,6 +20,7 @@ public sealed partial class ActivatableUISystem : EntitySystem [Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; public override void Initialize() { @@ -96,7 +98,7 @@ public sealed partial class ActivatableUISystem : EntitySystem if (!args.CanAccess) return false; - if (!component.RequiredItems?.IsValid(args.Using ?? default, EntityManager) ?? false) + if (_whitelistSystem.IsWhitelistFail(component.RequiredItems, args.Using ?? default)) return false; if (component.RequireHands) @@ -156,7 +158,7 @@ public sealed partial class ActivatableUISystem : EntitySystem if (component.RequiredItems == null) return; - if (!component.RequiredItems.IsValid(args.Used, EntityManager)) + if (_whitelistSystem.IsWhitelistFail(component.RequiredItems, args.Used)) return; args.Handled = InteractUI(args.User, uid, component); diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs index 1f9e6cee76..9123661c8e 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs @@ -15,6 +15,7 @@ public abstract partial class SharedGunSystem { [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + protected virtual void InitializeBallistic() { SubscribeLocalEvent(OnBallisticInit); @@ -125,7 +126,7 @@ public abstract partial class SharedGunSystem if (ent == null) continue; - if (!target.Whitelist.IsValid(ent.Value)) + if (_whitelistSystem.IsWhitelistFail(target.Whitelist, ent.Value)) { Popup( Loc.GetString("gun-ballistic-transfer-invalid", diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs index 77ee419ac3..d4aa024f4c 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs @@ -42,7 +42,7 @@ public partial class SharedGunSystem while (enumerator.NextItem(out var item)) { - if (component.ProviderWhitelist == null || !component.ProviderWhitelist.IsValid(item, EntityManager)) + if (_whitelistSystem.IsWhitelistFailOrNull(component.ProviderWhitelist, item)) continue; slotEntity = item; From b51f04a765a68d5d5b86f83f49eb14c812ea0ac0 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Mon, 3 Jun 2024 15:42:50 -0700 Subject: [PATCH 52/63] Gets rid of obsolete EntityWhitelist.IsValid() function (#28565) Gets rid of obsolete IsValid function Co-authored-by: plykiya --- Content.Shared/Whitelist/EntityWhitelist.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Content.Shared/Whitelist/EntityWhitelist.cs b/Content.Shared/Whitelist/EntityWhitelist.cs index 895759be95..3e4e2fecb2 100644 --- a/Content.Shared/Whitelist/EntityWhitelist.cs +++ b/Content.Shared/Whitelist/EntityWhitelist.cs @@ -54,14 +54,4 @@ public sealed partial class EntityWhitelist /// [DataField] public bool RequireAll; - - [Obsolete("Use WhitelistSystem")] - public bool IsValid(EntityUid uid, IEntityManager? man = null) - { - var sys = man?.System() ?? - IoCManager.Resolve().GetEntitySystem(); - - return sys.IsValid(this, uid); - - } } From 2ae5c953de0ee6bb5cafa1c983106c9c4596c8d6 Mon Sep 17 00:00:00 2001 From: Verm <32827189+Vermidia@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:45:00 -0500 Subject: [PATCH 53/63] Humans can no longer honk on command (#28566) * Humans can no longer honk on command * Undo change it emote file * I hate tabs * Some comments --- .../Chat/Systems/ChatSystem.Emote.cs | 45 ++++++++++++++----- .../Chemistry/ReagentEffects/Emote.cs | 7 ++- Resources/Prototypes/Reagents/fun.yml | 1 + Resources/Prototypes/Reagents/toxins.yml | 1 + 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/Content.Server/Chat/Systems/ChatSystem.Emote.cs b/Content.Server/Chat/Systems/ChatSystem.Emote.cs index 20a4f18746..e4e5c39eeb 100644 --- a/Content.Server/Chat/Systems/ChatSystem.Emote.cs +++ b/Content.Server/Chat/Systems/ChatSystem.Emote.cs @@ -49,18 +49,20 @@ public partial class ChatSystem /// Whether or not this message should appear in the adminlog window /// Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all... /// The name to use for the speaking entity. Usually this should just be modified via . If this is set, the event will not get raised. + /// Bypasses whitelist/blacklist/availibility checks for if the entity can use this emote public void TryEmoteWithChat( EntityUid source, string emoteId, ChatTransmitRange range = ChatTransmitRange.Normal, bool hideLog = false, string? nameOverride = null, - bool ignoreActionBlocker = false + bool ignoreActionBlocker = false, + bool forceEmote = false ) { if (!_prototypeManager.TryIndex(emoteId, out var proto)) return; - TryEmoteWithChat(source, proto, range, hideLog: hideLog, nameOverride, ignoreActionBlocker: ignoreActionBlocker); + TryEmoteWithChat(source, proto, range, hideLog: hideLog, nameOverride, ignoreActionBlocker: ignoreActionBlocker, forceEmote: forceEmote); } /// @@ -72,22 +74,18 @@ public partial class ChatSystem /// Whether or not this message should appear in the chat window /// Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all... /// The name to use for the speaking entity. Usually this should just be modified via . If this is set, the event will not get raised. + /// Bypasses whitelist/blacklist/availibility checks for if the entity can use this emote public void TryEmoteWithChat( EntityUid source, EmotePrototype emote, ChatTransmitRange range = ChatTransmitRange.Normal, bool hideLog = false, string? nameOverride = null, - bool ignoreActionBlocker = false + bool ignoreActionBlocker = false, + bool forceEmote = false ) { - - if (_whitelistSystem.IsWhitelistFail(emote.Whitelist, source) || _whitelistSystem.IsBlacklistPass(emote.Blacklist, source)) - return; - - if (!emote.Available && - TryComp(source, out var speech) && - !speech.AllowedEmotes.Contains(emote.ID)) + if (!forceEmote && !AllowedToUseEmote(source, emote)) return; // check if proto has valid message for chat @@ -156,15 +154,40 @@ public partial class ChatSystem _audio.PlayPvs(sound, uid, param); return true; } - + /// + /// Checks if a valid emote was typed, to play sounds and etc and invokes an event. + /// + /// + /// private void TryEmoteChatInput(EntityUid uid, string textInput) { var actionLower = textInput.ToLower(); if (!_wordEmoteDict.TryGetValue(actionLower, out var emote)) return; + if (!AllowedToUseEmote(uid, emote)) + return; + InvokeEmoteEvent(uid, emote); } + /// + /// Checks if we can use this emote based on the emotes whitelist, blacklist, and availibility to the entity. + /// + /// The entity that is speaking + /// The emote being used + /// + private bool AllowedToUseEmote(EntityUid source, EmotePrototype emote) + { + if ((_whitelistSystem.IsWhitelistFail(emote.Whitelist, source) || _whitelistSystem.IsBlacklistPass(emote.Blacklist, source))) + return false; + + if (!emote.Available && + TryComp(source, out var speech) && + !speech.AllowedEmotes.Contains(emote.ID)) + return false; + + return true; + } private void InvokeEmoteEvent(EntityUid uid, EmotePrototype proto) { diff --git a/Content.Server/Chemistry/ReagentEffects/Emote.cs b/Content.Server/Chemistry/ReagentEffects/Emote.cs index a4d49e4ad1..db6de6cc75 100644 --- a/Content.Server/Chemistry/ReagentEffects/Emote.cs +++ b/Content.Server/Chemistry/ReagentEffects/Emote.cs @@ -8,7 +8,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy namespace Content.Server.Chemistry.ReagentEffects; /// -/// Tries to force someone to emote (scream, laugh, etc). +/// Tries to force someone to emote (scream, laugh, etc). Still respects whitelists/blacklists and other limits of the specified emote unless forced. /// [UsedImplicitly] public sealed partial class Emote : ReagentEffect @@ -19,6 +19,9 @@ public sealed partial class Emote : ReagentEffect [DataField] public bool ShowInChat; + [DataField] + public bool Force = false; + // JUSTIFICATION: Emoting is flavor, so same reason popup messages are not in here. protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => null; @@ -30,7 +33,7 @@ public sealed partial class Emote : ReagentEffect var chatSys = args.EntityManager.System(); if (ShowInChat) - chatSys.TryEmoteWithChat(args.SolutionEntity, EmoteId, ChatTransmitRange.GhostRangeLimit); + chatSys.TryEmoteWithChat(args.SolutionEntity, EmoteId, ChatTransmitRange.GhostRangeLimit, forceEmote: Force); else chatSys.TryEmoteWithoutChat(args.SolutionEntity, EmoteId); diff --git a/Resources/Prototypes/Reagents/fun.yml b/Resources/Prototypes/Reagents/fun.yml index befa8d8296..1df2636c8c 100644 --- a/Resources/Prototypes/Reagents/fun.yml +++ b/Resources/Prototypes/Reagents/fun.yml @@ -333,6 +333,7 @@ - !type:Emote emote: Weh showInChat: true + force: true probability: 0.5 - !type:Polymorph prototype: ArtifactLizard # Does the same thing as the original YML I made for this reagent. diff --git a/Resources/Prototypes/Reagents/toxins.yml b/Resources/Prototypes/Reagents/toxins.yml index f5b196acf6..9665de7b09 100644 --- a/Resources/Prototypes/Reagents/toxins.yml +++ b/Resources/Prototypes/Reagents/toxins.yml @@ -560,6 +560,7 @@ - !type:Emote emote: Honk showInChat: true + force: true probability: 0.2 - !type:HealthChange conditions: From 7d22897d02706507be7f918bfafa493fccc702e3 Mon Sep 17 00:00:00 2001 From: "Mr. 27" <45323883+Dutch-VanDerLinde@users.noreply.github.com> Date: Mon, 3 Jun 2024 19:52:15 -0400 Subject: [PATCH 54/63] Job starting gear is now defined in the starting gear rather than backpack prototypes (#27605) * --- .../Tests/Roles/StartingGearStorageTests.cs | 72 +++ .../Station/Systems/StationSpawningSystem.cs | 15 +- Content.Shared/Roles/StartingGearPrototype.cs | 68 ++- .../Station/SharedStationSpawningSystem.cs | 20 +- .../en-US/preferences/loadout-groups.ftl | 11 +- .../Fills/Backpacks/StarterGear/backpack.yml | 422 ------------------ .../Fills/Backpacks/StarterGear/duffelbag.yml | 275 ------------ .../Fills/Backpacks/StarterGear/satchel.yml | 300 ------------- .../Catalog/Fills/Backpacks/duffelbag.yml | 49 -- .../Entities/Clothing/Back/backpacks.yml | 10 + .../Prototypes/Entities/Mobs/NPCs/human.yml | 2 +- .../Loadouts/Jobs/Cargo/cargo_technician.yml | 6 +- .../Loadouts/Jobs/Cargo/quartermaster.yml | 28 -- .../Jobs/Cargo/salvage_specialist.yml | 6 +- .../Loadouts/Jobs/Civilian/botanist.yml | 6 +- .../Loadouts/Jobs/Civilian/chaplain.yml | 28 -- .../Loadouts/Jobs/Civilian/clown.yml | 6 +- .../Loadouts/Jobs/Civilian/lawyer.yml | 30 +- .../Loadouts/Jobs/Civilian/mime.yml | 6 +- .../Loadouts/Jobs/Civilian/musician.yml | 28 -- .../Loadouts/Jobs/Civilian/passenger.yml | 6 +- .../Loadouts/Jobs/Command/captain.yml | 6 +- .../Jobs/Command/head_of_personnel.yml | 29 +- .../Engineering/atmospheric_technician.yml | 6 +- .../Jobs/Engineering/chief_engineer.yml | 28 -- .../Jobs/Engineering/station_engineer.yml | 6 +- .../Loadouts/Jobs/Medical/chemist.yml | 6 +- .../Jobs/Medical/chief_medical_officer.yml | 28 -- .../Loadouts/Jobs/Medical/medical_doctor.yml | 6 +- .../Loadouts/Jobs/Medical/paramedic.yml | 28 -- .../Jobs/Science/research_director.yml | 28 -- .../Loadouts/Jobs/Science/scientist.yml | 6 +- .../Loadouts/Jobs/Security/detective.yml | 28 -- .../Jobs/Security/security_officer.yml | 6 +- .../Prototypes/Loadouts/loadout_groups.yml | 82 +--- .../Prototypes/Loadouts/role_loadouts.yml | 18 +- Resources/Prototypes/Roles/Antags/Thief.yml | 7 + Resources/Prototypes/Roles/Antags/ninja.yml | 30 ++ Resources/Prototypes/Roles/Antags/nukeops.yml | 63 +++ Resources/Prototypes/Roles/Antags/pirate.yml | 16 +- .../Prototypes/Roles/Antags/revolutionary.yml | 7 + Resources/Prototypes/Roles/Antags/traitor.yml | 33 ++ .../Roles/Jobs/Cargo/cargo_technician.yml | 5 +- .../Roles/Jobs/Cargo/quartermaster.yml | 6 +- .../Roles/Jobs/Cargo/salvage_specialist.yml | 5 +- .../Roles/Jobs/Civilian/assistant.yml | 3 + .../Roles/Jobs/Civilian/bartender.yml | 3 + .../Roles/Jobs/Civilian/botanist.yml | 3 + .../Roles/Jobs/Civilian/chaplain.yml | 5 + .../Prototypes/Roles/Jobs/Civilian/chef.yml | 3 + .../Prototypes/Roles/Jobs/Civilian/clown.yml | 7 +- .../Roles/Jobs/Civilian/janitor.yml | 3 + .../Prototypes/Roles/Jobs/Civilian/lawyer.yml | 4 + .../Roles/Jobs/Civilian/librarian.yml | 4 + .../Prototypes/Roles/Jobs/Civilian/mime.yml | 4 + .../Roles/Jobs/Civilian/musician.yml | 7 +- .../Roles/Jobs/Civilian/service_worker.yml | 3 + .../Prototypes/Roles/Jobs/Command/captain.yml | 5 + .../Roles/Jobs/Command/head_of_personnel.yml | 4 + .../Engineering/atmospheric_technician.yml | 3 + .../Roles/Jobs/Engineering/chief_engineer.yml | 4 + .../Jobs/Engineering/station_engineer.yml | 3 + .../Jobs/Engineering/technical_assistant.yml | 5 +- .../Roles/Jobs/Fun/cult_startinggear.yml | 10 +- .../Roles/Jobs/Fun/emergencyresponseteam.yml | 174 +++++++- .../Roles/Jobs/Fun/misc_startinggear.yml | 221 +++------ .../Roles/Jobs/Fun/wizard_startinggear.yml | 22 +- .../Prototypes/Roles/Jobs/Medical/chemist.yml | 5 +- .../Jobs/Medical/chief_medical_officer.yml | 4 + .../Roles/Jobs/Medical/medical_doctor.yml | 3 + .../Roles/Jobs/Medical/medical_intern.yml | 5 +- .../Roles/Jobs/Medical/paramedic.yml | 4 + .../Roles/Jobs/Science/research_assistant.yml | 3 + .../Roles/Jobs/Science/research_director.yml | 6 +- .../Roles/Jobs/Science/scientist.yml | 4 +- .../Roles/Jobs/Security/detective.yml | 6 + .../Roles/Jobs/Security/head_of_security.yml | 5 + .../Roles/Jobs/Security/security_cadet.yml | 7 +- .../Roles/Jobs/Security/security_officer.yml | 5 + .../Prototypes/Roles/Jobs/Security/warden.yml | 5 + .../Prototypes/Roles/Jobs/Wildcards/boxer.yml | 3 + .../Roles/Jobs/Wildcards/psychologist.yml | 3 + .../Roles/Jobs/Wildcards/reporter.yml | 3 + .../Roles/Jobs/Wildcards/zookeeper.yml | 3 + Resources/migration.yml | 6 +- 85 files changed, 729 insertions(+), 1728 deletions(-) create mode 100644 Content.IntegrationTests/Tests/Roles/StartingGearStorageTests.cs delete mode 100644 Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml delete mode 100644 Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml delete mode 100644 Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml diff --git a/Content.IntegrationTests/Tests/Roles/StartingGearStorageTests.cs b/Content.IntegrationTests/Tests/Roles/StartingGearStorageTests.cs new file mode 100644 index 0000000000..0f15a02eaa --- /dev/null +++ b/Content.IntegrationTests/Tests/Roles/StartingGearStorageTests.cs @@ -0,0 +1,72 @@ +using System.Linq; +using Content.Shared.Roles; +using Content.Server.Storage.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Collections; + +namespace Content.IntegrationTests.Tests.Roles; + +[TestFixture] +public sealed class StartingGearPrototypeStorageTest +{ + /// + /// Checks that a storage fill on a StartingGearPrototype will properly fill + /// + [Test] + public async Task TestStartingGearStorage() + { + var settings = new PoolSettings { Connected = true, Dirty = true }; + await using var pair = await PoolManager.GetServerClient(settings); + var server = pair.Server; + var mapManager = server.ResolveDependency(); + var storageSystem = server.System(); + + var protos = server.ProtoMan + .EnumeratePrototypes() + .Where(p => !p.Abstract) + .ToList() + .OrderBy(p => p.ID); + + var testMap = await pair.CreateTestMap(); + var coords = testMap.GridCoords; + + await server.WaitAssertion(() => + { + foreach (var gearProto in protos) + { + var backpackProto = gearProto.GetGear("back"); + if (backpackProto == string.Empty) + continue; + + var bag = server.EntMan.SpawnEntity(backpackProto, coords); + var ents = new ValueList(); + + foreach (var (slot, entProtos) in gearProto.Storage) + { + if (entProtos.Count == 0) + continue; + + foreach (var ent in entProtos) + { + ents.Add(server.EntMan.SpawnEntity(ent, coords)); + } + + foreach (var ent in ents) + { + if (!storageSystem.CanInsert(bag, ent, out _)) + Assert.Fail($"StartingGearPrototype {gearProto.ID} could not successfully put items into storage {bag.Id}"); + + server.EntMan.DeleteEntity(ent); + } + } + + server.EntMan.DeleteEntity(bag); + } + + mapManager.DeleteMap(testMap.MapId); + }); + + await pair.CleanReturnAsync(); + } +} diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index 557a1f9566..b91082ff26 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -179,13 +179,6 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem profile = HumanoidCharacterProfile.RandomWithSpecies(speciesId); } - if (prototype?.StartingGear != null) - { - var startingGear = _prototypeManager.Index(prototype.StartingGear); - EquipStartingGear(entity.Value, startingGear, raiseEvent: false); - } - - // Run loadouts after so stuff like storage loadouts can get var jobLoadout = LoadoutSystem.GetJobPrototype(prototype?.ID); if (_prototypeManager.TryIndex(jobLoadout, out RoleLoadoutPrototype? roleProto)) @@ -203,6 +196,12 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem EquipRoleLoadout(entity.Value, loadout, roleProto); } + if (prototype?.StartingGear != null) + { + var startingGear = _prototypeManager.Index(prototype.StartingGear); + EquipStartingGear(entity.Value, startingGear, raiseEvent: false); + } + var gearEquippedEv = new StartingGearEquippedEvent(entity.Value); RaiseLocalEvent(entity.Value, ref gearEquippedEv); @@ -309,4 +308,4 @@ public sealed class PlayerSpawningEvent : EntityEventArgs HumanoidCharacterProfile = humanoidCharacterProfile; Station = station; } -} +} \ No newline at end of file diff --git a/Content.Shared/Roles/StartingGearPrototype.cs b/Content.Shared/Roles/StartingGearPrototype.cs index fc9ecec7af..d96d014f88 100644 --- a/Content.Shared/Roles/StartingGearPrototype.cs +++ b/Content.Shared/Roles/StartingGearPrototype.cs @@ -1,30 +1,50 @@ -using Content.Shared.Preferences; using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; -namespace Content.Shared.Roles +namespace Content.Shared.Roles; + +[Prototype] +public sealed partial class StartingGearPrototype : IPrototype, IInheritingPrototype { - [Prototype("startingGear")] - public sealed partial class StartingGearPrototype : IPrototype + /// + [ViewVariables] + [IdDataField] + public string ID { get; private set; } = string.Empty; + + /// + [ParentDataField(typeof(AbstractPrototypeIdArraySerializer))] + public string[]? Parents { get; private set; } + + /// + [AbstractDataField] + public bool Abstract { get; } + + /// + /// The slot and entity prototype ID of the equipment that is to be spawned and equipped onto the entity. + /// + [DataField] + [AlwaysPushInheritance] + public Dictionary Equipment = new(); + + /// + /// The inhand items that are equipped when this starting gear is equipped onto an entity. + /// + [DataField] + [AlwaysPushInheritance] + public List Inhand = new(0); + + /// + /// Inserts entities into the specified slot's storage (if it does have storage). + /// + [DataField] + [AlwaysPushInheritance] + public Dictionary> Storage = new(); + + /// + /// Gets the entity prototype ID of a slot in this starting gear. + /// + public string GetGear(string slot) { - [DataField] - public Dictionary Equipment = new(); - - [DataField] - public List Inhand = new(0); - - /// - /// Inserts entities into the specified slot's storage (if it does have storage). - /// - [DataField] - public Dictionary> Storage = new(); - - [ViewVariables] - [IdDataField] - public string ID { get; private set; } = string.Empty; - - public string GetGear(string slot) - { - return Equipment.TryGetValue(slot, out var equipment) ? equipment : string.Empty; - } + return Equipment.TryGetValue(slot, out var equipment) ? equipment : string.Empty; } } diff --git a/Content.Shared/Station/SharedStationSpawningSystem.cs b/Content.Shared/Station/SharedStationSpawningSystem.cs index f352c9db63..ca53998115 100644 --- a/Content.Shared/Station/SharedStationSpawningSystem.cs +++ b/Content.Shared/Station/SharedStationSpawningSystem.cs @@ -15,9 +15,9 @@ public abstract class SharedStationSpawningSystem : EntitySystem { [Dependency] protected readonly IPrototypeManager PrototypeManager = default!; [Dependency] protected readonly InventorySystem InventorySystem = default!; - [Dependency] private readonly SharedHandsSystem _handsSystem = default!; - [Dependency] private readonly SharedStorageSystem _storage = default!; - [Dependency] private readonly SharedTransformSystem _xformSystem = default!; + [Dependency] private readonly SharedHandsSystem _handsSystem = default!; + [Dependency] private readonly SharedStorageSystem _storage = default!; + [Dependency] private readonly SharedTransformSystem _xformSystem = default!; private EntityQuery _handsQuery; private EntityQuery _inventoryQuery; @@ -91,7 +91,7 @@ public abstract class SharedStationSpawningSystem : EntitySystem if (!string.IsNullOrEmpty(equipmentStr)) { var equipmentEntity = EntityManager.SpawnEntity(equipmentStr, xform.Coordinates); - InventorySystem.TryEquip(entity, equipmentEntity, slot.Name, silent: true, force:true); + InventorySystem.TryEquip(entity, equipmentEntity, slot.Name, silent: true, force: true); } } } @@ -122,15 +122,15 @@ public abstract class SharedStationSpawningSystem : EntitySystem if (entProtos.Count == 0) continue; - foreach (var ent in entProtos) - { - ents.Add(Spawn(ent, coords)); - } - if (inventoryComp != null && InventorySystem.TryGetSlotEntity(entity, slot, out var slotEnt, inventoryComponent: inventoryComp) && _storageQuery.TryComp(slotEnt, out var storage)) { + foreach (var ent in entProtos) + { + ents.Add(Spawn(ent, coords)); + } + foreach (var ent in ents) { _storage.Insert(slotEnt.Value, ent, out _, storageComp: storage, playSound: false); @@ -145,4 +145,4 @@ public abstract class SharedStationSpawningSystem : EntitySystem RaiseLocalEvent(entity, ref ev); } } -} +} \ No newline at end of file diff --git a/Resources/Locale/en-US/preferences/loadout-groups.ftl b/Resources/Locale/en-US/preferences/loadout-groups.ftl index 68a47cba19..28863268df 100644 --- a/Resources/Locale/en-US/preferences/loadout-groups.ftl +++ b/Resources/Locale/en-US/preferences/loadout-groups.ftl @@ -1,6 +1,7 @@ # Miscellaneous loadout-group-trinkets = Trinkets loadout-group-glasses = Glasses +loadout-group-backpack = Backpack # Command loadout-group-captain-head = Captain head @@ -19,7 +20,6 @@ loadout-group-hop-outerclothing = Head of Personnel outer clothing loadout-group-passenger-jumpsuit = Passenger jumpsuit loadout-group-passenger-mask = Passenger mask loadout-group-passenger-gloves = Passenger gloves -loadout-group-passenger-backpack = Passenger backpack loadout-group-passenger-outerclothing = Passenger outer clothing loadout-group-passenger-shoes = Passenger shoes @@ -36,12 +36,10 @@ loadout-group-librarian-jumpsuit = Librarian jumpsuit loadout-group-lawyer-jumpsuit = Lawyer jumpsuit loadout-group-lawyer-neck = Lawyer neck -loadout-group-lawyer-backpack = Lawyer backpack loadout-group-chaplain-head = Chaplain head loadout-group-chaplain-mask = Chaplain mask loadout-group-chaplain-jumpsuit = Chaplain jumpsuit -loadout-group-chaplain-backpack = Chaplain backpack loadout-group-chaplain-outerclothing = Chaplain outer clothing loadout-group-chaplain-neck = Chaplain neck @@ -67,13 +65,11 @@ loadout-group-mime-jumpsuit = Mime jumpsuit loadout-group-mime-backpack = Mime backpack loadout-group-mime-outerclothing = Mime outer clothing -loadout-group-musician-backpack = Musician backpack loadout-group-musician-outerclothing = Musician outer clothing # Cargo loadout-group-quartermaster-head = Quartermaster head loadout-group-quartermaster-jumpsuit = Quartermaster jumpsuit -loadout-group-quartermaster-backpack = Quartermaster backpack loadout-group-quartermaster-neck = Quartermaster neck loadout-group-quartermaster-outerclothing = Quartermaster outer clothing loadout-group-quartermaster-shoes = Quartermaster shoes @@ -91,7 +87,6 @@ loadout-group-salvage-specialist-shoes = Salvage Specialist shoes # Engineering loadout-group-chief-engineer-head = Chief Engineer head loadout-group-chief-engineer-jumpsuit = Chief Engineer jumpsuit -loadout-group-chief-engineer-backpack = Chief Engineer backpack loadout-group-chief-engineer-outerclothing = Chief Engineer outer clothing loadout-group-chief-engineer-neck = Chief Engineer neck loadout-group-chief-engineer-shoes = Chief Engineer shoes @@ -114,7 +109,6 @@ loadout-group-atmospheric-technician-shoes = Atmospheric Technician shoes loadout-group-research-director-head = Research Director head loadout-group-research-director-neck = Research Director neck loadout-group-research-director-jumpsuit = Research Director jumpsuit -loadout-group-research-director-backpack = Research Director backpack loadout-group-research-director-outerclothing = Research Director outer clothing loadout-group-research-director-shoes = Research Director shoes @@ -150,7 +144,6 @@ loadout-group-security-id = Security ID loadout-group-detective-head = Detective head loadout-group-detective-neck = Detective neck loadout-group-detective-jumpsuit = Detective jumpsuit -loadout-group-detective-backpack = Detective backpack loadout-group-detective-outerclothing = Detective outer clothing loadout-group-security-cadet-jumpsuit = Security cadet jumpsuit @@ -162,7 +155,6 @@ loadout-group-medical-mask = Medical mask loadout-group-chief-medical-officer-head = Chief Medical Officer head loadout-group-chief-medical-officer-jumpsuit = Chief Medical Officer jumpsuit loadout-group-chief-medical-officer-outerclothing = Chief Medical Officer outer clothing -loadout-group-chief-medical-officer-backpack = Chief Medical Officer backpack loadout-group-chief-medical-officer-shoes = Chief Medical Officer shoes loadout-group-chief-medical-officer-neck = Chief Medical Officer neck @@ -183,7 +175,6 @@ loadout-group-paramedic-head = Paramedic head loadout-group-paramedic-jumpsuit = Paramedic jumpsuit loadout-group-paramedic-outerclothing = Paramedic outer clothing loadout-group-paramedic-shoes = Paramedic shoes -loadout-group-paramedic-backpack = Paramedic backpack # Wildcards loadout-group-reporter-jumpsuit = Reporter jumpsuit diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml deleted file mode 100644 index 71c679a2aa..0000000000 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ /dev/null @@ -1,422 +0,0 @@ -- type: entity - parent: ClothingBackpack - id: ClothingBackpackFilled - noSpawn: true - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackClown - id: ClothingBackpackClownFilled - components: - - type: StorageFill - contents: - - id: BoxHug - - id: RubberStampClown - - id: CrayonRainbow - -- type: entity - noSpawn: true - parent: ClothingBackpackSecurity - id: ClothingBackpackSecurityFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: MagazinePistol - -- type: entity - noSpawn: true - parent: ClothingBackpackSecurity - id: ClothingBackpackSecurityFilledDetective - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: ForensicPad - - id: ForensicScanner - -- type: entity - noSpawn: true - parent: ClothingBackpackMedical - id: ClothingBackpackMedicalFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - -- type: entity - noSpawn: true - parent: ClothingBackpackMedical - id: ClothingBackpackParamedicFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - - id: EmergencyRollerBedSpawnFolded - -- type: entity - noSpawn: true - parent: ClothingBackpackCaptain - id: ClothingBackpackCaptainFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- name: StationCharter - #- name: TelescopicBaton -- type: entity - noSpawn: true - parent: ClothingBackpackEngineering - id: ClothingBackpackChiefEngineerFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackScience - id: ClothingBackpackResearchDirectorFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpack - id: ClothingBackpackHOPFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackIan - id: ClothingBackpackHOPIanFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackMedical - id: ClothingBackpackCMOFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackCargo - id: ClothingBackpackQuartermasterFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackSecurity - id: ClothingBackpackHOSFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: MagazinePistol - -- type: entity - noSpawn: true - parent: ClothingBackpackEngineering - id: ClothingBackpackEngineeringFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - -- type: entity - noSpawn: true - parent: ClothingBackpackAtmospherics - id: ClothingBackpackAtmosphericsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - -- type: entity - noSpawn: true - parent: ClothingBackpackScience - id: ClothingBackpackScienceFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackHydroponics - id: ClothingBackpackHydroponicsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackMime - id: ClothingBackpackMimeFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: RubberStampMime - -- type: entity - noSpawn: true - parent: ClothingBackpackChemistry - id: ClothingBackpackChemistryFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - -- type: entity - noSpawn: true - parent: ClothingBackpack - id: ClothingBackpackChaplainFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Bible - - id: RubberStampChaplain - -- type: entity - noSpawn: true - parent: ClothingBackpack - id: ClothingBackpackLawyerFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: RubberStampLawyer - -- type: entity - noSpawn: true - parent: ClothingBackpack - id: ClothingBackpackMusicianFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: AcousticGuitarInstrument - - id: SaxophoneInstrument - -- type: entity - noSpawn: true - parent: ClothingBackpack - id: ClothingBackpackLibrarianFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: BookRandom - -- type: entity - noSpawn: true - parent: ClothingBackpack - id: ClothingBackpackDetectiveFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Lighter - - id: CigPackBlack - - id: HandLabeler - - id: BoxForensicPad - -# ERT - -- type: entity - noSpawn: true - parent: ClothingBackpackERTLeader - id: ClothingBackpackERTLeaderFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: WeaponDisabler - - id: MedicatedSuture - - id: RegenerativeMesh - - id: BoxZiptie - - id: CrowbarRed - - id: MagazineMagnum - -- type: entity - noSpawn: true - parent: ClothingBackpackERTSecurity - id: ClothingBackpackERTSecurityFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: WeaponDisabler - - id: MedicatedSuture - - id: RegenerativeMesh - - id: BoxZiptie - - id: CrowbarRed - - id: MagazinePistol - -- type: entity - noSpawn: true - parent: ClothingBackpackERTMedical - id: ClothingBackpackERTMedicalFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - - id: Hypospray - - id: MedkitAdvancedFilled - - id: CrowbarRed - - id: OmnizineChemistryBottle - - id: EpinephrineChemistryBottle - - id: EpinephrineChemistryBottle - -- type: entity - noSpawn: true - parent: ClothingBackpackERTEngineer - id: ClothingBackpackERTEngineerFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: trayScanner - - id: RCD - - id: RCDAmmo - amount: 2 - - id: CableMVStack - - id: CableHVStack - - id: CableApcStack - - id: SheetPlasteel - - id: SheetSteel - - id: SheetGlass - -- type: entity - noSpawn: true - parent: ClothingBackpackERTJanitor - id: ClothingBackpackERTJanitorFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: LightReplacer - - id: BoxLightMixed - - id: BoxLightMixed - - id: Soap - - id: CrowbarRed - - id: AdvMopItem - -- type: entity - noSpawn: true - parent: ClothingBackpackERTChaplain - id: ClothingBackpackERTChaplainFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: BoxCandle - - id: BoxBodyBag - - id: DrinkWaterMelonJuiceJug - - id: Lantern - - id: Lantern - - id: Bible - - id: CrowbarRed - - id: FoodBakedBunHotX - - id: FoodBakedBunHotX - - id: FoodBakedBunHotX - - id: FoodBakedBunHotX - - id: Lighter - -# Death Squad - -- type: entity - noSpawn: false - parent: ClothingBackpackERTSecurity - id: ClothingBackpackDeathSquadFilled - name: death squad backpack - description: Holds the kit of CentComm's most feared agents. - components: - - type: Storage - grid: - - 0,0,7,6 - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: WeaponPulseRifle - - id: WeaponPulsePistol - - id: WeaponRevolverMateba - - id: SpeedLoaderMagnumAP - - id: SpeedLoaderMagnumAP - - id: BoxFlashbang - - id: ToolDebug # spanish army knife - - id: WelderExperimental - - id: Hypospray - - id: DeathAcidifierImplanter # crew will try to steal their amazing hardsuits - - id: FreedomImplanter - -# Cargo - -- type: entity - noSpawn: true - parent: ClothingBackpackCargo - id: ClothingBackpackCargoFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackSalvage - id: ClothingBackpackSalvageFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -# Pirate - -- type: entity - parent: ClothingBackpackSatchelLeather - id: ClothingBackpackPirateFilled - suffix: Filled, Pirate - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Cutlass - - id: WeaponRevolverPirate - - id: ClothingEyesEyepatch diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml deleted file mode 100644 index 477b8b2f18..0000000000 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml +++ /dev/null @@ -1,275 +0,0 @@ -- type: entity - noSpawn: true - parent: ClothingBackpackDuffel - id: ClothingBackpackDuffelFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelClown - id: ClothingBackpackDuffelClownFilled - components: - - type: StorageFill - contents: - - id: BoxHug - - id: RubberStampClown - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelSecurity - id: ClothingBackpackDuffelSecurityFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: MagazinePistol - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelSecurity - id: ClothingBackpackDuffelSecurityFilledDetective - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: ForensicPad - - id: ForensicScanner - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelBrigmedic - id: ClothingBackpackDuffelBrigmedicFilled - components: - - type: StorageFill - contents: - - id: Flash - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelMedical - id: ClothingBackpackDuffelMedicalFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelMedical - id: ClothingBackpackDuffelParamedicFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - - id: EmergencyRollerBedSpawnFolded - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelCaptain - id: ClothingBackpackDuffelCaptainFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- name: StationCharter - #- name: TelescopicBaton -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelEngineering - id: ClothingBackpackDuffelChiefEngineerFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelScience - id: ClothingBackpackDuffelResearchDirectorFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffel - id: ClothingBackpackDuffelHOPFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelMedical - id: ClothingBackpackDuffelCMOFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelCargo - id: ClothingBackpackDuffelQuartermasterFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelSecurity - id: ClothingBackpackDuffelHOSFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: MagazinePistol - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelEngineering - id: ClothingBackpackDuffelEngineeringFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelAtmospherics - id: ClothingBackpackDuffelAtmosphericsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelScience - id: ClothingBackpackDuffelScienceFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelHydroponics - id: ClothingBackpackDuffelHydroponicsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelMime - id: ClothingBackpackDuffelMimeFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: RubberStampMime - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelChemistry - id: ClothingBackpackDuffelChemistryFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffel - id: ClothingBackpackDuffelChaplainFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Bible - - id: RubberStampChaplain - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffel - id: ClothingBackpackDuffelLawyerFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: RubberStampLawyer - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffel - id: ClothingBackpackDuffelMusicianFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: AcousticGuitarInstrument - - id: SaxophoneInstrument - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffel - id: ClothingBackpackDuffelLibrarianFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: BookRandom - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffel - id: ClothingBackpackDuffelDetectiveFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Lighter - - id: CigPackBlack - - id: BoxForensicPad - - id: HandLabeler - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelCargo - id: ClothingBackpackDuffelCargoFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackDuffelSalvage - id: ClothingBackpackDuffelSalvageFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml deleted file mode 100644 index fe41168829..0000000000 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml +++ /dev/null @@ -1,300 +0,0 @@ -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelTools - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Crowbar - - id: Wrench - - id: Screwdriver - - id: Wirecutter - - id: Welder - - id: Multitool - -- type: entity - parent: ClothingBackpackSatchelClown - id: ClothingBackpackSatchelClownFilled - components: - - type: StorageFill - contents: - - id: BoxHug - - id: RubberStampClown - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelSecurity - id: ClothingBackpackSatchelSecurityFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: MagazinePistol - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelSecurity - id: ClothingBackpackSatchelSecurityFilledDetective - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: ForensicPad - - id: ForensicScanner - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelBrigmedic - id: ClothingBackpackSatchelBrigmedicFilled - components: - - type: StorageFill - contents: - - id: Flash - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelMedical - id: ClothingBackpackSatchelMedicalFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelMedical - id: ClothingBackpackSatchelParamedicFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - - id: EmergencyRollerBedSpawnFolded - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelCaptain - id: ClothingBackpackSatchelCaptainFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- name: StationCharter - #- name: TelescopicBaton -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelEngineering - id: ClothingBackpackSatchelChiefEngineerFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelScience - id: ClothingBackpackSatchelResearchDirectorFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelHOPFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelMedical - id: ClothingBackpackSatchelCMOFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelCargo - id: ClothingBackpackSatchelQuartermasterFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Flash - #- id: TelescopicBaton - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelSecurity - id: ClothingBackpackSatchelHOSFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalSecurity - - id: Flash - - id: MagazinePistol - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelEngineering - id: ClothingBackpackSatchelEngineeringFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelAtmospherics - id: ClothingBackpackSatchelAtmosphericsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelScience - id: ClothingBackpackSatchelScienceFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelHydroponics - id: ClothingBackpackSatchelHydroponicsFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelChemistry - id: ClothingBackpackSatchelChemistryFilled - components: - - type: StorageFill - contents: - - id: BoxSurvivalMedical - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelChaplainFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: Bible - - id: RubberStampChaplain - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelLawyerFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: RubberStampLawyer - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelMusicianFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: AcousticGuitarInstrument - - id: SaxophoneInstrument - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelLibrarianFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: BookRandom - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchel - id: ClothingBackpackSatchelDetectiveFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: BoxForensicPad - - id: Lighter - - id: CigPackBlack - - id: HandLabeler - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelCargo - id: ClothingBackpackSatchelCargoFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelSalvage - id: ClothingBackpackSatchelSalvageFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelMime - id: ClothingBackpackSatchelMimeFilled - components: - - type: StorageFill - contents: - - id: BoxSurvival - - id: RubberStampMime - -- type: entity - noSpawn: true - parent: ClothingBackpackSatchelHolding - id: ClothingBackpackSatchelHoldingAdmin - components: - - type: StorageFill - contents: - - id: GasAnalyzer - - id: trayScanner - - id: AccessConfiguratorUniversal - - type: Unremoveable diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml index 4e4b6d9382..ae57ea6342 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml @@ -13,23 +13,6 @@ - id: Retractor - id: Scalpel -- type: entity - id: ClothingBackpackDuffelCBURNFilled - parent: ClothingBackpackDuffelCBURN - suffix: Filled - components: - - type: StorageFill - contents: - - id: BoxSurvivalEngineering - - id: WeaponShotgunDoubleBarreled - - id: BoxShotgunIncendiary - amount: 2 - - id: GrenadeFlashBang - amount: 2 - - id: PillAmbuzolPlus - - id: PillAmbuzol - amount: 4 - - type: entity parent: ClothingBackpackDuffelSyndicateMedicalBundle id: ClothingBackpackDuffelSyndicateFilledMedical @@ -320,38 +303,6 @@ - id: PillAmbuzol amount: 3 -- type: entity - parent: ClothingBackpackDuffelSyndicateBundle - id: ClothingBackpackDuffelSyndicateOperative - name: operative duffelbag - components: - - type: StorageFill - contents: - - id: BoxSurvivalSyndicate - - id: WeaponPistolViper - - id: PinpointerSyndicateNuclear - - id: DeathAcidifierImplanter - - -- type: entity - parent: ClothingBackpackDuffelSyndicateMedicalBundle - id: ClothingBackpackDuffelSyndicateOperativeMedic - name: operative medic duffelbag - description: A large duffel bag for holding extra medical supplies. - components: - - type: StorageFill - contents: - - id: SyndiHypo - - id: BoxSurvivalSyndicate - - id: SawAdvanced - - id: Cautery - - id: CombatKnife - - id: WeaponPistolViper - - id: PinpointerSyndicateNuclear - - id: HandheldHealthAnalyzer - - id: CombatMedipen - - id: DeathAcidifierImplanter - - type: entity parent: ClothingBackpackDuffelSyndicateMedicalBundle id: ClothingBackpackDuffelSyndicateMedicalBundleFilled diff --git a/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml b/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml index 5d9fc64e12..ceaa744295 100644 --- a/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml +++ b/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml @@ -257,6 +257,16 @@ - type: Sprite sprite: Clothing/Back/Backpacks/ertchaplain.rsi +- type: entity + parent: ClothingBackpackERTSecurity + id: ClothingBackpackDeathSquad + name: death squad backpack + description: Holds the kit of CentComm's most feared agents. + components: + - type: Storage + grid: + - 0,0,7,6 + #Syndicate - type: entity parent: ClothingBackpack diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/human.yml b/Resources/Prototypes/Entities/Mobs/NPCs/human.yml index 2133694342..ec2ed5070d 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/human.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/human.yml @@ -7,7 +7,7 @@ - type: InputMover - type: MobMover - type: Loadout - prototypes: [PassengerGear] + prototypes: [LimitedPassengerGear] - type: NpcFactionMember factions: - NanoTrasen diff --git a/Resources/Prototypes/Loadouts/Jobs/Cargo/cargo_technician.yml b/Resources/Prototypes/Loadouts/Jobs/Cargo/cargo_technician.yml index f2922d8cfd..ecc3534458 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Cargo/cargo_technician.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Cargo/cargo_technician.yml @@ -35,7 +35,7 @@ - type: startingGear id: CargoTechnicianBackpack equipment: - back: ClothingBackpackCargoFilled + back: ClothingBackpackCargo - type: loadout id: CargoTechnicianSatchel @@ -44,7 +44,7 @@ - type: startingGear id: CargoTechnicianSatchel equipment: - back: ClothingBackpackSatchelCargoFilled + back: ClothingBackpackSatchelCargo - type: loadout id: CargoTechnicianDuffel @@ -53,7 +53,7 @@ - type: startingGear id: CargoTechnicianDuffel equipment: - back: ClothingBackpackDuffelCargoFilled + back: ClothingBackpackDuffelCargo # OuterClothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Loadouts/Jobs/Cargo/quartermaster.yml index d738306c65..f02da12316 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Cargo/quartermaster.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Cargo/quartermaster.yml @@ -82,34 +82,6 @@ equipment: neck: ClothingNeckMantleQM -# Back -- type: loadout - id: QuartermasterBackpack - equipment: QuartermasterBackpack - -- type: startingGear - id: QuartermasterBackpack - equipment: - back: ClothingBackpackQuartermasterFilled - -- type: loadout - id: QuartermasterSatchel - equipment: QuartermasterSatchel - -- type: startingGear - id: QuartermasterSatchel - equipment: - back: ClothingBackpackSatchelQuartermasterFilled - -- type: loadout - id: QuartermasterDuffel - equipment: QuartermasterDuffel - -- type: startingGear - id: QuartermasterDuffel - equipment: - back: ClothingBackpackDuffelQuartermasterFilled - # OuterClothing - type: loadout id: QuartermasterWintercoat diff --git a/Resources/Prototypes/Loadouts/Jobs/Cargo/salvage_specialist.yml b/Resources/Prototypes/Loadouts/Jobs/Cargo/salvage_specialist.yml index 2b42fab50a..abf787d510 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Cargo/salvage_specialist.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Cargo/salvage_specialist.yml @@ -6,7 +6,7 @@ - type: startingGear id: SalvageSpecialistBackpack equipment: - back: ClothingBackpackSalvageFilled + back: ClothingBackpackSalvage - type: loadout id: SalvageSpecialistSatchel @@ -15,7 +15,7 @@ - type: startingGear id: SalvageSpecialistSatchel equipment: - back: ClothingBackpackSatchelSalvageFilled + back: ClothingBackpackSatchelSalvage - type: loadout id: SalvageSpecialistDuffel @@ -24,7 +24,7 @@ - type: startingGear id: SalvageSpecialistDuffel equipment: - back: ClothingBackpackDuffelSalvageFilled + back: ClothingBackpackDuffelSalvage # OuterClothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Civilian/botanist.yml b/Resources/Prototypes/Loadouts/Jobs/Civilian/botanist.yml index 5ab2cecd15..7dba761a18 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Civilian/botanist.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Civilian/botanist.yml @@ -53,7 +53,7 @@ - type: startingGear id: BotanistBackpack equipment: - back: ClothingBackpackHydroponicsFilled + back: ClothingBackpackHydroponics - type: loadout id: BotanistSatchel @@ -62,7 +62,7 @@ - type: startingGear id: BotanistSatchel equipment: - back: ClothingBackpackSatchelHydroponicsFilled + back: ClothingBackpackSatchelHydroponics - type: loadout id: BotanistDuffel @@ -71,7 +71,7 @@ - type: startingGear id: BotanistDuffel equipment: - back: ClothingBackpackDuffelHydroponicsFilled + back: ClothingBackpackDuffelHydroponics # Outer clothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Civilian/chaplain.yml b/Resources/Prototypes/Loadouts/Jobs/Civilian/chaplain.yml index 623e18a01d..160f06d5cf 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Civilian/chaplain.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Civilian/chaplain.yml @@ -91,34 +91,6 @@ equipment: jumpsuit: ClothingUniformJumpsuitMonasticRobeLight -# Back -- type: loadout - id: ChaplainBackpack - equipment: ChaplainBackpack - -- type: startingGear - id: ChaplainBackpack - equipment: - back: ClothingBackpackChaplainFilled - -- type: loadout - id: ChaplainSatchel - equipment: ChaplainSatchel - -- type: startingGear - id: ChaplainSatchel - equipment: - back: ClothingBackpackSatchelChaplainFilled - -- type: loadout - id: ChaplainDuffel - equipment: ChaplainDuffel - -- type: startingGear - id: ChaplainDuffel - equipment: - back: ClothingBackpackDuffelChaplainFilled - # Neck - type: loadout id: ChaplainNeck diff --git a/Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml b/Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml index 8b315d50c1..d3a3ce2e6c 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml @@ -35,7 +35,7 @@ - type: startingGear id: ClownBackpack equipment: - back: ClothingBackpackClownFilled + back: ClothingBackpackClown - type: loadout id: ClownSatchel @@ -44,7 +44,7 @@ - type: startingGear id: ClownSatchel equipment: - back: ClothingBackpackSatchelClownFilled + back: ClothingBackpackSatchelClown - type: loadout id: ClownDuffel @@ -53,7 +53,7 @@ - type: startingGear id: ClownDuffel equipment: - back: ClothingBackpackDuffelClownFilled + back: ClothingBackpackDuffelClown # Shoes - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Civilian/lawyer.yml b/Resources/Prototypes/Loadouts/Jobs/Civilian/lawyer.yml index 5edd3ecf76..00be124430 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Civilian/lawyer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Civilian/lawyer.yml @@ -97,32 +97,4 @@ - type: startingGear id: LawyerNeck equipment: - neck: ClothingNeckLawyerbadge - -# Backpack -- type: loadout - id: LawyerBackpack - equipment: LawyerBackpack - -- type: startingGear - id: LawyerBackpack - equipment: - back: ClothingBackpackLawyerFilled - -- type: loadout - id: LawyerSatchel - equipment: LawyerSatchel - -- type: startingGear - id: LawyerSatchel - equipment: - back: ClothingBackpackSatchelLawyerFilled - -- type: loadout - id: LawyerDuffel - equipment: LawyerDuffel - -- type: startingGear - id: LawyerDuffel - equipment: - back: ClothingBackpackDuffelLawyerFilled + neck: ClothingNeckLawyerbadge \ No newline at end of file diff --git a/Resources/Prototypes/Loadouts/Jobs/Civilian/mime.yml b/Resources/Prototypes/Loadouts/Jobs/Civilian/mime.yml index 95647052b8..e60b2807ff 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Civilian/mime.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Civilian/mime.yml @@ -81,7 +81,7 @@ - type: startingGear id: MimeBackpack equipment: - back: ClothingBackpackMimeFilled + back: ClothingBackpackMime - type: loadout id: MimeSatchel @@ -90,7 +90,7 @@ - type: startingGear id: MimeSatchel equipment: - back: ClothingBackpackSatchelMimeFilled + back: ClothingBackpackSatchelMime - type: loadout id: MimeDuffel @@ -99,7 +99,7 @@ - type: startingGear id: MimeDuffel equipment: - back: ClothingBackpackDuffelMimeFilled + back: ClothingBackpackDuffelMime # Outerclothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Civilian/musician.yml b/Resources/Prototypes/Loadouts/Jobs/Civilian/musician.yml index 579481c0ee..c26da03628 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Civilian/musician.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Civilian/musician.yml @@ -1,31 +1,3 @@ -# Back -- type: loadout - id: MusicianBackpack - equipment: MusicianBackpack - -- type: startingGear - id: MusicianBackpack - equipment: - back: ClothingBackpackMusicianFilled - -- type: loadout - id: MusicianSatchel - equipment: MusicianSatchel - -- type: startingGear - id: MusicianSatchel - equipment: - back: ClothingBackpackSatchelMusicianFilled - -- type: loadout - id: MusicianDuffel - equipment: MusicianDuffel - -- type: startingGear - id: MusicianDuffel - equipment: - back: ClothingBackpackDuffelMusicianFilled - # Outerclothing - type: loadout id: MusicianWintercoat diff --git a/Resources/Prototypes/Loadouts/Jobs/Civilian/passenger.yml b/Resources/Prototypes/Loadouts/Jobs/Civilian/passenger.yml index 5c09b1299f..84685e1702 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Civilian/passenger.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Civilian/passenger.yml @@ -75,7 +75,7 @@ - type: startingGear id: CommonBackpack equipment: - back: ClothingBackpackFilled + back: ClothingBackpack - type: loadout id: CommonSatchel @@ -84,7 +84,7 @@ - type: startingGear id: CommonSatchel equipment: - back: ClothingBackpackSatchelFilled + back: ClothingBackpackSatchel - type: loadout id: CommonDuffel @@ -93,7 +93,7 @@ - type: startingGear id: CommonDuffel equipment: - back: ClothingBackpackDuffelFilled + back: ClothingBackpackDuffel # Gloves - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Command/captain.yml b/Resources/Prototypes/Loadouts/Jobs/Command/captain.yml index 6ec2d7f789..50786d6154 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Command/captain.yml @@ -90,7 +90,7 @@ - type: startingGear id: CaptainBackpack equipment: - back: ClothingBackpackCaptainFilled + back: ClothingBackpackCaptain - type: loadout id: CaptainSatchel @@ -99,7 +99,7 @@ - type: startingGear id: CaptainSatchel equipment: - back: ClothingBackpackSatchelCaptainFilled + back: ClothingBackpackSatchelCaptain - type: loadout id: CaptainDuffel @@ -108,7 +108,7 @@ - type: startingGear id: CaptainDuffel equipment: - back: ClothingBackpackDuffelCaptainFilled + back: ClothingBackpackDuffelCaptain # Outer clothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Loadouts/Jobs/Command/head_of_personnel.yml index 0abba16f12..1e4e5d527f 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Command/head_of_personnel.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Command/head_of_personnel.yml @@ -57,33 +57,6 @@ neck: ClothingNeckMantleHOP # Back -- type: loadout - id: HoPBackpack - equipment: HoPBackpack - -- type: startingGear - id: HoPBackpack - equipment: - back: ClothingBackpackHOPFilled - -- type: loadout - id: HoPSatchel - equipment: HoPSatchel - -- type: startingGear - id: HoPSatchel - equipment: - back: ClothingBackpackSatchelHOPFilled - -- type: loadout - id: HoPDuffel - equipment: HoPDuffel - -- type: startingGear - id: HoPDuffel - equipment: - back: ClothingBackpackDuffelHOPFilled - - type: loadout id: HoPBackpackIan equipment: HoPBackpackIan @@ -94,7 +67,7 @@ - type: startingGear id: HoPBackpackIan equipment: - back: ClothingBackpackHOPIanFilled + back: ClothingBackpackIan # Outerclothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Engineering/atmospheric_technician.yml b/Resources/Prototypes/Loadouts/Jobs/Engineering/atmospheric_technician.yml index fc9bbbf282..5f1e753b9f 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Engineering/atmospheric_technician.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Engineering/atmospheric_technician.yml @@ -34,7 +34,7 @@ - type: startingGear id: AtmosphericTechnicianBackpack equipment: - back: ClothingBackpackAtmosphericsFilled + back: ClothingBackpackAtmospherics - type: loadout id: AtmosphericTechnicianSatchel @@ -43,7 +43,7 @@ - type: startingGear id: AtmosphericTechnicianSatchel equipment: - back: ClothingBackpackSatchelAtmosphericsFilled + back: ClothingBackpackSatchelAtmospherics - type: loadout id: AtmosphericTechnicianDuffel @@ -52,7 +52,7 @@ - type: startingGear id: AtmosphericTechnicianDuffel equipment: - back: ClothingBackpackDuffelAtmosphericsFilled + back: ClothingBackpackDuffelAtmospherics # OuterClothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Loadouts/Jobs/Engineering/chief_engineer.yml index 2373205066..5bfbb8c201 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Engineering/chief_engineer.yml @@ -68,34 +68,6 @@ equipment: neck: ClothingNeckMantleCE -# Back -- type: loadout - id: ChiefEngineerBackpack - equipment: ChiefEngineerBackpack - -- type: startingGear - id: ChiefEngineerBackpack - equipment: - back: ClothingBackpackChiefEngineerFilled - -- type: loadout - id: ChiefEngineerSatchel - equipment: ChiefEngineerSatchel - -- type: startingGear - id: ChiefEngineerSatchel - equipment: - back: ClothingBackpackSatchelChiefEngineerFilled - -- type: loadout - id: ChiefEngineerDuffel - equipment: ChiefEngineerDuffel - -- type: startingGear - id: ChiefEngineerDuffel - equipment: - back: ClothingBackpackDuffelChiefEngineerFilled - # OuterClothing - type: loadout id: ChiefEngineerWintercoat diff --git a/Resources/Prototypes/Loadouts/Jobs/Engineering/station_engineer.yml b/Resources/Prototypes/Loadouts/Jobs/Engineering/station_engineer.yml index 7104598b3a..7f9e20e2aa 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Engineering/station_engineer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Engineering/station_engineer.yml @@ -118,7 +118,7 @@ - type: startingGear id: StationEngineerBackpack equipment: - back: ClothingBackpackEngineeringFilled + back: ClothingBackpackEngineering - type: loadout id: StationEngineerSatchel @@ -127,7 +127,7 @@ - type: startingGear id: StationEngineerSatchel equipment: - back: ClothingBackpackSatchelEngineeringFilled + back: ClothingBackpackSatchelEngineering - type: loadout id: StationEngineerDuffel @@ -136,7 +136,7 @@ - type: startingGear id: StationEngineerDuffel equipment: - back: ClothingBackpackDuffelEngineeringFilled + back: ClothingBackpackDuffelEngineering # OuterClothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Medical/chemist.yml b/Resources/Prototypes/Loadouts/Jobs/Medical/chemist.yml index 9b05120b1a..289910c8c8 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Medical/chemist.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Medical/chemist.yml @@ -25,7 +25,7 @@ - type: startingGear id: ChemistBackpack equipment: - back: ClothingBackpackChemistryFilled + back: ClothingBackpackChemistry - type: loadout id: ChemistSatchel @@ -34,7 +34,7 @@ - type: startingGear id: ChemistSatchel equipment: - back: ClothingBackpackSatchelChemistryFilled + back: ClothingBackpackSatchelChemistry - type: loadout id: ChemistDuffel @@ -43,7 +43,7 @@ - type: startingGear id: ChemistDuffel equipment: - back: ClothingBackpackDuffelChemistryFilled + back: ClothingBackpackDuffelChemistry # Outer clothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Loadouts/Jobs/Medical/chief_medical_officer.yml index 8cf8148518..f7436a4281 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Medical/chief_medical_officer.yml @@ -73,34 +73,6 @@ equipment: neck: ClothingNeckMantleCMO -# Back -- type: loadout - id: ChiefMedicalOfficerBackpack - equipment: ChiefMedicalOfficerBackpack - -- type: startingGear - id: ChiefMedicalOfficerBackpack - equipment: - back: ClothingBackpackCMOFilled - -- type: loadout - id: ChiefMedicalOfficerSatchel - equipment: ChiefMedicalOfficerSatchel - -- type: startingGear - id: ChiefMedicalOfficerSatchel - equipment: - back: ClothingBackpackSatchelCMOFilled - -- type: loadout - id: ChiefMedicalOfficerDuffel - equipment: ChiefMedicalOfficerDuffel - -- type: startingGear - id: ChiefMedicalOfficerDuffel - equipment: - back: ClothingBackpackDuffelCMOFilled - # Outer clothing - type: loadout id: ChiefMedicalOfficerLabCoat diff --git a/Resources/Prototypes/Loadouts/Jobs/Medical/medical_doctor.yml b/Resources/Prototypes/Loadouts/Jobs/Medical/medical_doctor.yml index ebad9b9f84..a64d60ba1f 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Medical/medical_doctor.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Medical/medical_doctor.yml @@ -178,7 +178,7 @@ - type: startingGear id: MedicalDoctorBackpack equipment: - back: ClothingBackpackMedicalFilled + back: ClothingBackpackMedical - type: loadout id: MedicalDoctorSatchel @@ -187,7 +187,7 @@ - type: startingGear id: MedicalDoctorSatchel equipment: - back: ClothingBackpackSatchelMedicalFilled + back: ClothingBackpackSatchelMedical - type: loadout id: MedicalDoctorDuffel @@ -196,7 +196,7 @@ - type: startingGear id: MedicalDoctorDuffel equipment: - back: ClothingBackpackDuffelMedicalFilled + back: ClothingBackpackDuffelMedical # OuterClothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml b/Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml index f393109eea..7fd8d4a32f 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml @@ -27,34 +27,6 @@ equipment: jumpsuit: ClothingUniformJumpskirtParamedic -# Back -- type: loadout - id: ParamedicBackpack - equipment: ParamedicBackpack - -- type: startingGear - id: ParamedicBackpack - equipment: - back: ClothingBackpackParamedicFilled - -- type: loadout - id: ParamedicSatchel - equipment: ParamedicSatchel - -- type: startingGear - id: ParamedicSatchel - equipment: - back: ClothingBackpackSatchelParamedicFilled - -- type: loadout - id: ParamedicDuffel - equipment: ParamedicDuffel - -- type: startingGear - id: ParamedicDuffel - equipment: - back: ClothingBackpackDuffelParamedicFilled - # Outer clothing - type: loadout id: ParamedicWindbreaker diff --git a/Resources/Prototypes/Loadouts/Jobs/Science/research_director.yml b/Resources/Prototypes/Loadouts/Jobs/Science/research_director.yml index 4d81b801e8..748e5d217c 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Science/research_director.yml @@ -43,34 +43,6 @@ equipment: jumpsuit: ClothingUniformJumpskirtResearchDirector -# Back -- type: loadout - id: ResearchDirectorBackpack - equipment: ResearchDirectorBackpack - -- type: startingGear - id: ResearchDirectorBackpack - equipment: - back: ClothingBackpackResearchDirectorFilled - -- type: loadout - id: ResearchDirectorSatchel - equipment: ResearchDirectorSatchel - -- type: startingGear - id: ResearchDirectorSatchel - equipment: - back: ClothingBackpackSatchelResearchDirectorFilled - -- type: loadout - id: ResearchDirectorDuffel - equipment: ResearchDirectorDuffel - -- type: startingGear - id: ResearchDirectorDuffel - equipment: - back: ClothingBackpackDuffelResearchDirectorFilled - # OuterClothing - type: loadout id: ResearchDirectorLabCoat diff --git a/Resources/Prototypes/Loadouts/Jobs/Science/scientist.yml b/Resources/Prototypes/Loadouts/Jobs/Science/scientist.yml index c03ae4cfbc..ee30a9cf41 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Science/scientist.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Science/scientist.yml @@ -120,7 +120,7 @@ - type: startingGear id: ScientistBackpack equipment: - back: ClothingBackpackScienceFilled + back: ClothingBackpackScience - type: loadout id: ScientistSatchel @@ -129,7 +129,7 @@ - type: startingGear id: ScientistSatchel equipment: - back: ClothingBackpackSatchelScienceFilled + back: ClothingBackpackSatchelScience - type: loadout id: ScientistDuffel @@ -138,7 +138,7 @@ - type: startingGear id: ScientistDuffel equipment: - back: ClothingBackpackDuffelScienceFilled + back: ClothingBackpackDuffelScience # OuterClothing - type: loadout diff --git a/Resources/Prototypes/Loadouts/Jobs/Security/detective.yml b/Resources/Prototypes/Loadouts/Jobs/Security/detective.yml index c16d24e5b8..888ed971e1 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Security/detective.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Security/detective.yml @@ -64,34 +64,6 @@ equipment: jumpsuit: ClothingUniformJumpskirtDetectiveGrey -# Back -- type: loadout - id: DetectiveBackpack - equipment: DetectiveBackpack - -- type: startingGear - id: DetectiveBackpack - equipment: - back: ClothingBackpackSecurityFilledDetective - -- type: loadout - id: DetectiveSatchel - equipment: DetectiveSatchel - -- type: startingGear - id: DetectiveSatchel - equipment: - back: ClothingBackpackSatchelSecurityFilledDetective - -- type: loadout - id: DetectiveDuffel - equipment: DetectiveDuffel - -- type: startingGear - id: DetectiveDuffel - equipment: - back: ClothingBackpackDuffelSecurityFilledDetective - # OuterClothing - type: loadout id: DetectiveArmorVest diff --git a/Resources/Prototypes/Loadouts/Jobs/Security/security_officer.yml b/Resources/Prototypes/Loadouts/Jobs/Security/security_officer.yml index b2b9e1e0c1..321cc46feb 100644 --- a/Resources/Prototypes/Loadouts/Jobs/Security/security_officer.yml +++ b/Resources/Prototypes/Loadouts/Jobs/Security/security_officer.yml @@ -110,7 +110,7 @@ - type: startingGear id: SecurityBackpack equipment: - back: ClothingBackpackSecurityFilled + back: ClothingBackpackSecurity - type: loadout id: SecuritySatchel @@ -119,7 +119,7 @@ - type: startingGear id: SecuritySatchel equipment: - back: ClothingBackpackSatchelSecurityFilled + back: ClothingBackpackSatchelSecurity - type: loadout id: SecurityDuffel @@ -128,7 +128,7 @@ - type: startingGear id: SecurityDuffel equipment: - back: ClothingBackpackDuffelSecurityFilled + back: ClothingBackpackDuffelSecurity # Belt - type: loadout diff --git a/Resources/Prototypes/Loadouts/loadout_groups.yml b/Resources/Prototypes/Loadouts/loadout_groups.yml index d889514a33..7f8a9ff4e4 100644 --- a/Resources/Prototypes/Loadouts/loadout_groups.yml +++ b/Resources/Prototypes/Loadouts/loadout_groups.yml @@ -103,9 +103,9 @@ id: HoPBackpack name: loadout-group-hop-backpack loadouts: - - HoPBackpack - - HoPSatchel - - HoPDuffel + - CommonBackpack + - CommonSatchel + - CommonDuffel - HoPBackpackIan - type: loadoutGroup @@ -122,8 +122,8 @@ loadouts: - GreyJumpsuit - GreyJumpskirt - - RainbowJumpsuit - AncientJumpsuit + - RainbowJumpsuit - type: loadoutGroup id: PassengerFace @@ -141,7 +141,7 @@ - type: loadoutGroup id: CommonBackpack - name: loadout-group-passenger-backpack + name: loadout-group-backpack loadouts: - CommonBackpack - CommonSatchel @@ -247,14 +247,6 @@ loadouts: - LawyerNeck -- type: loadoutGroup - id: LawyerBackpack - name: loadout-group-lawyer-backpack - loadouts: - - LawyerBackpack - - LawyerSatchel - - LawyerDuffel - - type: loadoutGroup id: ChaplainHead name: loadout-group-chaplain-head @@ -282,14 +274,6 @@ - ChaplainRobesLight - ChaplainRobesDark -- type: loadoutGroup - id: ChaplainBackpack - name: loadout-group-chaplain-backpack - loadouts: - - ChaplainBackpack - - ChaplainSatchel - - ChaplainDuffel - - type: loadoutGroup id: ChaplainOuterClothing name: loadout-group-chaplain-outerclothing @@ -446,14 +430,6 @@ loadouts: - MimeWintercoat -- type: loadoutGroup - id: MusicianBackpack - name: loadout-group-musician-backpack - loadouts: - - MusicianBackpack - - MusicianSatchel - - MusicianDuffel - - type: loadoutGroup id: MusicianOuterClothing name: loadout-group-musician-outerclothing @@ -480,14 +456,6 @@ - QuartermasterTurtleneckSkirt - QuartermasterFormalSuit -- type: loadoutGroup - id: QuartermasterBackpack - name: loadout-group-quartermaster-backpack - loadouts: - - QuartermasterBackpack - - QuartermasterSatchel - - QuartermasterDuffel - - type: loadoutGroup id: QuartermasterNeck name: loadout-group-quartermaster-neck @@ -586,14 +554,6 @@ - ChiefEngineerTurtleneck - ChiefEngineerTurtleneckSkirt -- type: loadoutGroup - id: ChiefEngineerBackpack - name: loadout-group-chief-engineer-backpack - loadouts: - - ChiefEngineerBackpack - - ChiefEngineerSatchel - - ChiefEngineerDuffel - - type: loadoutGroup id: ChiefEngineerNeck name: loadout-group-chief-engineer-neck @@ -725,14 +685,6 @@ - ResearchDirectorJumpsuit - ResearchDirectorJumpskirt -- type: loadoutGroup - id: ResearchDirectorBackpack - name: loadout-group-research-director-backpack - loadouts: - - ResearchDirectorBackpack - - ResearchDirectorSatchel - - ResearchDirectorDuffel - - type: loadoutGroup id: ResearchDirectorOuterClothing name: loadout-group-research-director-outerclothing @@ -964,14 +916,6 @@ - NoirJumpsuit - NoirJumpskirt -- type: loadoutGroup - id: DetectiveBackpack - name: loadout-group-detective-backpack - loadouts: - - DetectiveBackpack - - DetectiveSatchel - - DetectiveDuffel - - type: loadoutGroup id: DetectiveOuterClothing name: loadout-group-detective-outerclothing @@ -1013,14 +957,6 @@ - ChiefMedicalOfficerLabCoat - ChiefMedicalOfficerWintercoat -- type: loadoutGroup - id: ChiefMedicalOfficerBackpack - name: loadout-group-chief-medical-officer-backpack - loadouts: - - ChiefMedicalOfficerBackpack - - ChiefMedicalOfficerSatchel - - ChiefMedicalOfficerDuffel - - type: loadoutGroup id: ChiefMedicalOfficerNeck name: loadout-group-chief-medical-officer-neck @@ -1160,14 +1096,6 @@ - ParamedicWindbreaker - ParamedicWintercoat -- type: loadoutGroup - id: ParamedicBackpack - name: loadout-group-paramedic-backpack - loadouts: - - ParamedicBackpack - - ParamedicSatchel - - ParamedicDuffel - - type: loadoutGroup id: ParamedicShoes name: loadout-group-paramedic-shoes diff --git a/Resources/Prototypes/Loadouts/role_loadouts.yml b/Resources/Prototypes/Loadouts/role_loadouts.yml index 5bc6fc4572..4ff2775dfc 100644 --- a/Resources/Prototypes/Loadouts/role_loadouts.yml +++ b/Resources/Prototypes/Loadouts/role_loadouts.yml @@ -75,7 +75,7 @@ groups: - LawyerNeck - LawyerJumpsuit - - LawyerBackpack + - CommonBackpack - Glasses - Trinkets @@ -86,7 +86,7 @@ - ChaplainMask - ChaplainNeck - ChaplainJumpsuit - - ChaplainBackpack + - CommonBackpack - ChaplainOuterClothing - Glasses - Trinkets @@ -137,7 +137,7 @@ - type: roleLoadout id: JobMusician groups: - - MusicianBackpack + - CommonBackpack - MusicianOuterClothing - Glasses - Trinkets @@ -149,7 +149,7 @@ - QuartermasterHead - QuartermasterNeck - QuartermasterJumpsuit - - QuartermasterBackpack + - CargoTechnicianBackpack - QuartermasterOuterClothing - QuartermasterShoes - Glasses @@ -181,7 +181,7 @@ groups: - ChiefEngineerHead - ChiefEngineerJumpsuit - - ChiefEngineerBackpack + - StationEngineerBackpack - ChiefEngineerNeck - ChiefEngineerOuterClothing - ChiefEngineerShoes @@ -221,7 +221,7 @@ - ResearchDirectorHead - ResearchDirectorNeck - ResearchDirectorJumpsuit - - ResearchDirectorBackpack + - ScientistBackpack - ResearchDirectorOuterClothing - ScientistGloves - ResearchDirectorShoes @@ -292,7 +292,7 @@ - DetectiveHead - DetectiveNeck - DetectiveJumpsuit - - DetectiveBackpack + - SecurityBackpack - DetectiveOuterClothing - SecurityShoes - Trinkets @@ -312,7 +312,7 @@ - MedicalMask - ChiefMedicalOfficerJumpsuit - MedicalGloves - - ChiefMedicalOfficerBackpack + - MedicalBackpack - ChiefMedicalOfficerOuterClothing - ChiefMedicalOfficerNeck - ChiefMedicalOfficerShoes @@ -359,7 +359,7 @@ - MedicalMask - ParamedicJumpsuit - MedicalGloves - - ParamedicBackpack + - MedicalBackpack - ParamedicOuterClothing - ParamedicShoes - Glasses diff --git a/Resources/Prototypes/Roles/Antags/Thief.yml b/Resources/Prototypes/Roles/Antags/Thief.yml index 131db8cf1d..d85d366f6b 100644 --- a/Resources/Prototypes/Roles/Antags/Thief.yml +++ b/Resources/Prototypes/Roles/Antags/Thief.yml @@ -4,3 +4,10 @@ antagonist: true setPreference: true objective: roles-antag-thief-objective + +- type: startingGear + id: ThiefGear + storage: + back: + - ToolboxThief + - ClothingHandsChameleonThief \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Antags/ninja.yml b/Resources/Prototypes/Roles/Antags/ninja.yml index a7492bd1b1..cb32dc2c10 100644 --- a/Resources/Prototypes/Roles/Antags/ninja.yml +++ b/Resources/Prototypes/Roles/Antags/ninja.yml @@ -4,3 +4,33 @@ antagonist: true setPreference: false objective: roles-antag-space-ninja-objective + +#Ninja Gear +- type: startingGear + id: SpaceNinjaGear + equipment: + jumpsuit: ClothingUniformJumpsuitNinja + back: ClothingBackpackSatchel + mask: ClothingMaskNinja + head: ClothingHeadHelmetSpaceNinja + eyes: ClothingEyesVisorNinja + gloves: ClothingHandsGlovesSpaceNinja + outerClothing: ClothingOuterSuitSpaceNinja + shoes: ClothingShoesSpaceNinja + id: AgentIDCard + ears: ClothingHeadsetGrey + pocket1: SpiderCharge + pocket2: PinpointerStation + belt: EnergyKatana + suitstorage: OxygenTankFilled + inhand: + - JetpackBlackFilled + storage: + back: # belt holds katana so satchel has the tools for sabotaging things + - BoxSurvival + - Crowbar + - Wrench + - Screwdriver + - Wirecutter + - Welder + - Multitool \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Antags/nukeops.yml b/Resources/Prototypes/Roles/Antags/nukeops.yml index 4075005e68..e91d50f53c 100644 --- a/Resources/Prototypes/Roles/Antags/nukeops.yml +++ b/Resources/Prototypes/Roles/Antags/nukeops.yml @@ -34,3 +34,66 @@ department: Security time: 18000 # 5h # should be changed to nukie playtime when thats tracked (wyci) + +#Nuclear Operative Gear +- type: startingGear + id: SyndicateOperativeGearFull + equipment: + jumpsuit: ClothingUniformJumpsuitOperative + back: ClothingBackpackDuffelSyndicate + mask: ClothingMaskGasSyndicate + eyes: ClothingEyesHudSyndicate + ears: ClothingHeadsetAltSyndicate + gloves: ClothingHandsGlovesCombat + outerClothing: ClothingOuterHardsuitSyndie + shoes: ClothingShoesBootsCombatFilled + id: SyndiPDA + pocket1: DoubleEmergencyOxygenTankFilled + pocket2: BaseUplinkRadio40TC + belt: ClothingBeltMilitaryWebbing + storage: + back: + - BoxSurvivalSyndicate + - WeaponPistolViper + - PinpointerSyndicateNuclear + - DeathAcidifierImplanter + +#Nuclear Operative Commander Gear +- type: startingGear + id: SyndicateCommanderGearFull + parent: SyndicateOperativeGearFull + equipment: + neck: SyndicateWhistle + outerClothing: ClothingOuterHardsuitSyndieCommander + inhand: + - NukeOpsDeclarationOfWar + +#Nuclear Operative Medic Gear +- type: startingGear + id: SyndicateOperativeMedicFull + parent: SyndicateOperativeGearFull + equipment: + eyes: ClothingEyesHudSyndicateAgent + outerClothing: ClothingOuterHardsuitSyndieMedic + shoes: ClothingShoesBootsMagSyndie + id: SyndiAgentPDA + belt: ClothingBeltMilitaryWebbingMedFilled + storage: + back: + - SyndiHypo + - BoxSurvivalSyndicate + - SawAdvanced + - Cautery + - CombatKnife + - WeaponPistolViper + - PinpointerSyndicateNuclear + - HandheldHealthAnalyzer + - CombatMedipen + - DeathAcidifierImplanter + +#Lone Operative Gear +- type: startingGear + id: SyndicateLoneOperativeGearFull + parent: SyndicateOperativeGearFull + equipment: + pocket2: BaseUplinkRadio60TC \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Antags/pirate.yml b/Resources/Prototypes/Roles/Antags/pirate.yml index 235ccfdab8..849e9dc1f2 100644 --- a/Resources/Prototypes/Roles/Antags/pirate.yml +++ b/Resources/Prototypes/Roles/Antags/pirate.yml @@ -2,7 +2,7 @@ id: PirateGear equipment: jumpsuit: ClothingUniformJumpsuitPirate - back: ClothingBackpackPirateFilled + back: ClothingBackpackSatchelLeather head: ClothingHeadBandBlack shoes: ClothingShoesBootsLaceup id: PiratePDA @@ -11,25 +11,15 @@ - type: startingGear id: PirateCaptainGear + parent: PirateGear equipment: - jumpsuit: ClothingUniformJumpsuitPirate - back: ClothingBackpackPirateFilled head: ClothingHeadHatPirate - shoes: ClothingShoesBootsLaceup - id: PiratePDA - belt: ClothingBeltUtility - pocket1: AppraisalTool pocket2: EnergyCutlass outerClothing: ClothingOuterCoatPirate - type: startingGear id: PirateFirstmateGear + parent: PirateGear equipment: - jumpsuit: ClothingUniformJumpsuitPirate - back: ClothingBackpackPirateFilled head: ClothingHeadHatPirateTricord - shoes: ClothingShoesBootsLaceup - id: PiratePDA - belt: ClothingBeltUtility - pocket1: AppraisalTool outerClothing: ClothingOuterCoatGentle diff --git a/Resources/Prototypes/Roles/Antags/revolutionary.yml b/Resources/Prototypes/Roles/Antags/revolutionary.yml index c5e6cb8149..3bdc9d7977 100644 --- a/Resources/Prototypes/Roles/Antags/revolutionary.yml +++ b/Resources/Prototypes/Roles/Antags/revolutionary.yml @@ -11,3 +11,10 @@ antagonist: true setPreference: false objective: roles-antag-rev-objective + +- type: startingGear + id: HeadRevGear + storage: + back: + - Flash + - ClothingEyesGlassesSunglasses \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Antags/traitor.yml b/Resources/Prototypes/Roles/Antags/traitor.yml index a4e1fe8d10..f192733b7e 100644 --- a/Resources/Prototypes/Roles/Antags/traitor.yml +++ b/Resources/Prototypes/Roles/Antags/traitor.yml @@ -4,3 +4,36 @@ antagonist: true setPreference: true objective: roles-antag-syndicate-agent-objective + +# Syndicate Operative Outfit - Monkey +- type: startingGear + id: SyndicateOperativeGearMonkey + equipment: + head: ClothingHeadHatOutlawHat + jumpsuit: ClothingUniformJumpsuitOperative + mask: CigaretteSyndicate + +# Syndicate Operative Outfit - Barratry +- type: startingGear + id: SyndicateOperativeGearExtremelyBasic + equipment: + jumpsuit: ClothingUniformJumpsuitOperative + back: ClothingBackpackSyndicate + shoes: ClothingShoesBootsCombatFilled + gloves: ClothingHandsGlovesColorBlack + storage: + back: + - BoxSurvivalSyndicate + - WeaponPistolViper + - PinpointerSyndicateNuclear + - DeathAcidifierImplanter + +#Syndicate Operative Outfit - Basic +- type: startingGear + id: SyndicateOperativeGearBasic + parent: SyndicateOperativeGearExtremelyBasic + equipment: + ears: ClothingHeadsetAltSyndicate + gloves: ClothingHandsGlovesCombat + pocket1: BaseUplinkRadio40TC + id: SyndiPDA \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml index 46c5273549..78ab1847a4 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml @@ -17,4 +17,7 @@ equipment: id: CargoPDA ears: ClothingHeadsetCargo - pocket1: AppraisalTool \ No newline at end of file + pocket1: AppraisalTool + storage: + back: + - BoxSurvival \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml index 36d904c56e..e39c327e90 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml @@ -41,4 +41,8 @@ id: QuartermasterPDA ears: ClothingHeadsetQM belt: BoxFolderClipboard - pocket1: AppraisalTool \ No newline at end of file + pocket1: AppraisalTool + storage: + back: + - BoxSurvival + - Flash \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/salvage_specialist.yml b/Resources/Prototypes/Roles/Jobs/Cargo/salvage_specialist.yml index 7b3fcd6b58..4dd20f51fb 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/salvage_specialist.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/salvage_specialist.yml @@ -23,4 +23,7 @@ equipment: jumpsuit: ClothingUniformJumpsuitSalvageSpecialist id: SalvagePDA - ears: ClothingHeadsetCargo \ No newline at end of file + ears: ClothingHeadsetCargo + storage: + back: + - BoxSurvival \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml index b43f929d69..06b66448cb 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml @@ -14,3 +14,6 @@ equipment: id: PassengerPDA ears: ClothingHeadsetGrey + storage: + back: + - BoxSurvival diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml index a49e3cef7f..6bceebc65e 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml @@ -24,3 +24,6 @@ shoes: ClothingShoesColorBlack id: BartenderPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml index feed9e7e6b..e8cda18914 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml @@ -21,3 +21,6 @@ id: BotanistPDA ears: ClothingHeadsetService belt: ClothingBeltPlantFilled + storage: + back: + - BoxSurvival diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml index e3dc1cb23d..0ae49f853c 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml @@ -20,3 +20,8 @@ shoes: ClothingShoesColorBlack id: ChaplainPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival + - Bible + - RubberStampChaplain diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml index 1dda98bb37..0d8d1911e5 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml @@ -25,3 +25,6 @@ id: ChefPDA ears: ClothingHeadsetService belt: ClothingBeltChefFilled + storage: + back: + - BoxSurvival diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml index c70b4a9943..627469f6c5 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml @@ -32,4 +32,9 @@ pocket1: BikeHorn pocket2: ClownRecorder id: ClownPDA - ears: ClothingHeadsetService \ No newline at end of file + ears: ClothingHeadsetService + storage: + back: + - BoxHug + - RubberStampClown + - CrayonRainbow \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml index b768bd25be..9b006cbed1 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml @@ -32,3 +32,6 @@ head: ClothingHeadHatCatEars ears: ClothingHeadsetService belt: ClothingBeltJanitorFilled + storage: + back: + - BoxSurvival diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml b/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml index 1a321aff40..3ec0eba51c 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/lawyer.yml @@ -24,3 +24,7 @@ # TODO add copy of space law inhand: - BriefcaseBrownFilled + storage: + back: + - BoxSurvival + - RubberStampLawyer diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/librarian.yml b/Resources/Prototypes/Roles/Jobs/Civilian/librarian.yml index 909d8da19d..f5826b76bf 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/librarian.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/librarian.yml @@ -18,3 +18,7 @@ ears: ClothingHeadsetService pocket1: d10Dice pocket2: HandLabeler # for making named bestsellers + storage: + back: + - BoxSurvival + - BookRandom diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml index 27a164210b..b7e932acb4 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml @@ -28,6 +28,10 @@ pocket2: Paper id: MimePDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival + - RubberStampMime - type: entity id: ActionMimeInvisibleWall diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/musician.yml b/Resources/Prototypes/Roles/Jobs/Civilian/musician.yml index 1ba1e998f6..4b508c907d 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/musician.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/musician.yml @@ -21,4 +21,9 @@ eyes: ClothingEyesGlassesSunglasses shoes: ClothingShoesBootsLaceup id: MusicianPDA - ears: ClothingHeadsetService \ No newline at end of file + ears: ClothingHeadsetService + storage: + back: + - BoxSurvival + - AcousticGuitarInstrument + - SaxophoneInstrument \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/service_worker.yml b/Resources/Prototypes/Roles/Jobs/Civilian/service_worker.yml index db23826673..efda20712f 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/service_worker.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/service_worker.yml @@ -21,3 +21,6 @@ shoes: ClothingShoesColorBlack id: ServiceWorkerPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml index dd7445670a..1e93ff73cc 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml @@ -40,3 +40,8 @@ gloves: ClothingHandsGlovesCaptain id: CaptainPDA ears: ClothingHeadsetAltCommand + storage: + back: + - BoxSurvival + - Flash + # - StationCharter \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml index 5f119b6434..72a862f264 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml @@ -64,3 +64,7 @@ gloves: ClothingHandsGlovesHop ears: ClothingHeadsetAltCommand belt: BoxFolderClipboard + storage: + back: + - BoxSurvival + - Flash \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml b/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml index 01af70888d..49a8978633 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml @@ -23,3 +23,6 @@ id: AtmosPDA belt: ClothingBeltUtilityEngineering ears: ClothingHeadsetEngineering + storage: + back: + - BoxSurvivalEngineering \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml index c55fbfbd41..8cc934d634 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml @@ -44,3 +44,7 @@ eyes: ClothingEyesGlassesMeson ears: ClothingHeadsetCE belt: ClothingBeltUtilityEngineering + storage: + back: + - BoxSurvivalEngineering + - Flash \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml index d378479681..1bff9257bb 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml @@ -23,3 +23,6 @@ eyes: ClothingEyesGlassesMeson belt: ClothingBeltUtilityEngineering ears: ClothingHeadsetEngineering + storage: + back: + - BoxSurvivalEngineering \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml b/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml index f3b21e6444..8bbaf2a390 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/technical_assistant.yml @@ -26,4 +26,7 @@ id: TechnicalAssistantPDA belt: ClothingBeltUtilityEngineering ears: ClothingHeadsetEngineering - pocket2: BookEngineersHandbook \ No newline at end of file + pocket2: BookEngineersHandbook + storage: + back: + - BoxSurvivalEngineering \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Fun/cult_startinggear.yml b/Resources/Prototypes/Roles/Jobs/Fun/cult_startinggear.yml index 8748367830..5542a7a69d 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/cult_startinggear.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/cult_startinggear.yml @@ -3,21 +3,27 @@ id: CultLeaderGear equipment: jumpsuit: ClothingUniformJumpsuitColorBlack - back: ClothingBackpackFilled + back: ClothingBackpack head: ClothingHeadHelmetCult neck: BedsheetCult outerClothing: ClothingOuterArmorCult shoes: ClothingShoesCult id: PassengerPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival - type: startingGear id: CultistGear equipment: jumpsuit: ClothingUniformJumpsuitColorBlack - back: ClothingBackpackFilled + back: ClothingBackpack head: ClothingHeadHatHoodCulthood outerClothing: ClothingOuterRobesCult shoes: ClothingShoesColorRed id: PassengerPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival diff --git a/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml b/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml index f37085e005..337b7e1de9 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/emergencyresponseteam.yml @@ -18,7 +18,7 @@ id: ERTLeaderGear equipment: jumpsuit: ClothingUniformJumpsuitERTLeader - back: ClothingBackpackERTLeaderFilled + back: ClothingBackpackERTLeader shoes: ClothingShoesBootsCombatFilled head: ClothingHeadHelmetERTLeader eyes: ClothingEyesGlassesSecurity @@ -29,12 +29,21 @@ belt: ClothingBeltSecurityFilled pocket1: WeaponPistolN1984 pocket2: FlashlightSeclite + storage: + back: + - BoxSurvivalEngineering + - WeaponDisabler + - MedicatedSuture + - RegenerativeMesh + - BoxZiptie + - CrowbarRed + - MagazineMagnum - type: startingGear id: ERTLeaderGearEVA equipment: jumpsuit: ClothingUniformJumpsuitERTLeader - back: ClothingBackpackERTLeaderFilled + back: ClothingBackpackERTLeader shoes: ClothingShoesBootsMagAdv mask: ClothingMaskGasERT eyes: ClothingEyesGlassesSecurity @@ -46,12 +55,21 @@ belt: ClothingBeltSecurityFilled pocket1: WeaponPistolN1984 pocket2: FlashlightSeclite + storage: + back: + - BoxSurvivalEngineering + - WeaponDisabler + - MedicatedSuture + - RegenerativeMesh + - BoxZiptie + - CrowbarRed + - MagazineMagnum - type: startingGear id: ERTLeaderGearEVALecter equipment: jumpsuit: ClothingUniformJumpsuitERTLeader - back: ClothingBackpackERTLeaderFilled + back: ClothingBackpackERTLeader shoes: ClothingShoesBootsMagAdv mask: ClothingMaskGasERT eyes: ClothingEyesGlassesSecurity @@ -65,6 +83,15 @@ pocket2: MagazineRifle inhand: - AirTankFilled + storage: + back: + - BoxSurvivalEngineering + - WeaponDisabler + - MedicatedSuture + - RegenerativeMesh + - BoxZiptie + - CrowbarRed + - MagazineMagnum # Chaplain - type: job @@ -90,7 +117,7 @@ id: ERTChaplainGear equipment: jumpsuit: ClothingUniformJumpsuitERTChaplain - back: ClothingBackpackERTChaplainFilled + back: ClothingBackpackERTChaplain shoes: ClothingShoesLeather head: ClothingHeadHatFez eyes: ClothingEyesGlasses @@ -102,12 +129,27 @@ belt: ClothingBeltStorageWaistbag pocket1: Flare pocket2: DrinkWaterBottleFull + storage: + back: + - BoxSurvivalEngineering + - BoxCandle + - BoxBodyBag + - DrinkWaterMelonJuiceJug + - Lantern + - Lantern + - Bible + - CrowbarRed + - FoodBakedBunHotX + - FoodBakedBunHotX + - FoodBakedBunHotX + - FoodBakedBunHotX + - Lighter - type: startingGear id: ERTChaplainGearEVA equipment: jumpsuit: ClothingUniformJumpsuitERTChaplain - back: ClothingBackpackERTChaplainFilled + back: ClothingBackpackERTChaplain shoes: ClothingShoesBootsMagAdv mask: ClothingMaskGasERT eyes: ClothingEyesGlasses @@ -120,6 +162,21 @@ belt: ClothingBeltStorageWaistbag pocket1: Flare pocket2: DrinkWaterBottleFull + storage: + back: + - BoxSurvivalEngineering + - BoxCandle + - BoxBodyBag + - DrinkWaterMelonJuiceJug + - Lantern + - Lantern + - Bible + - CrowbarRed + - FoodBakedBunHotX + - FoodBakedBunHotX + - FoodBakedBunHotX + - FoodBakedBunHotX + - Lighter # Engineer - type: job @@ -141,7 +198,7 @@ id: ERTEngineerGear equipment: jumpsuit: ClothingUniformJumpsuitERTEngineer - back: ClothingBackpackERTEngineerFilled + back: ClothingBackpackERTEngineer shoes: ClothingShoesBootsWork head: ClothingHeadHelmetERTEngineer eyes: ClothingEyesGlassesMeson @@ -152,12 +209,25 @@ belt: ClothingBeltChiefEngineerFilled pocket1: Flare pocket2: GasAnalyzer + storage: + back: + - BoxSurvivalEngineering + - trayScanner + - RCD + - RCDAmmo + - RCDAmmo + - CableMVStack + - CableHVStack + - CableApcStack + - SheetPlasteel + - SheetSteel + - SheetGlass - type: startingGear id: ERTEngineerGearEVA equipment: jumpsuit: ClothingUniformJumpsuitERTEngineer - back: ClothingBackpackERTEngineerFilled + back: ClothingBackpackERTEngineer shoes: ClothingShoesBootsMagAdv mask: ClothingMaskGasERT eyes: ClothingEyesGlassesMeson @@ -169,6 +239,19 @@ belt: ClothingBeltChiefEngineerFilled pocket1: Flare pocket2: GasAnalyzer + storage: + back: + - BoxSurvivalEngineering + - trayScanner + - RCD + - RCDAmmo + - RCDAmmo + - CableMVStack + - CableHVStack + - CableApcStack + - SheetPlasteel + - SheetSteel + - SheetGlass # Security - type: job @@ -190,7 +273,7 @@ id: ERTSecurityGear equipment: jumpsuit: ClothingUniformJumpsuitERTSecurity - back: ClothingBackpackERTSecurityFilled + back: ClothingBackpackERTSecurity shoes: ClothingShoesBootsCombatFilled head: ClothingHeadHelmetERTSecurity eyes: ClothingEyesGlassesSecurity @@ -201,12 +284,21 @@ belt: ClothingBeltSecurityFilled pocket1: WeaponPistolMk58 pocket2: FlashlightSeclite + storage: + back: + - BoxSurvivalEngineering + - WeaponDisabler + - MedicatedSuture + - RegenerativeMesh + - BoxZiptie + - CrowbarRed + - MagazinePistol - type: startingGear id: ERTSecurityGearEVA equipment: jumpsuit: ClothingUniformJumpsuitERTSecurity - back: ClothingBackpackERTSecurityFilled + back: ClothingBackpackERTSecurity shoes: ClothingShoesBootsMag mask: ClothingMaskGasERT eyes: ClothingEyesGlassesSecurity @@ -218,12 +310,21 @@ belt: ClothingBeltSecurityFilled pocket1: WeaponPistolMk58 pocket2: FlashlightSeclite + storage: + back: + - BoxSurvivalEngineering + - WeaponDisabler + - MedicatedSuture + - RegenerativeMesh + - BoxZiptie + - CrowbarRed + - MagazinePistol - type: startingGear id: ERTSecurityGearEVALecter equipment: jumpsuit: ClothingUniformJumpsuitERTSecurity - back: ClothingBackpackERTSecurityFilled + back: ClothingBackpackERTSecurity shoes: ClothingShoesBootsMag mask: ClothingMaskGasERT eyes: ClothingEyesGlassesSecurity @@ -237,6 +338,15 @@ pocket2: MagazineRifle inhand: - AirTankFilled + storage: + back: + - BoxSurvivalEngineering + - WeaponDisabler + - MedicatedSuture + - RegenerativeMesh + - BoxZiptie + - CrowbarRed + - MagazinePistol # Medical - type: job @@ -258,7 +368,7 @@ id: ERTMedicalGear equipment: jumpsuit: ClothingUniformJumpsuitERTMedic - back: ClothingBackpackERTMedicalFilled + back: ClothingBackpackERTMedical shoes: ClothingShoesBootsCombatFilled head: ClothingHeadHelmetERTMedic eyes: ClothingEyesHudMedical @@ -268,12 +378,21 @@ ears: ClothingHeadsetAltCentCom belt: ClothingBeltMedicalFilled pocket1: Flare + storage: + back: + - BoxSurvivalMedical + - Hypospray + - MedkitAdvancedFilled + - CrowbarRed + - OmnizineChemistryBottle + - EpinephrineChemistryBottle + - EpinephrineChemistryBottle - type: startingGear id: ERTMedicalGearEVA equipment: jumpsuit: ClothingUniformJumpsuitERTMedic - back: ClothingBackpackERTMedicalFilled + back: ClothingBackpackERTMedical shoes: ClothingShoesBootsMag mask: ClothingMaskGasERT eyes: ClothingEyesHudMedical @@ -284,6 +403,15 @@ ears: ClothingHeadsetAltCentCom belt: ClothingBeltMedicalFilled pocket1: Flare + storage: + back: + - BoxSurvivalMedical + - Hypospray + - MedkitAdvancedFilled + - CrowbarRed + - OmnizineChemistryBottle + - EpinephrineChemistryBottle + - EpinephrineChemistryBottle # Janitor - type: job @@ -305,7 +433,7 @@ id: ERTJanitorGear equipment: jumpsuit: ClothingUniformJumpsuitERTJanitor - back: ClothingBackpackERTJanitorFilled + back: ClothingBackpackERTJanitor shoes: ClothingShoesGaloshes head: ClothingHeadHelmetERTJanitor gloves: ClothingHandsGlovesColorPurple @@ -314,12 +442,21 @@ ears: ClothingHeadsetAltCentCom belt: ClothingBeltJanitorFilled pocket1: Flare + storage: + back: + - BoxSurvivalEngineering + - LightReplacer + - BoxLightMixed + - BoxLightMixed + - Soap + - CrowbarRed + - AdvMopItem - type: startingGear id: ERTJanitorGearEVA equipment: jumpsuit: ClothingUniformJumpsuitERTJanitor - back: ClothingBackpackERTJanitorFilled + back: ClothingBackpackERTJanitor shoes: ClothingShoesBootsMag mask: ClothingMaskGasERT gloves: ClothingHandsGlovesColorPurple @@ -329,3 +466,12 @@ ears: ClothingHeadsetAltCentCom belt: ClothingBeltJanitorFilled pocket1: Flare + storage: + back: + - BoxSurvivalEngineering + - LightReplacer + - BoxLightMixed + - BoxLightMixed + - Soap + - CrowbarRed + - AdvMopItem \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml index d4cfc3e29c..e12bee8c79 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml @@ -5,7 +5,7 @@ id: SkeletonBiker equipment: jumpsuit: ClothingUniformJumpsuitColorBlack - back: ClothingBackpackFilled + back: ClothingBackpack head: ClothingHeadBandSkull eyes: ClothingEyesGlassesSunglasses outerClothing: ClothingOuterCoatGentle @@ -13,35 +13,16 @@ shoes: ClothingShoesBootsJack id: PassengerPDA ears: ClothingHeadsetGrey - -#Space Ninja Outfit -- type: startingGear - id: SpaceNinjaGear - equipment: - jumpsuit: ClothingUniformJumpsuitNinja - # belt holds katana so satchel has the tools for sabotaging things - back: ClothingBackpackSatchelTools - mask: ClothingMaskNinja - head: ClothingHeadHelmetSpaceNinja - eyes: ClothingEyesVisorNinja - gloves: ClothingHandsGlovesSpaceNinja - outerClothing: ClothingOuterSuitSpaceNinja - shoes: ClothingShoesSpaceNinja - id: AgentIDCard - ears: ClothingHeadsetGrey - pocket1: SpiderCharge - pocket2: PinpointerStation - belt: EnergyKatana - suitstorage: OxygenTankFilled - inhand: - - JetpackBlackFilled + storage: + back: + - BoxSurvival #Deathsquad Outfit - type: startingGear id: DeathSquadGear equipment: jumpsuit: ClothingUniformJumpsuitDeathSquad - back: ClothingBackpackDeathSquadFilled + back: ClothingBackpackDeathSquad mask: ClothingMaskGasDeathSquad eyes: ClothingEyesHudSecurity ears: ClothingHeadsetAltCentCom @@ -53,23 +34,20 @@ pocket1: EnergySword pocket2: EnergyShield belt: ClothingBeltMilitaryWebbingMedFilled - -# Syndicate Operative Outfit - Monkey -- type: startingGear - id: SyndicateOperativeGearMonkey - equipment: - head: ClothingHeadHatOutlawHat - jumpsuit: ClothingUniformJumpsuitOperative - mask: CigaretteSyndicate - -# Syndicate Operative Outfit - Barratry -- type: startingGear - id: SyndicateOperativeGearExtremelyBasic - equipment: - jumpsuit: ClothingUniformJumpsuitOperative - back: ClothingBackpackDuffelSyndicateOperative - shoes: ClothingShoesBootsCombatFilled - gloves: ClothingHandsGlovesColorBlack + storage: + back: + - BoxSurvivalEngineering + - WeaponPulseRifle + - WeaponPulsePistol + - WeaponRevolverMateba + - SpeedLoaderMagnumAP + - SpeedLoaderMagnumAP + - BoxFlashbang + - ToolDebug # spanish army knife + - WelderExperimental + - Hypospray + - DeathAcidifierImplanter # crew will try to steal their amazing hardsuits + - FreedomImplanter # Syndicate Operative Outfit - Civilian - type: startingGear @@ -82,103 +60,6 @@ id: SyndiPDA ears: ClothingHeadsetAltSyndicate -#Syndicate Operative Outfit - Basic -- type: startingGear - id: SyndicateOperativeGearBasic - equipment: - jumpsuit: ClothingUniformJumpsuitOperative - back: ClothingBackpackDuffelSyndicateOperative - ears: ClothingHeadsetAltSyndicate - gloves: ClothingHandsGlovesCombat - shoes: ClothingShoesBootsCombatFilled - pocket1: BaseUplinkRadio40TC - id: SyndiPDA - -#Syndicate Operative Outfit - Full Kit -- type: startingGear - id: SyndicateOperativeGearFull - equipment: - jumpsuit: ClothingUniformJumpsuitOperative - back: ClothingBackpackDuffelSyndicateOperative - mask: ClothingMaskGasSyndicate - eyes: ClothingEyesHudSyndicate - ears: ClothingHeadsetAltSyndicate - gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterHardsuitSyndie - shoes: ClothingShoesBootsCombatFilled - id: SyndiPDA - pocket1: DoubleEmergencyOxygenTankFilled - pocket2: BaseUplinkRadio40TC - belt: ClothingBeltMilitaryWebbing - -#Nuclear Operative Commander Gear -- type: startingGear - id: SyndicateCommanderGearFull - equipment: - jumpsuit: ClothingUniformJumpsuitOperative - back: ClothingBackpackDuffelSyndicateOperative - mask: ClothingMaskGasSyndicate - eyes: ClothingEyesHudSyndicate - ears: ClothingHeadsetAltSyndicate - neck: SyndicateWhistle - gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterHardsuitSyndieCommander - shoes: ClothingShoesBootsCombatFilled - id: SyndiPDA - pocket1: DoubleEmergencyOxygenTankFilled - pocket2: BaseUplinkRadio40TC - belt: ClothingBeltMilitaryWebbing - inhand: - - NukeOpsDeclarationOfWar - -#Nuclear Operative Medic Gear -- type: startingGear - id: SyndicateOperativeMedicFull - equipment: - jumpsuit: ClothingUniformJumpsuitOperative - back: ClothingBackpackDuffelSyndicateOperativeMedic - mask: ClothingMaskGasSyndicate - eyes: ClothingEyesHudSyndicateAgent - ears: ClothingHeadsetAltSyndicate - gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterHardsuitSyndieMedic - shoes: ClothingShoesBootsMagSyndie - id: SyndiAgentPDA - pocket1: DoubleEmergencyOxygenTankFilled - pocket2: BaseUplinkRadio40TC - belt: ClothingBeltMilitaryWebbingMedFilled - -#Syndicate Lone Operative Outfit - Full Kit -- type: startingGear - id: SyndicateLoneOperativeGearFull - equipment: - jumpsuit: ClothingUniformJumpsuitOperative - back: ClothingBackpackDuffelSyndicateOperative - mask: ClothingMaskGasSyndicate - eyes: ClothingEyesHudSyndicate - ears: ClothingHeadsetAltSyndicate - gloves: ClothingHandsGlovesCombat - outerClothing: ClothingOuterHardsuitSyndie - shoes: ClothingShoesBootsCombatFilled - id: SyndiPDA - pocket1: DoubleEmergencyOxygenTankFilled - pocket2: BaseUplinkRadio60TC - belt: ClothingBeltMilitaryWebbing - -# Syndicate Footsoldier Gear -- type: startingGear - id: SyndicateFootsoldierGear - equipment: - jumpsuit: ClothingUniformJumpsuitOperative - head: ClothingHeadHelmetSwatSyndicate - mask: ClothingMaskGas - outerClothing: ClothingOuterArmorBasic - ears: ClothingHeadsetAltSyndicate - gloves: ClothingHandsGlovesCombat - back: ClothingBackpackFilled - shoes: ClothingShoesBootsCombat - id: SyndiPDA - # Syndicate Footsoldier Gear - No Headset - type: startingGear id: SyndicateFootsoldierGearRuin @@ -188,16 +69,26 @@ mask: ClothingMaskGas outerClothing: ClothingOuterArmorBasic gloves: ClothingHandsGlovesCombat - back: ClothingBackpackFilled + back: ClothingBackpack shoes: ClothingShoesBootsCombat id: SyndiPDA + storage: + back: + - BoxSurvival + +# Syndicate Footsoldier Gear +- type: startingGear + id: SyndicateFootsoldierGear + parent: SyndicateFootsoldierGearRuin + equipment: + ears: ClothingHeadsetAltSyndicate # Nanotrasen Paramilitary Unit Gear - type: startingGear id: NanotrasenParamilitaryGear equipment: jumpsuit: ClothingUniformJumpsuitSec - back: ClothingBackpackSecurityFilled + back: ClothingBackpackSecurity shoes: ClothingShoesBootsCombatFilled eyes: ClothingEyesGlassesSecurity head: ClothingHeadHelmetSwat @@ -205,13 +96,18 @@ outerClothing: ClothingOuterArmorBasicSlim ears: ClothingHeadsetSecurity gloves: ClothingHandsGlovesCombat + storage: + back: + - BoxSurvivalSecurity + - Flash + - MagazinePistol #CBURN Unit Gear - Full Kit - type: startingGear id: CBURNGear equipment: jumpsuit: ClothingUniformJumpsuitColorBrown - back: ClothingBackpackDuffelCBURNFilled + back: ClothingBackpackDuffelCBURN mask: ClothingMaskGasERT eyes: ClothingEyesGlassesSecurity ears: ClothingHeadsetAltCentCom @@ -223,6 +119,14 @@ pocket2: WeaponLaserGun suitstorage: OxygenTankFilled belt: ClothingBeltBandolier + storage: + back: + - BoxSurvivalEngineering + - WeaponShotgunDoubleBarreled + - BoxShotgunIncendiary + - GrenadeFlashBang + - PillAmbuzolPlus + - PillAmbuzol - type: startingGear id: BoxingKangarooGear @@ -237,14 +141,6 @@ jumpsuit: ClothingUniformJumpsuitJacketMonkey id: PunPunIDCard -# Passenger but without the ID, bag, or headset - -- type: startingGear - id: LimitedPassengerGear - equipment: - jumpsuit: ClothingUniformJumpsuitColorGrey - shoes: ClothingShoesColorBlack - # DeathMatch Gear - type: startingGear @@ -278,24 +174,13 @@ - type: startingGear id: MobAghostGear equipment: - back: ClothingBackpackSatchelHoldingAdmin + back: ClothingBackpackSatchelHolding id: AdminPDA - -#Head Rev Gear -- type: startingGear - id: HeadRevGear storage: back: - - Flash - - ClothingEyesGlassesSunglasses - -#Thief Gear -- type: startingGear - id: ThiefGear - storage: - back: - - ToolboxThief - - ClothingHandsChameleonThief + - GasAnalyzer + - trayScanner + - AccessConfiguratorUniversal #Gladiator with spear - type: startingGear @@ -325,10 +210,16 @@ shoes: ClothingShoesClownBanana jumpsuit: ClothingUniformJumpsuitClownBanana mask: ClothingMaskClownBanana - ears: ClothingHeadsetService pocket1: BikeHorn pocket2: ClownRecorder +# Passenger but without the ID, bag, or headset +- type: startingGear + id: LimitedPassengerGear + equipment: + jumpsuit: ClothingUniformJumpsuitColorGrey + shoes: ClothingShoesColorBlack + #Clown Troupe - type: startingGear id: ClownTroupe diff --git a/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml b/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml index 596e42776b..d053d8da1c 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml @@ -3,41 +3,33 @@ id: WizardBlueGear equipment: jumpsuit: ClothingUniformJumpsuitColorDarkBlue - back: ClothingBackpackFilled head: ClothingHeadHatWizard outerClothing: ClothingOuterWizard shoes: ClothingShoesWizard id: PassengerPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival - type: startingGear id: WizardRedGear + parent: WizardBlueGear equipment: jumpsuit: ClothingUniformJumpsuitColorRed - back: ClothingBackpackFilled head: ClothingHeadHatRedwizard outerClothing: ClothingOuterWizardRed - shoes: ClothingShoesWizard - id: PassengerPDA - ears: ClothingHeadsetService - type: startingGear id: WizardVioletGear + parent: WizardBlueGear equipment: jumpsuit: ClothingUniformJumpsuitColorPurple - back: ClothingBackpackFilled head: ClothingHeadHatVioletwizard outerClothing: ClothingOuterWizardViolet - shoes: ClothingShoesWizard - id: PassengerPDA - ears: ClothingHeadsetService - type: startingGear id: WizardHardsuitGear + parent: WizardVioletGear equipment: - jumpsuit: ClothingUniformJumpsuitColorPurple - back: ClothingBackpackFilled - outerClothing: ClothingOuterHardsuitWizard - shoes: ClothingShoesWizard - id: PassengerPDA - ears: ClothingHeadsetService + outerClothing: ClothingOuterHardsuitWizard \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml b/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml index 0684d9d36a..fefd0110ac 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chemist.yml @@ -22,4 +22,7 @@ ears: ClothingHeadsetMedical belt: ChemBag pocket1: HandLabeler - eyes: ClothingEyesGlassesChemical \ No newline at end of file + eyes: ClothingEyesGlassesChemical + storage: + back: + - BoxSurvivalMedical \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index e20edb32d4..3f6bd5e452 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -44,3 +44,7 @@ id: CMOPDA ears: ClothingHeadsetCMO belt: ClothingBeltMedicalFilled + storage: + back: + - BoxSurvivalMedical + - Flash diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml index 27efb3b8b2..be058518a6 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml @@ -21,3 +21,6 @@ equipment: ears: ClothingHeadsetMedical belt: ClothingBeltMedicalFilled + storage: + back: + - BoxSurvivalMedical \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml index 199645d5c3..3fe26e6056 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_intern.yml @@ -23,4 +23,7 @@ id: MedicalInternPDA ears: ClothingHeadsetMedical belt: ClothingBeltMedicalFilled - pocket2: BookMedicalReferenceBook \ No newline at end of file + pocket2: BookMedicalReferenceBook + storage: + back: + - BoxSurvivalMedical \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml b/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml index fb9fd2822d..242fac8d0c 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/paramedic.yml @@ -24,3 +24,7 @@ id: ParamedicPDA ears: ClothingHeadsetMedical belt: ClothingBeltMedicalEMTFilled + storage: + back: + - BoxSurvivalMedical + - EmergencyRollerBedSpawnFolded \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml b/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml index b50c61ebdb..aec2dd6fff 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_assistant.yml @@ -23,3 +23,6 @@ id: ResearchAssistantPDA ears: ClothingHeadsetScience pocket2: BookScientistsGuidebook + storage: + back: + - BoxSurvival \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml index adf53d9c70..fd6e00a8e3 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml @@ -33,4 +33,8 @@ id: ResearchDirectorGear equipment: id: RnDPDA - ears: ClothingHeadsetRD \ No newline at end of file + ears: ClothingHeadsetRD + storage: + back: + - BoxSurvival + - Flash \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml index 5188e47057..b2e63fead8 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml @@ -18,4 +18,6 @@ id: ScientistGear equipment: ears: ClothingHeadsetScience - + storage: + back: + - BoxSurvival \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Security/detective.yml b/Resources/Prototypes/Roles/Jobs/Security/detective.yml index b17d0d41df..47258fa00b 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/detective.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/detective.yml @@ -28,3 +28,9 @@ id: DetectivePDA ears: ClothingHeadsetSecurity belt: ClothingBeltHolsterFilled + storage: + back: + - BoxSurvivalSecurity + - Flash + - ForensicPad + - ForensicScanner \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index 8646ca8ddd..aac7c7b350 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -47,3 +47,8 @@ gloves: ClothingHandsGlovesCombat ears: ClothingHeadsetAltSecurity pocket1: WeaponPistolMk58 + storage: + back: + - BoxSurvivalSecurity + - Flash + - MagazinePistol \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml b/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml index 17e09b232e..b68336c953 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml @@ -34,4 +34,9 @@ ears: ClothingHeadsetSecurity belt: ClothingBeltSecurityFilled pocket1: WeaponPistolMk58 - pocket2: BookSecurity \ No newline at end of file + pocket2: BookSecurity + storage: + back: + - BoxSurvivalSecurity + - Flash + - MagazinePistol \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml index edf16448d7..c773396601 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml @@ -28,3 +28,8 @@ eyes: ClothingEyesGlassesSecurity ears: ClothingHeadsetSecurity pocket1: WeaponPistolMk58 + storage: + back: + - BoxSurvivalSecurity + - Flash + - MagazinePistol \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml index 5c1dc985d1..7f15752576 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml @@ -31,3 +31,8 @@ id: WardenPDA ears: ClothingHeadsetSecurity pocket1: WeaponPistolMk58 + storage: + back: + - BoxSurvivalSecurity + - Flash + - MagazinePistol \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Wildcards/boxer.yml b/Resources/Prototypes/Roles/Jobs/Wildcards/boxer.yml index 0f19323724..aceb7a10f6 100644 --- a/Resources/Prototypes/Roles/Jobs/Wildcards/boxer.yml +++ b/Resources/Prototypes/Roles/Jobs/Wildcards/boxer.yml @@ -17,3 +17,6 @@ ears: ClothingHeadsetService shoes: ClothingShoesColorRed belt: ClothingBeltChampion + storage: + back: + - BoxSurvival \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Wildcards/psychologist.yml b/Resources/Prototypes/Roles/Jobs/Wildcards/psychologist.yml index d1d07c008c..17bed0ee7f 100644 --- a/Resources/Prototypes/Roles/Jobs/Wildcards/psychologist.yml +++ b/Resources/Prototypes/Roles/Jobs/Wildcards/psychologist.yml @@ -19,3 +19,6 @@ shoes: ClothingShoesLeather id: PsychologistPDA ears: ClothingHeadsetMedical + storage: + back: + - BoxSurvivalMedical \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Wildcards/reporter.yml b/Resources/Prototypes/Roles/Jobs/Wildcards/reporter.yml index d2d70d856a..b379a0ec23 100644 --- a/Resources/Prototypes/Roles/Jobs/Wildcards/reporter.yml +++ b/Resources/Prototypes/Roles/Jobs/Wildcards/reporter.yml @@ -16,3 +16,6 @@ shoes: ClothingShoesColorWhite id: ReporterPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival \ No newline at end of file diff --git a/Resources/Prototypes/Roles/Jobs/Wildcards/zookeeper.yml b/Resources/Prototypes/Roles/Jobs/Wildcards/zookeeper.yml index 27e7fa65ff..815ead412c 100644 --- a/Resources/Prototypes/Roles/Jobs/Wildcards/zookeeper.yml +++ b/Resources/Prototypes/Roles/Jobs/Wildcards/zookeeper.yml @@ -18,3 +18,6 @@ shoes: ClothingShoesColorWhite id: ZookeeperPDA ears: ClothingHeadsetService + storage: + back: + - BoxSurvival \ No newline at end of file diff --git a/Resources/migration.yml b/Resources/migration.yml index 65e914aed6..5f73d4d253 100644 --- a/Resources/migration.yml +++ b/Resources/migration.yml @@ -251,11 +251,11 @@ AirlockGlassShuttleEasyPryLocked: AirlockExternalGlassShuttleLocked AirlockShuttleEasyPryLocked: AirlockExternalShuttleLocked # 2024-03-10 -ClothingBackpackFilledDetective: ClothingBackpackSecurityFilledDetective -ClothingBackpackDuffelFilledDetective: ClothingBackpackDuffelSecurityFilledDetective -ClothingBackpackSatchelFilledDetective: ClothingBackpackSatchelSecurityFilledDetective FoodChili: FoodChiliPepper FoodChilly: FoodChillyPepper +# ClothingBackpackFilledDetective: ClothingBackpackSecurityFilledDetective +# ClothingBackpackDuffelFilledDetective: ClothingBackpackDuffelSecurityFilledDetective +# ClothingBackpackSatchelFilledDetective: ClothingBackpackSatchelSecurityFilledDetective # 2024-03-11 ImprovisedExplosive: FireBomb From 16b3fb1204d3921200822bf558c510c585ba33e3 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Tue, 4 Jun 2024 00:04:19 +0000 Subject: [PATCH 55/63] LoadMapRule grid storage rework (#28210) * --- .../Tests/GameRules/NukeOpsTest.cs | 10 +-- .../Rules/Components/LoadMapRuleComponent.cs | 26 +++--- .../Rules/Components/RuleGridsComponent.cs | 30 +++++++ .../Rules/GameRuleSystem.Utility.cs | 4 + .../GameTicking/Rules/LoadMapRuleSystem.cs | 90 +++++++------------ .../GameTicking/Rules/NukeopsRuleSystem.cs | 12 +-- .../GameTicking/Rules/RuleGridsSystem.cs | 78 ++++++++++++++++ .../GridPreloader/GridPreloaderSystem.cs | 9 +- .../Events/StationEventSystem.cs | 9 -- Resources/Prototypes/GameRules/events.yml | 1 + Resources/Prototypes/GameRules/midround.yml | 1 - Resources/Prototypes/GameRules/roundstart.yml | 1 + .../Prototypes/GameRules/unknown_shuttles.yml | 49 +++------- 13 files changed, 190 insertions(+), 130 deletions(-) create mode 100644 Content.Server/GameTicking/Rules/Components/RuleGridsComponent.cs create mode 100644 Content.Server/GameTicking/Rules/RuleGridsSystem.cs diff --git a/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs b/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs index ea19a30005..2360ea0bf4 100644 --- a/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs +++ b/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs @@ -114,8 +114,8 @@ public sealed class NukeOpsTest // The game rule exists, and all the stations/shuttles/maps are properly initialized var rule = entMan.AllComponents().Single().Component; - var mapRule = entMan.AllComponents().Single().Component; - foreach (var grid in mapRule.MapGrids) + var gridsRule = entMan.AllComponents().Single().Component; + foreach (var grid in gridsRule.MapGrids) { Assert.That(entMan.EntityExists(grid)); Assert.That(entMan.HasComponent(grid)); @@ -129,7 +129,7 @@ public sealed class NukeOpsTest Assert.That(entMan.EntityExists(nukieShuttlEnt)); EntityUid? nukieStationEnt = null; - foreach (var grid in mapRule.MapGrids) + foreach (var grid in gridsRule.MapGrids) { if (entMan.HasComponent(grid)) { @@ -144,8 +144,8 @@ public sealed class NukeOpsTest Assert.That(entMan.EntityExists(nukieStation.Station)); Assert.That(nukieStation.Station, Is.Not.EqualTo(rule.TargetStation)); - Assert.That(server.MapMan.MapExists(mapRule.Map)); - var nukieMap = mapSys.GetMap(mapRule.Map!.Value); + Assert.That(server.MapMan.MapExists(gridsRule.Map)); + var nukieMap = mapSys.GetMap(gridsRule.Map!.Value); var targetStation = entMan.GetComponent(rule.TargetStation!.Value); var targetGrid = targetStation.Grids.First(); diff --git a/Content.Server/GameTicking/Rules/Components/LoadMapRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/LoadMapRuleComponent.cs index b7aef0c61d..1f0505c60f 100644 --- a/Content.Server/GameTicking/Rules/Components/LoadMapRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/LoadMapRuleComponent.cs @@ -1,8 +1,6 @@ +using Content.Server.GameTicking.Rules; using Content.Server.Maps; using Content.Shared.GridPreloader.Prototypes; -using Content.Shared.Storage; -using Content.Shared.Whitelist; -using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -10,25 +8,27 @@ namespace Content.Server.GameTicking.Rules.Components; /// /// This is used for a game rule that loads a map when activated. +/// Works with . /// -[RegisterComponent] +[RegisterComponent, Access(typeof(LoadMapRuleSystem))] public sealed partial class LoadMapRuleComponent : Component { - [DataField] - public MapId? Map; - + /// + /// A to load on a new map. + /// [DataField] public ProtoId? GameMap; + /// + /// A map path to load on a new map. + /// [DataField] public ResPath? MapPath; + /// + /// A to move to a new map. + /// If there are no instances left nothing is done. + /// [DataField] public ProtoId? PreloadedGrid; - - [DataField] - public List MapGrids = new(); - - [DataField] - public EntityWhitelist? SpawnerWhitelist; } diff --git a/Content.Server/GameTicking/Rules/Components/RuleGridsComponent.cs b/Content.Server/GameTicking/Rules/Components/RuleGridsComponent.cs new file mode 100644 index 0000000000..eec6f88815 --- /dev/null +++ b/Content.Server/GameTicking/Rules/Components/RuleGridsComponent.cs @@ -0,0 +1,30 @@ +using Content.Server.GameTicking.Rules; +using Content.Shared.Whitelist; +using Robust.Shared.Map; + +/// +/// Stores grids created by another gamerule component. +/// With AntagSelection, spawners on these grids can be used for its antags. +/// +[RegisterComponent, Access(typeof(RuleGridsSystem))] +public sealed partial class RuleGridsComponent : Component +{ + /// + /// The map that was loaded. + /// + [DataField] + public MapId? Map; + + /// + /// The grid entities that have been loaded. + /// + [DataField] + public List MapGrids = new(); + + /// + /// Whitelist for a spawner to be considered for an antag. + /// All spawners must have SpawnPointComponent regardless to be found. + /// + [DataField] + public EntityWhitelist? SpawnerWhitelist; +} diff --git a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs index cbd981e99e..9ac7a6edbb 100644 --- a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs +++ b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs @@ -126,4 +126,8 @@ public abstract partial class GameRuleSystem where T: IComponent return found; } + protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null) + { + GameTicker.EndGameRule(uid, component); + } } diff --git a/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs b/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs index c60cf2513e..1c09d6e86e 100644 --- a/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs @@ -1,9 +1,6 @@ -using Content.Server.Antag; using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.GridPreloader; -using Content.Server.Spawners.Components; -using Content.Shared.Whitelist; using Robust.Server.GameObjects; using Robust.Server.Maps; using Robust.Shared.Map; @@ -14,97 +11,70 @@ namespace Content.Server.GameTicking.Rules; public sealed class LoadMapRuleSystem : GameRuleSystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly MapSystem _map = default!; [Dependency] private readonly MapLoaderSystem _mapLoader = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly GridPreloaderSystem _gridPreloader = default!; - [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnSelectLocation); - SubscribeLocalEvent(OnGridSplit); - } - - private void OnGridSplit(ref GridSplitEvent args) - { - var rule = QueryActiveRules(); - while (rule.MoveNext(out _, out var mapComp, out _)) - { - if (!mapComp.MapGrids.Contains(args.Grid)) - continue; - - mapComp.MapGrids.AddRange(args.NewGrids); - break; - } - } protected override void Added(EntityUid uid, LoadMapRuleComponent comp, GameRuleComponent rule, GameRuleAddedEvent args) { - if (comp.Map != null) + if (comp.PreloadedGrid != null && !_gridPreloader.PreloadingEnabled) + { + // Preloading will never work if it's disabled, duh + Log.Debug($"Immediately ending {ToPrettyString(uid):rule} as preloading grids is disabled by cvar."); + ForceEndSelf(uid, rule); return; + } // grid preloading needs map to init after moving it - var mapUid = comp.PreloadedGrid != null ? _map.CreateMap(out var mapId, false) : _map.CreateMap(out mapId); - _metaData.SetEntityName(mapUid, $"LoadMapRule destination for rule {ToPrettyString(uid)}"); - comp.Map = mapId; + var mapUid = _map.CreateMap(out var mapId, runMapInit: comp.PreloadedGrid == null); + Log.Info($"Created map {mapId} for {ToPrettyString(uid):rule}"); + + IReadOnlyList grids; if (comp.GameMap != null) { var gameMap = _prototypeManager.Index(comp.GameMap.Value); - comp.MapGrids.AddRange(GameTicker.LoadGameMap(gameMap, comp.Map.Value, new MapLoadOptions())); + grids = GameTicker.LoadGameMap(gameMap, mapId, new MapLoadOptions()); } - else if (comp.MapPath != null) + else if (comp.MapPath is {} path) { - if (!_mapLoader.TryLoad(comp.Map.Value, - comp.MapPath.Value.ToString(), - out var roots, - new MapLoadOptions { LoadMap = true })) + var options = new MapLoadOptions { LoadMap = true }; + if (!_mapLoader.TryLoad(mapId, path.ToString(), out var roots, options)) { - _mapManager.DeleteMap(mapId); + Log.Error($"Failed to load map from {path}!"); + Del(mapUid); + ForceEndSelf(uid, rule); return; } - comp.MapGrids.AddRange(roots); + grids = roots; } - else if (comp.PreloadedGrid != null) + else if (comp.PreloadedGrid is {} preloaded) { // TODO: If there are no preloaded grids left, any rule announcements will still go off! - if (!_gridPreloader.TryGetPreloadedGrid(comp.PreloadedGrid.Value, out var loadedShuttle)) + if (!_gridPreloader.TryGetPreloadedGrid(preloaded, out var loadedShuttle)) { - _mapManager.DeleteMap(mapId); + Log.Error($"Failed to get a preloaded grid with {preloaded}!"); + Del(mapUid); + ForceEndSelf(uid, rule); return; } _transform.SetParent(loadedShuttle.Value, mapUid); - comp.MapGrids.Add(loadedShuttle.Value); - _map.InitializeMap(mapId); + grids = new List() { loadedShuttle.Value }; + _map.InitializeMap(mapUid); } else { Log.Error($"No valid map prototype or map path associated with the rule {ToPrettyString(uid)}"); + Del(mapUid); + ForceEndSelf(uid, rule); + return; } - } - private void OnSelectLocation(Entity ent, ref AntagSelectLocationEvent args) - { - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out _, out var xform)) - { - if (xform.MapID != ent.Comp.Map) - continue; - - if (xform.GridUid == null || !ent.Comp.MapGrids.Contains(xform.GridUid.Value)) - continue; - - if (_whitelistSystem.IsWhitelistFail(ent.Comp.SpawnerWhitelist, uid)) - continue; - - args.Coordinates.Add(_transform.GetMapCoordinates(xform)); - } + var ev = new RuleLoadedGridsEvent(mapId, grids); + RaiseLocalEvent(uid, ref ev); } } diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 1b62778d75..6688bfd980 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -260,10 +260,10 @@ public sealed class NukeopsRuleSystem : GameRuleSystem { var map = Transform(ent).MapID; - var rules = EntityQueryEnumerator(); - while (rules.MoveNext(out var uid, out _, out var mapRule)) + var rules = EntityQueryEnumerator(); + while (rules.MoveNext(out var uid, out _, out var grids)) { - if (map != mapRule.Map) + if (map != grids.Map) continue; ent.Comp.AssociatedRule = uid; break; @@ -324,7 +324,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem if (nukeops.WarDeclaredTime != null) continue; - if (TryComp(uid, out var mapComp) && Transform(ev.DeclaratorEntity).MapID != mapComp.Map) + if (TryComp(uid, out var grids) && Transform(ev.DeclaratorEntity).MapID != grids.Map) continue; var newStatus = GetWarCondition(nukeops, ev.Status); @@ -445,7 +445,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem // Check that there are spawns available and that they can access the shuttle. var spawnsAvailable = EntityQuery(true).Any(); - if (spawnsAvailable && CompOrNull(ent)?.Map == shuttleMapId) + if (spawnsAvailable && CompOrNull(ent)?.Map == shuttleMapId) return; // Ghost spawns can still access the shuttle. Continue the round. // The shuttle is inaccessible to both living nuke operatives and yet to spawn nuke operatives, @@ -478,7 +478,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem /// Is this method the shitty glue holding together the last of my sanity? yes. /// Do i have a better solution? not presently. /// - private EntityUid? GetOutpost(Entity ent) + private EntityUid? GetOutpost(Entity ent) { if (!Resolve(ent, ref ent.Comp, false)) return null; diff --git a/Content.Server/GameTicking/Rules/RuleGridsSystem.cs b/Content.Server/GameTicking/Rules/RuleGridsSystem.cs new file mode 100644 index 0000000000..9eae9e3c95 --- /dev/null +++ b/Content.Server/GameTicking/Rules/RuleGridsSystem.cs @@ -0,0 +1,78 @@ +using Content.Server.Antag; +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Spawners.Components; +using Content.Shared.Whitelist; +using Robust.Server.Physics; +using Robust.Shared.Map; + +namespace Content.Server.GameTicking.Rules; + +/// +/// Handles storing grids from and antags spawning on their spawners. +/// +public sealed class RuleGridsSystem : GameRuleSystem +{ + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGridSplit); + + SubscribeLocalEvent(OnLoadedGrids); + SubscribeLocalEvent(OnSelectLocation); + } + + private void OnGridSplit(ref GridSplitEvent args) + { + var rule = QueryActiveRules(); + while (rule.MoveNext(out _, out var comp, out _)) + { + if (!comp.MapGrids.Contains(args.Grid)) + continue; + + comp.MapGrids.AddRange(args.NewGrids); + break; // only 1 rule can own a grid, not multiple + } + } + + private void OnLoadedGrids(Entity ent, ref RuleLoadedGridsEvent args) + { + var (uid, comp) = ent; + if (comp.Map != null && args.Map != comp.Map) + { + Log.Warning($"{ToPrettyString(uid):rule} loaded grids on multiple maps {comp.Map} and {args.Map}, the second will be ignored."); + return; + } + + comp.Map = args.Map; + comp.MapGrids.AddRange(args.Grids); + } + + private void OnSelectLocation(Entity ent, ref AntagSelectLocationEvent args) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out _, out var xform)) + { + if (xform.MapID != ent.Comp.Map) + continue; + + if (xform.GridUid is not {} grid || !ent.Comp.MapGrids.Contains(grid)) + continue; + + if (_whitelist.IsWhitelistFail(ent.Comp.SpawnerWhitelist, uid)) + continue; + + args.Coordinates.Add(_transform.GetMapCoordinates(xform)); + } + } +} + +/// +/// Raised by another gamerule system to store loaded grids, and have other systems work with it. +/// A single rule can only load grids for a single map, attempts to load more are ignored. +/// +[ByRefEvent] +public record struct RuleLoadedGridsEvent(MapId Map, IReadOnlyList Grids); diff --git a/Content.Server/GridPreloader/GridPreloaderSystem.cs b/Content.Server/GridPreloader/GridPreloaderSystem.cs index 569fe54141..e12ce41a31 100644 --- a/Content.Server/GridPreloader/GridPreloaderSystem.cs +++ b/Content.Server/GridPreloader/GridPreloaderSystem.cs @@ -24,12 +24,19 @@ public sealed class GridPreloaderSystem : SharedGridPreloaderSystem [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + /// + /// Whether the preloading CVar is set or not. + /// + public bool PreloadingEnabled; + public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnRoundRestart); SubscribeLocalEvent(OnPostGameMapLoad); + + Subs.CVar(_cfg, CCVars.PreloadGrids, value => PreloadingEnabled = value, true); } private void OnRoundRestart(RoundRestartCleanupEvent ev) @@ -52,7 +59,7 @@ public sealed class GridPreloaderSystem : SharedGridPreloaderSystem if (GetPreloaderEntity() != null) return; - if (!_cfg.GetCVar(CCVars.PreloadGrids)) + if (!PreloadingEnabled) return; var mapUid = _map.CreateMap(out var mapId, false); diff --git a/Content.Server/StationEvents/Events/StationEventSystem.cs b/Content.Server/StationEvents/Events/StationEventSystem.cs index 35dc646bce..06dfdd5276 100644 --- a/Content.Server/StationEvents/Events/StationEventSystem.cs +++ b/Content.Server/StationEvents/Events/StationEventSystem.cs @@ -108,13 +108,4 @@ public abstract class StationEventSystem : GameRuleSystem where T : ICompo } } } - - #region Helper Functions - - protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null) - { - GameTicker.EndGameRule(uid, component); - } - - #endregion } diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index f421cf6818..d3b0971be0 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -422,6 +422,7 @@ weight: 5.5 minimumPlayers: 20 duration: 1 + - type: RuleGrids - type: LoadMapRule preloadedGrid: ShuttleStriker - type: NukeopsRule diff --git a/Resources/Prototypes/GameRules/midround.yml b/Resources/Prototypes/GameRules/midround.yml index c190b0333a..5a38c22215 100644 --- a/Resources/Prototypes/GameRules/midround.yml +++ b/Resources/Prototypes/GameRules/midround.yml @@ -3,7 +3,6 @@ - type: entity id: Ninja parent: BaseGameRule - noSpawn: true components: - type: GenericAntagRule agentName: ninja-round-end-agent-name diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index 3493749457..88f80fd4f6 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -78,6 +78,7 @@ - operationPrefix - operationSuffix - type: NukeopsRule + - type: RuleGrids - type: AntagSelection - type: AntagLoadProfileRule diff --git a/Resources/Prototypes/GameRules/unknown_shuttles.yml b/Resources/Prototypes/GameRules/unknown_shuttles.yml index 359d7bffc0..1ce365cd81 100644 --- a/Resources/Prototypes/GameRules/unknown_shuttles.yml +++ b/Resources/Prototypes/GameRules/unknown_shuttles.yml @@ -1,7 +1,7 @@ -- type: entity - id: UnknownShuttleCargoLost +- type: entity + abstract: true parent: BaseGameRule - noSpawn: true + id: BaseUnknownShuttleRule components: - type: StationEvent startAnnouncement: station-event-unknown-shuttle-incoming @@ -10,65 +10,44 @@ weight: 5 reoccurrenceDelay: 30 duration: 1 + - type: RuleGrids + - type: LoadMapRule + +- type: entity + parent: BaseUnknownShuttleRule + id: UnknownShuttleCargoLost + components: - type: LoadMapRule preloadedGrid: ShuttleCargoLost - type: entity + parent: BaseUnknownShuttleRule id: UnknownShuttleTravelingCuisine - parent: BaseGameRule - noSpawn: true components: - - type: StationEvent - startAnnouncement: station-event-unknown-shuttle-incoming - startAudio: - path: /Audio/Announcements/attention.ogg - weight: 5 - reoccurrenceDelay: 30 - duration: 1 - type: LoadMapRule preloadedGrid: TravelingCuisine - type: entity + parent: BaseUnknownShuttleRule id: UnknownShuttleDisasterEvacPod - parent: BaseGameRule - noSpawn: true components: - - type: StationEvent - startAnnouncement: station-event-unknown-shuttle-incoming - startAudio: - path: /Audio/Announcements/attention.ogg - weight: 5 - reoccurrenceDelay: 30 - duration: 1 - type: LoadMapRule preloadedGrid: DisasterEvacPod - type: entity + parent: BaseUnknownShuttleRule id: UnknownShuttleHonki - parent: BaseGameRule - noSpawn: true components: - type: StationEvent - startAnnouncement: station-event-unknown-shuttle-incoming - startAudio: - path: /Audio/Announcements/attention.ogg weight: 2 - reoccurrenceDelay: 30 - duration: 1 - type: LoadMapRule preloadedGrid: Honki - type: entity + parent: BaseUnknownShuttleRule id: UnknownShuttleSyndieEvacPod - parent: BaseGameRule - noSpawn: true components: - type: StationEvent - startAnnouncement: station-event-unknown-shuttle-incoming - startAudio: - path: /Audio/Announcements/attention.ogg weight: 2 - reoccurrenceDelay: 30 - duration: 1 - type: LoadMapRule preloadedGrid: SyndieEvacPod From 9d2b4ed3b22e548f02aeee7caa855b65b37dda24 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Mon, 3 Jun 2024 20:23:43 -0400 Subject: [PATCH 56/63] Add an integration test for solution fill level sprites. (#28564) --- .../Tests/FillLevelSpriteTest.cs | 71 +++++++++++++++++++ .../Prototypes/Entities/Objects/Fun/darts.yml | 4 -- .../Entities/Objects/Specific/chemistry.yml | 4 ++ 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 Content.IntegrationTests/Tests/FillLevelSpriteTest.cs diff --git a/Content.IntegrationTests/Tests/FillLevelSpriteTest.cs b/Content.IntegrationTests/Tests/FillLevelSpriteTest.cs new file mode 100644 index 0000000000..37e777fa8c --- /dev/null +++ b/Content.IntegrationTests/Tests/FillLevelSpriteTest.cs @@ -0,0 +1,71 @@ +using System.Linq; +using Content.Shared.Chemistry.Components; +using Robust.Client.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.IntegrationTests.Tests; + +/// +/// Tests to see if any entity prototypes specify solution fill level sprites that don't exist. +/// +[TestFixture] +public sealed class FillLevelSpriteTest +{ + private static readonly string[] HandStateNames = ["left", "right"]; + + [Test] + public async Task FillLevelSpritesExist() + { + await using var pair = await PoolManager.GetServerClient(); + var client = pair.Client; + var protoMan = client.ResolveDependency(); + var componentFactory = client.ResolveDependency(); + + await client.WaitAssertion(() => + { + var protos = protoMan.EnumeratePrototypes() + .Where(p => !p.Abstract) + .Where(p => !pair.IsTestPrototype(p)) + .Where(p => p.TryGetComponent(out _, componentFactory)) + .OrderBy(p => p.ID) + .ToList(); + + foreach (var proto in protos) + { + Assert.That(proto.TryGetComponent(out var visuals, componentFactory)); + Assert.That(proto.TryGetComponent(out var sprite, componentFactory)); + + var rsi = sprite.BaseRSI; + + // Test base sprite fills + if (!string.IsNullOrEmpty(visuals.FillBaseName)) + { + for (var i = 1; i <= visuals.MaxFillLevels; i++) + { + var state = $"{visuals.FillBaseName}{i}"; + Assert.That(rsi.TryGetState(state, out _), @$"{proto.ID} has SolutionContainerVisualsComponent with + MaxFillLevels = {visuals.MaxFillLevels}, but {rsi.Path} doesn't have state {state}!"); + } + } + + // Test inhand sprite fills + if (!string.IsNullOrEmpty(visuals.InHandsFillBaseName)) + { + for (var i = 1; i <= visuals.InHandsMaxFillLevels; i++) + { + foreach (var handname in HandStateNames) + { + var state = $"inhand-{handname}{visuals.InHandsFillBaseName}{i}"; + Assert.That(rsi.TryGetState(state, out _), @$"{proto.ID} has SolutionContainerVisualsComponent with + InHandsMaxFillLevels = {visuals.InHandsMaxFillLevels}, but {rsi.Path} doesn't have state {state}!"); + } + + } + } + } + }); + + await pair.CleanReturnAsync(); + } +} diff --git a/Resources/Prototypes/Entities/Objects/Fun/darts.yml b/Resources/Prototypes/Entities/Objects/Fun/darts.yml index 36c841995e..c0b5eb3399 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/darts.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/darts.yml @@ -83,10 +83,6 @@ max: 1 - !type:DoActsBehavior acts: [ "Destruction" ] - - type: Appearance - - type: SolutionContainerVisuals - maxFillLevels: 1 - fillBaseName: dart - type: entity parent: Dart diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml index ce0e0b629a..dd15a90baa 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml @@ -233,6 +233,8 @@ sprite: Objects/Specific/Chemistry/beaker_cryostasis.rsi layers: - state: beakernoreact + - type: SolutionContainerVisuals + maxFillLevels: 0 - type: SolutionContainerManager solutions: beaker: @@ -251,6 +253,8 @@ sprite: Objects/Specific/Chemistry/beaker_bluespace.rsi layers: - state: beakerbluespace + - type: SolutionContainerVisuals + maxFillLevels: 0 - type: SolutionContainerManager solutions: beaker: From a3a1538d32c4e0c7d9aeab9790e0c522a211fc79 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Tue, 4 Jun 2024 11:53:24 +0000 Subject: [PATCH 57/63] move gamerule components to shared (#28572) * move MinMax to shared * cleanup MinMax * move other ticking components to shared just because * remove unused prototype file * update everything to use shared components * test * test 2 * test 3 --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../DestructibleDestructionTest.cs | 1 + .../Tests/GameRules/FailAndStartPresetTest.cs | 2 +- .../Tests/GameRules/RuleMaxTimeRestartTest.cs | 2 +- Content.Server/Administration/ServerApi.cs | 2 +- Content.Server/Antag/AntagSelectionSystem.cs | 2 +- .../Components/AntagSelectionComponent.cs | 2 +- .../Antag/MobReplacementRuleSystem.cs | 2 +- .../Behaviors/SpawnEntitiesBehavior.cs | 6 ++--- .../Destructible/Thresholds/MinMax.cs | 26 ------------------- .../GameTicking/GameTicker.GameRule.cs | 2 +- .../GameTicking/Rules/DeathMatchRuleSystem.cs | 2 +- .../GameTicking/Rules/GameRulePrototype.cs | 15 ----------- .../Rules/GameRuleSystem.Utility.cs | 2 +- .../GameTicking/Rules/GameRuleSystem.cs | 2 +- .../Rules/InactivityTimeRestartRuleSystem.cs | 2 +- .../Rules/KillCalloutRuleSystem.cs | 2 +- .../GameTicking/Rules/LoadMapRuleSystem.cs | 2 +- .../Rules/MaxTimeRestartRuleSystem.cs | 2 +- .../GameTicking/Rules/NukeopsRuleSystem.cs | 2 +- .../GameTicking/Rules/RespawnRuleSystem.cs | 2 +- .../Rules/RevolutionaryRuleSystem.cs | 2 +- .../RoundstartStationVariationRuleSystem.cs | 2 +- .../GameTicking/Rules/SandboxRuleSystem.cs | 2 +- .../GameTicking/Rules/SecretRuleSystem.cs | 2 +- .../GameTicking/Rules/SubGamemodesSystem.cs | 2 +- .../GameTicking/Rules/TraitorRuleSystem.cs | 2 +- .../GameTicking/Rules/ZombieRuleSystem.cs | 2 +- Content.Server/Objectives/ObjectivesSystem.cs | 2 +- .../PowerMonitoringConsoleSystem.cs | 2 +- .../EntitySystems/ConditionalSpawnerSystem.cs | 2 +- .../BasicStationEventSchedulerSystem.cs | 2 +- .../Events/AlertLevelInterceptionRule.cs | 4 +-- .../StationEvents/Events/AnomalySpawnRule.cs | 2 +- .../Events/BluespaceArtifactRule.cs | 2 +- .../Events/BluespaceLockerRule.cs | 2 +- .../StationEvents/Events/BreakerFlipRule.cs | 2 +- .../Events/BureaucraticErrorRule.cs | 2 +- .../StationEvents/Events/CargoGiftsRule.cs | 2 +- .../StationEvents/Events/ClericalErrorRule.cs | 2 +- .../StationEvents/Events/FalseAlarmRule.cs | 2 +- .../StationEvents/Events/GasLeakRule.cs | 2 +- .../StationEvents/Events/ImmovableRodRule.cs | 2 +- .../StationEvents/Events/IonStormRule.cs | 2 +- .../StationEvents/Events/KudzuGrowthRule.cs | 2 +- .../Events/MassHallucinationsRule.cs | 2 +- .../StationEvents/Events/MeteorSwarmRule.cs | 2 +- .../StationEvents/Events/NinjaSpawnRule.cs | 2 +- .../Events/PowerGridCheckRule.cs | 2 +- .../Events/RandomEntityStorageSpawnRule.cs | 2 +- .../Events/RandomSentienceRule.cs | 2 +- .../StationEvents/Events/RandomSpawnRule.cs | 2 +- .../StationEvents/Events/SolarFlareRule.cs | 2 +- .../Events/StationEventSystem.cs | 2 +- .../StationEvents/Events/VentClogRule.cs | 2 +- .../StationEvents/Events/VentCrittersRule.cs | 2 +- .../RampingStationEventSchedulerSystem.cs | 2 +- .../Destructible/Thresholds/MinMax.cs | 24 +++++++++++++++++ .../Components/ActiveGameRuleComponent.cs | 6 ++--- .../Components/DelayedStartRuleComponent.cs | 2 +- .../Components/EndedGameRuleComponent.cs | 6 ++--- .../Components/GameRuleComponent.cs | 4 +-- 61 files changed, 88 insertions(+), 108 deletions(-) delete mode 100644 Content.Server/Destructible/Thresholds/MinMax.cs delete mode 100644 Content.Server/GameTicking/Rules/GameRulePrototype.cs create mode 100644 Content.Shared/Destructible/Thresholds/MinMax.cs rename {Content.Server => Content.Shared}/GameTicking/Components/ActiveGameRuleComponent.cs (67%) rename {Content.Server => Content.Shared}/GameTicking/Components/DelayedStartRuleComponent.cs (91%) rename {Content.Server => Content.Shared}/GameTicking/Components/EndedGameRuleComponent.cs (61%) rename {Content.Server => Content.Shared}/GameTicking/Components/GameRuleComponent.cs (94%) diff --git a/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs b/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs index e14a826467..a50238d8f5 100644 --- a/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs +++ b/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs @@ -3,6 +3,7 @@ using Content.Server.Destructible.Thresholds; using Content.Server.Destructible.Thresholds.Behaviors; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; +using Content.Shared.Destructible.Thresholds; using Robust.Shared.GameObjects; using Robust.Shared.Prototypes; using static Content.IntegrationTests.Tests.Destructible.DestructibleTestPrototypes; diff --git a/Content.IntegrationTests/Tests/GameRules/FailAndStartPresetTest.cs b/Content.IntegrationTests/Tests/GameRules/FailAndStartPresetTest.cs index 1fed226bee..09a27c1bae 100644 --- a/Content.IntegrationTests/Tests/GameRules/FailAndStartPresetTest.cs +++ b/Content.IntegrationTests/Tests/GameRules/FailAndStartPresetTest.cs @@ -1,9 +1,9 @@ #nullable enable using Content.Server.GameTicking; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Presets; using Content.Shared.CCVar; using Content.Shared.GameTicking; +using Content.Shared.GameTicking.Components; using Robust.Shared.GameObjects; namespace Content.IntegrationTests.Tests.GameRules; diff --git a/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs b/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs index 20a157e33e..4708bd10c0 100644 --- a/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs +++ b/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs @@ -1,9 +1,9 @@ using Content.Server.GameTicking; using Content.Server.GameTicking.Commands; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; using Content.Shared.CCVar; +using Content.Shared.GameTicking.Components; using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.Timing; diff --git a/Content.Server/Administration/ServerApi.cs b/Content.Server/Administration/ServerApi.cs index 04fd38598f..d0f23db637 100644 --- a/Content.Server/Administration/ServerApi.cs +++ b/Content.Server/Administration/ServerApi.cs @@ -8,13 +8,13 @@ using System.Text.Json.Nodes; using System.Threading.Tasks; using Content.Server.Administration.Systems; using Content.Server.GameTicking; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Presets; using Content.Server.GameTicking.Rules.Components; using Content.Server.Maps; using Content.Server.RoundEnd; using Content.Shared.Administration.Managers; using Content.Shared.CCVar; +using Content.Shared.GameTicking.Components; using Content.Shared.Prototypes; using Robust.Server.ServerStatus; using Robust.Shared.Asynchronous; diff --git a/Content.Server/Antag/AntagSelectionSystem.cs b/Content.Server/Antag/AntagSelectionSystem.cs index 710bb8f3d7..52ccb1bd70 100644 --- a/Content.Server/Antag/AntagSelectionSystem.cs +++ b/Content.Server/Antag/AntagSelectionSystem.cs @@ -2,7 +2,6 @@ using System.Linq; using Content.Server.Antag.Components; using Content.Server.Chat.Managers; using Content.Server.GameTicking; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules; using Content.Server.Ghost.Roles; using Content.Server.Ghost.Roles.Components; @@ -15,6 +14,7 @@ using Content.Server.Shuttles.Components; using Content.Server.Station.Systems; using Content.Shared.Antag; using Content.Shared.GameTicking; +using Content.Shared.GameTicking.Components; using Content.Shared.Ghost; using Content.Shared.Humanoid; using Content.Shared.Players; diff --git a/Content.Server/Antag/Components/AntagSelectionComponent.cs b/Content.Server/Antag/Components/AntagSelectionComponent.cs index f70c27d12f..1ab16e8aec 100644 --- a/Content.Server/Antag/Components/AntagSelectionComponent.cs +++ b/Content.Server/Antag/Components/AntagSelectionComponent.cs @@ -1,6 +1,6 @@ using Content.Server.Administration.Systems; -using Content.Server.Destructible.Thresholds; using Content.Shared.Antag; +using Content.Shared.Destructible.Thresholds; using Content.Shared.Roles; using Content.Shared.Storage; using Content.Shared.Whitelist; diff --git a/Content.Server/Antag/MobReplacementRuleSystem.cs b/Content.Server/Antag/MobReplacementRuleSystem.cs index 18837b5a7c..eeff765d8b 100644 --- a/Content.Server/Antag/MobReplacementRuleSystem.cs +++ b/Content.Server/Antag/MobReplacementRuleSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Antag.Mimic; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; +using Content.Shared.GameTicking.Components; using Content.Shared.VendingMachines; using Robust.Shared.Map; using Robust.Shared.Random; diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs index 057b6df9df..4ec6fa9e90 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/SpawnEntitiesBehavior.cs @@ -1,12 +1,12 @@ using System.Numerics; using Content.Server.Forensics; using Content.Server.Stack; +using Content.Shared.Destructible.Thresholds; using Content.Shared.Prototypes; using Content.Shared.Stacks; using Robust.Server.GameObjects; using Robust.Shared.Prototypes; using Robust.Shared.Random; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; namespace Content.Server.Destructible.Thresholds.Behaviors { @@ -17,8 +17,8 @@ namespace Content.Server.Destructible.Thresholds.Behaviors /// /// Entities spawned on reaching this threshold, from a min to a max. /// - [DataField("spawn", customTypeSerializer:typeof(PrototypeIdDictionarySerializer))] - public Dictionary Spawn { get; set; } = new(); + [DataField] + public Dictionary Spawn = new(); [DataField("offset")] public float Offset { get; set; } = 0.5f; diff --git a/Content.Server/Destructible/Thresholds/MinMax.cs b/Content.Server/Destructible/Thresholds/MinMax.cs deleted file mode 100644 index c44864183a..0000000000 --- a/Content.Server/Destructible/Thresholds/MinMax.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Robust.Shared.Random; - -namespace Content.Server.Destructible.Thresholds -{ - [Serializable] - [DataDefinition] - public partial struct MinMax - { - [DataField("min")] - public int Min; - - [DataField("max")] - public int Max; - - public MinMax(int min, int max) - { - Min = min; - Max = max; - } - - public int Next(IRobustRandom random) - { - return random.Next(Min, Max + 1); - } - } -} diff --git a/Content.Server/GameTicking/GameTicker.GameRule.cs b/Content.Server/GameTicking/GameTicker.GameRule.cs index a6d0a4baf0..2a33d01bd0 100644 --- a/Content.Server/GameTicking/GameTicker.GameRule.cs +++ b/Content.Server/GameTicking/GameTicker.GameRule.cs @@ -1,9 +1,9 @@ using System.Linq; using Content.Server.Administration; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Shared.Administration; using Content.Shared.Database; +using Content.Shared.GameTicking.Components; using Content.Shared.Prototypes; using JetBrains.Annotations; using Robust.Shared.Console; diff --git a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs index 9e3203d170..557e44f095 100644 --- a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs @@ -1,12 +1,12 @@ using System.Linq; using Content.Server.Administration.Commands; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.KillTracking; using Content.Server.Mind; using Content.Server.Points; using Content.Server.RoundEnd; using Content.Server.Station.Systems; +using Content.Shared.GameTicking.Components; using Content.Shared.Points; using Content.Shared.Storage; using Robust.Server.GameObjects; diff --git a/Content.Server/GameTicking/Rules/GameRulePrototype.cs b/Content.Server/GameTicking/Rules/GameRulePrototype.cs deleted file mode 100644 index 47f99184f7..0000000000 --- a/Content.Server/GameTicking/Rules/GameRulePrototype.cs +++ /dev/null @@ -1,15 +0,0 @@ - - -namespace Content.Server.GameTicking.Rules; - -/* -[Prototype("gameRule")] -public sealed partial class GameRulePrototype : IPrototype -{ - [IdDataField] - public string ID { get; private set; } = default!; - - [DataField("config", required: true)] - public GameRuleConfiguration Configuration { get; private set; } = default!; -} -*/ diff --git a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs index 9ac7a6edbb..5a5eb720cf 100644 --- a/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs +++ b/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs @@ -1,8 +1,8 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Station.Components; +using Content.Shared.GameTicking.Components; using Content.Shared.Random.Helpers; using Robust.Server.GameObjects; using Robust.Shared.Collections; diff --git a/Content.Server/GameTicking/Rules/GameRuleSystem.cs b/Content.Server/GameTicking/Rules/GameRuleSystem.cs index 05374aa139..730748ce6b 100644 --- a/Content.Server/GameTicking/Rules/GameRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/GameRuleSystem.cs @@ -1,6 +1,6 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Chat.Managers; -using Content.Server.GameTicking.Components; +using Content.Shared.GameTicking.Components; using Robust.Server.GameObjects; using Robust.Shared.Random; using Robust.Shared.Timing; diff --git a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs index 01fa387595..e56537c438 100644 --- a/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/InactivityTimeRestartRuleSystem.cs @@ -1,7 +1,7 @@ using System.Threading; using Content.Server.Chat.Managers; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; +using Content.Shared.GameTicking.Components; using Robust.Server.Player; using Robust.Shared.Player; using Timer = Robust.Shared.Timing.Timer; diff --git a/Content.Server/GameTicking/Rules/KillCalloutRuleSystem.cs b/Content.Server/GameTicking/Rules/KillCalloutRuleSystem.cs index 3da55e30c9..8f706fd2ad 100644 --- a/Content.Server/GameTicking/Rules/KillCalloutRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/KillCalloutRuleSystem.cs @@ -1,8 +1,8 @@ using Content.Server.Chat.Managers; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.KillTracking; using Content.Shared.Chat; +using Content.Shared.GameTicking.Components; using Robust.Server.Player; using Robust.Shared.Player; using Robust.Shared.Random; diff --git a/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs b/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs index 1c09d6e86e..3594242bcd 100644 --- a/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/LoadMapRuleSystem.cs @@ -1,6 +1,6 @@ -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.GridPreloader; +using Content.Shared.GameTicking.Components; using Robust.Server.GameObjects; using Robust.Server.Maps; using Robust.Shared.Map; diff --git a/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs b/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs index cae99fee9f..db9df8a5b0 100644 --- a/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/MaxTimeRestartRuleSystem.cs @@ -1,7 +1,7 @@ using System.Threading; using Content.Server.Chat.Managers; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; +using Content.Shared.GameTicking.Components; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 6688bfd980..5c3459ef81 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -11,6 +11,7 @@ using Content.Server.Shuttles.Systems; using Content.Server.Station.Components; using Content.Server.Store.Components; using Content.Server.Store.Systems; +using Content.Shared.GameTicking.Components; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.NPC.Components; @@ -24,7 +25,6 @@ using Robust.Shared.Map; using Robust.Shared.Random; using Robust.Shared.Utility; using System.Linq; -using Content.Server.GameTicking.Components; using Content.Shared.Store.Components; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs b/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs index 3f8d31f622..38102f1a2e 100644 --- a/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/RespawnRuleSystem.cs @@ -1,9 +1,9 @@ using Content.Server.Chat.Managers; using Content.Server.Database.Migrations.Postgres; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Station.Systems; using Content.Shared.Chat; +using Content.Shared.GameTicking.Components; using Content.Shared.Interaction.Events; using Content.Shared.Mind; using Content.Shared.Mobs; diff --git a/Content.Server/GameTicking/Rules/RevolutionaryRuleSystem.cs b/Content.Server/GameTicking/Rules/RevolutionaryRuleSystem.cs index 58ced96295..c5f88ab6cf 100644 --- a/Content.Server/GameTicking/Rules/RevolutionaryRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/RevolutionaryRuleSystem.cs @@ -12,6 +12,7 @@ using Content.Server.RoundEnd; using Content.Server.Shuttles.Systems; using Content.Server.Station.Systems; using Content.Shared.Database; +using Content.Shared.GameTicking.Components; using Content.Shared.Humanoid; using Content.Shared.IdentityManagement; using Content.Shared.Mind; @@ -27,7 +28,6 @@ using Content.Shared.Stunnable; using Content.Shared.Zombies; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -using Content.Server.GameTicking.Components; using Content.Shared.Cuffs.Components; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/RoundstartStationVariationRuleSystem.cs b/Content.Server/GameTicking/Rules/RoundstartStationVariationRuleSystem.cs index f09ed3ebc3..570889155b 100644 --- a/Content.Server/GameTicking/Rules/RoundstartStationVariationRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/RoundstartStationVariationRuleSystem.cs @@ -1,9 +1,9 @@ using System.Linq; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Shuttles.Systems; using Content.Server.Station.Components; using Content.Server.Station.Events; +using Content.Shared.GameTicking.Components; using Content.Shared.Storage; using Robust.Shared.Prototypes; using Robust.Shared.Random; diff --git a/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs b/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs index c60670a3ad..23e9ee5a7d 100644 --- a/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SandboxRuleSystem.cs @@ -1,6 +1,6 @@ -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Sandbox; +using Content.Shared.GameTicking.Components; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/SecretRuleSystem.cs b/Content.Server/GameTicking/Rules/SecretRuleSystem.cs index d25262b797..320f9d197a 100644 --- a/Content.Server/GameTicking/Rules/SecretRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SecretRuleSystem.cs @@ -1,10 +1,10 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Server.Administration.Logs; -using Content.Server.GameTicking.Components; using Content.Server.Chat.Managers; using Content.Server.GameTicking.Presets; using Content.Server.GameTicking.Rules.Components; +using Content.Shared.GameTicking.Components; using Content.Shared.Random; using Content.Shared.CCVar; using Content.Shared.Database; diff --git a/Content.Server/GameTicking/Rules/SubGamemodesSystem.cs b/Content.Server/GameTicking/Rules/SubGamemodesSystem.cs index 4486ee40fb..4fe3827ce5 100644 --- a/Content.Server/GameTicking/Rules/SubGamemodesSystem.cs +++ b/Content.Server/GameTicking/Rules/SubGamemodesSystem.cs @@ -1,5 +1,5 @@ -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; +using Content.Shared.GameTicking.Components; using Content.Shared.Storage; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 29de85a42e..17442da857 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -5,6 +5,7 @@ using Content.Server.Objectives; using Content.Server.PDA.Ringer; using Content.Server.Roles; using Content.Server.Traitor.Uplink; +using Content.Shared.GameTicking.Components; using Content.Shared.Mind; using Content.Shared.NPC.Systems; using Content.Shared.Objectives.Components; @@ -15,7 +16,6 @@ using Robust.Shared.Prototypes; using Robust.Shared.Random; using System.Linq; using System.Text; -using Content.Server.GameTicking.Components; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index 97e5fd3fc4..95d1f791ef 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -6,6 +6,7 @@ using Content.Server.RoundEnd; using Content.Server.Station.Components; using Content.Server.Station.Systems; using Content.Server.Zombies; +using Content.Shared.GameTicking.Components; using Content.Shared.Humanoid; using Content.Shared.Mind; using Content.Shared.Mobs; @@ -15,7 +16,6 @@ using Content.Shared.Zombies; using Robust.Shared.Player; using Robust.Shared.Timing; using System.Globalization; -using Content.Server.GameTicking.Components; namespace Content.Server.GameTicking.Rules; diff --git a/Content.Server/Objectives/ObjectivesSystem.cs b/Content.Server/Objectives/ObjectivesSystem.cs index f8ecc22828..18077b413a 100644 --- a/Content.Server/Objectives/ObjectivesSystem.cs +++ b/Content.Server/Objectives/ObjectivesSystem.cs @@ -1,6 +1,7 @@ using Content.Server.GameTicking; using Content.Server.Shuttles.Systems; using Content.Shared.Cuffs.Components; +using Content.Shared.GameTicking.Components; using Content.Shared.Mind; using Content.Shared.Objectives.Components; using Content.Shared.Objectives.Systems; @@ -9,7 +10,6 @@ using Content.Shared.Random.Helpers; using Robust.Shared.Prototypes; using Robust.Shared.Random; using System.Linq; -using Content.Server.GameTicking.Components; using System.Text; using Robust.Server.Player; diff --git a/Content.Server/Power/EntitySystems/PowerMonitoringConsoleSystem.cs b/Content.Server/Power/EntitySystems/PowerMonitoringConsoleSystem.cs index 42c84b7f43..35b17dc958 100644 --- a/Content.Server/Power/EntitySystems/PowerMonitoringConsoleSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerMonitoringConsoleSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Power.Nodes; using Content.Server.Power.NodeGroups; using Content.Server.Station.Components; using Content.Server.StationEvents.Components; +using Content.Shared.GameTicking.Components; using Content.Shared.Pinpointer; using Content.Shared.Power; using JetBrains.Annotations; @@ -13,7 +14,6 @@ using Robust.Server.GameObjects; using Robust.Shared.Map.Components; using Robust.Shared.Utility; using System.Linq; -using Content.Server.GameTicking.Components; namespace Content.Server.Power.EntitySystems; diff --git a/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs b/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs index 75f8618798..f57481b05b 100644 --- a/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs +++ b/Content.Server/Spawners/EntitySystems/ConditionalSpawnerSystem.cs @@ -1,8 +1,8 @@ using System.Numerics; using Content.Server.GameTicking; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Spawners.Components; +using Content.Shared.GameTicking.Components; using JetBrains.Annotations; using Robust.Shared.Random; diff --git a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs index 7e32f546be..501d9033b9 100644 --- a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs +++ b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs @@ -1,11 +1,11 @@ using System.Linq; using Content.Server.Administration; using Content.Server.GameTicking; -using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; using Content.Server.StationEvents.Components; using Content.Shared.Administration; +using Content.Shared.GameTicking.Components; using JetBrains.Annotations; using Robust.Shared.Random; using Robust.Shared.Toolshed; diff --git a/Content.Server/StationEvents/Events/AlertLevelInterceptionRule.cs b/Content.Server/StationEvents/Events/AlertLevelInterceptionRule.cs index a78a542d3b..916d7d1688 100644 --- a/Content.Server/StationEvents/Events/AlertLevelInterceptionRule.cs +++ b/Content.Server/StationEvents/Events/AlertLevelInterceptionRule.cs @@ -1,6 +1,6 @@ -using Content.Server.GameTicking.Components; using Content.Server.StationEvents.Components; using Content.Server.AlertLevel; +using Content.Shared.GameTicking.Components; namespace Content.Server.StationEvents.Events; @@ -20,4 +20,4 @@ public sealed class AlertLevelInterceptionRule : StationEventSystem /// Added to game rules before and removed before . /// Mutually exclusive with . /// [RegisterComponent] -public sealed partial class ActiveGameRuleComponent : Component -{ -} +public sealed partial class ActiveGameRuleComponent : Component; diff --git a/Content.Server/GameTicking/Components/DelayedStartRuleComponent.cs b/Content.Shared/GameTicking/Components/DelayedStartRuleComponent.cs similarity index 91% rename from Content.Server/GameTicking/Components/DelayedStartRuleComponent.cs rename to Content.Shared/GameTicking/Components/DelayedStartRuleComponent.cs index de4be83627..9275da29b0 100644 --- a/Content.Server/GameTicking/Components/DelayedStartRuleComponent.cs +++ b/Content.Shared/GameTicking/Components/DelayedStartRuleComponent.cs @@ -1,6 +1,6 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; -namespace Content.Server.GameTicking.Components; +namespace Content.Shared.GameTicking.Components; /// /// Generic component used to track a gamerule that's start has been delayed. diff --git a/Content.Server/GameTicking/Components/EndedGameRuleComponent.cs b/Content.Shared/GameTicking/Components/EndedGameRuleComponent.cs similarity index 61% rename from Content.Server/GameTicking/Components/EndedGameRuleComponent.cs rename to Content.Shared/GameTicking/Components/EndedGameRuleComponent.cs index 3234bfff3a..5e209ed78a 100644 --- a/Content.Server/GameTicking/Components/EndedGameRuleComponent.cs +++ b/Content.Shared/GameTicking/Components/EndedGameRuleComponent.cs @@ -1,10 +1,8 @@ -namespace Content.Server.GameTicking.Components; +namespace Content.Shared.GameTicking.Components; /// /// Added to game rules before . /// Mutually exclusive with . /// [RegisterComponent] -public sealed partial class EndedGameRuleComponent : Component -{ -} +public sealed partial class EndedGameRuleComponent : Component; diff --git a/Content.Server/GameTicking/Components/GameRuleComponent.cs b/Content.Shared/GameTicking/Components/GameRuleComponent.cs similarity index 94% rename from Content.Server/GameTicking/Components/GameRuleComponent.cs rename to Content.Shared/GameTicking/Components/GameRuleComponent.cs index 635452b3f3..4e93c2b003 100644 --- a/Content.Server/GameTicking/Components/GameRuleComponent.cs +++ b/Content.Shared/GameTicking/Components/GameRuleComponent.cs @@ -1,8 +1,8 @@ -using Content.Server.Destructible.Thresholds; +using Content.Shared.Destructible.Thresholds; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; -namespace Content.Server.GameTicking.Components; +namespace Content.Shared.GameTicking.Components; /// /// Component attached to all gamerule entities. From 87fe804831e15ccd757d5830c9413811ed2fb780 Mon Sep 17 00:00:00 2001 From: Ghagliiarghii <68826635+Ghagliiarghii@users.noreply.github.com> Date: Tue, 4 Jun 2024 07:57:17 -0400 Subject: [PATCH 58/63] tyvm, tysm (#28577) * tyvm, tysm * cya -> see you * ya --- Resources/Locale/en-US/speech/speech-chatsan.ftl | 9 +++++++++ Resources/Prototypes/Accents/word_replacements.yml | 3 +++ 2 files changed, 12 insertions(+) diff --git a/Resources/Locale/en-US/speech/speech-chatsan.ftl b/Resources/Locale/en-US/speech/speech-chatsan.ftl index 25e6c6f1ea..ef94507295 100644 --- a/Resources/Locale/en-US/speech/speech-chatsan.ftl +++ b/Resources/Locale/en-US/speech/speech-chatsan.ftl @@ -120,3 +120,12 @@ chatsan-replacement-43 = i guess chatsan-word-44 = tbf chatsan-replacement-44 = to be fair + +chatsan-word-45 = tysm +chatsan-replacement-45 = thank you so much + +chatsan-word-46 = tyvm +chatsan-replacement-46 = thank you very much + +chatsan-word-47 = cya +chatsan-replacement-47 = see ya \ No newline at end of file diff --git a/Resources/Prototypes/Accents/word_replacements.yml b/Resources/Prototypes/Accents/word_replacements.yml index 9a801d786d..40cc94e453 100644 --- a/Resources/Prototypes/Accents/word_replacements.yml +++ b/Resources/Prototypes/Accents/word_replacements.yml @@ -425,6 +425,9 @@ chatsan-word-42: chatsan-replacement-42 chatsan-word-43: chatsan-replacement-43 chatsan-word-44: chatsan-replacement-44 + chatsan-word-45: chatsan-replacement-45 + chatsan-word-46: chatsan-replacement-46 + chatsan-word-47: chatsan-replacement-47 - type: accent id: liar From 58647e703683e848730589ab003a94400f6c1075 Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Tue, 4 Jun 2024 15:11:48 +0200 Subject: [PATCH 59/63] Don't switch-unwield if mob has more than 2 hands (#28438) --- Content.Shared/Wieldable/WieldableSystem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Wieldable/WieldableSystem.cs b/Content.Shared/Wieldable/WieldableSystem.cs index c09044f84b..cb95c1d7e7 100644 --- a/Content.Shared/Wieldable/WieldableSystem.cs +++ b/Content.Shared/Wieldable/WieldableSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Shared.Examine; using Content.Shared.Hands; using Content.Shared.Hands.Components; @@ -94,7 +95,8 @@ public sealed class WieldableSystem : EntitySystem private void OnDeselectWieldable(EntityUid uid, WieldableComponent component, HandDeselectedEvent args) { - if (!component.Wielded) + if (!component.Wielded || + _handsSystem.EnumerateHands(args.User).Count() > 2) return; TryUnwield(uid, component, args.User); From d4fe7eda515a1374ec753e740f025aefcae18e5a Mon Sep 17 00:00:00 2001 From: Hannah Giovanna Dawson Date: Tue, 4 Jun 2024 14:23:09 +0100 Subject: [PATCH 60/63] SS14-26964 Clown Waddling Replicates, etc (#26983) --- .../Movement/Systems/WaddleAnimationSystem.cs | 168 ++++++++---------- .../Movement/Systems/WaddleAnimationSystem.cs | 5 + .../Components/WaddleWhenWornComponent.cs | 11 +- .../EntitySystems}/WaddleClothingSystem.cs | 17 +- .../Components/WaddleAnimationComponent.cs | 28 +-- .../Systems/SharedWaddleAnimationSystem.cs | 106 +++++++++++ 6 files changed, 213 insertions(+), 122 deletions(-) create mode 100644 Content.Server/Movement/Systems/WaddleAnimationSystem.cs rename {Content.Client/Clothing/Systems => Content.Shared/Clothing/EntitySystems}/WaddleClothingSystem.cs (59%) create mode 100644 Content.Shared/Movement/Systems/SharedWaddleAnimationSystem.cs diff --git a/Content.Client/Movement/Systems/WaddleAnimationSystem.cs b/Content.Client/Movement/Systems/WaddleAnimationSystem.cs index 9555c1f6b9..0ed2d04f69 100644 --- a/Content.Client/Movement/Systems/WaddleAnimationSystem.cs +++ b/Content.Client/Movement/Systems/WaddleAnimationSystem.cs @@ -2,94 +2,115 @@ using Content.Client.Buckle; using Content.Client.Gravity; using Content.Shared.ActionBlocker; -using Content.Shared.Buckle.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Components; -using Content.Shared.Movement.Events; -using Content.Shared.StatusEffect; -using Content.Shared.Stunnable; +using Content.Shared.Movement.Systems; using Robust.Client.Animations; using Robust.Client.GameObjects; using Robust.Shared.Animations; -using Robust.Shared.Timing; namespace Content.Client.Movement.Systems; -public sealed class WaddleAnimationSystem : EntitySystem +public sealed class WaddleAnimationSystem : SharedWaddleAnimationSystem { [Dependency] private readonly AnimationPlayerSystem _animation = default!; [Dependency] private readonly GravitySystem _gravity = default!; - [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; [Dependency] private readonly BuckleSystem _buckle = default!; [Dependency] private readonly MobStateSystem _mobState = default!; public override void Initialize() { - SubscribeLocalEvent(OnMovementInput); - SubscribeLocalEvent(OnStartedWalking); - SubscribeLocalEvent(OnStoppedWalking); + base.Initialize(); + + SubscribeAllEvent(OnStartWaddling); SubscribeLocalEvent(OnAnimationCompleted); - SubscribeLocalEvent(OnStunned); - SubscribeLocalEvent(OnKnockedDown); - SubscribeLocalEvent(OnBuckleChange); + SubscribeAllEvent(OnStopWaddling); } - private void OnMovementInput(EntityUid entity, WaddleAnimationComponent component, MoveInputEvent args) + private void OnStartWaddling(StartedWaddlingEvent msg, EntitySessionEventArgs args) { - // Prediction mitigation. Prediction means that MoveInputEvents are spammed repeatedly, even though you'd assume - // they're once-only for the user actually doing something. As such do nothing if we're just repeating this FoR. - if (!_timing.IsFirstTimePredicted) - { - return; - } - - if (!args.HasDirectionalMovement && component.IsCurrentlyWaddling) - { - var stopped = new StoppedWaddlingEvent(entity); - - RaiseLocalEvent(entity, ref stopped); - - return; - } - - // Only start waddling if we're not currently AND we're actually moving. - if (component.IsCurrentlyWaddling || !args.HasDirectionalMovement) - return; - - var started = new StartedWaddlingEvent(entity); - - RaiseLocalEvent(entity, ref started); + if (TryComp(GetEntity(msg.Entity), out var comp)) + StartWaddling((GetEntity(msg.Entity), comp)); } - private void OnStartedWalking(EntityUid uid, WaddleAnimationComponent component, StartedWaddlingEvent args) + private void OnStopWaddling(StoppedWaddlingEvent msg, EntitySessionEventArgs args) { - if (_animation.HasRunningAnimation(uid, component.KeyName)) + if (TryComp(GetEntity(msg.Entity), out var comp)) + StopWaddling((GetEntity(msg.Entity), comp)); + } + + private void StartWaddling(Entity entity) + { + if (_animation.HasRunningAnimation(entity.Owner, entity.Comp.KeyName)) return; - if (!TryComp(uid, out var mover)) + if (!TryComp(entity.Owner, out var mover)) return; - if (_gravity.IsWeightless(uid)) + if (_gravity.IsWeightless(entity.Owner)) return; - - if (!_actionBlocker.CanMove(uid, mover)) + if (!_actionBlocker.CanMove(entity.Owner, mover)) return; // Do nothing if buckled in - if (_buckle.IsBuckled(uid)) + if (_buckle.IsBuckled(entity.Owner)) return; // Do nothing if crit or dead (for obvious reasons) - if (_mobState.IsIncapacitated(uid)) + if (_mobState.IsIncapacitated(entity.Owner)) return; - var tumbleIntensity = component.LastStep ? 360 - component.TumbleIntensity : component.TumbleIntensity; - var len = mover.Sprinting ? component.AnimationLength * component.RunAnimationLengthMultiplier : component.AnimationLength; + PlayWaddleAnimationUsing( + (entity.Owner, entity.Comp), + CalculateAnimationLength(entity.Comp, mover), + CalculateTumbleIntensity(entity.Comp) + ); + } - component.LastStep = !component.LastStep; - component.IsCurrentlyWaddling = true; + private static float CalculateTumbleIntensity(WaddleAnimationComponent component) + { + return component.LastStep ? 360 - component.TumbleIntensity : component.TumbleIntensity; + } + + private static float CalculateAnimationLength(WaddleAnimationComponent component, InputMoverComponent mover) + { + return mover.Sprinting ? component.AnimationLength * component.RunAnimationLengthMultiplier : component.AnimationLength; + } + + private void OnAnimationCompleted(Entity entity, ref AnimationCompletedEvent args) + { + if (args.Key != entity.Comp.KeyName) + return; + + if (!TryComp(entity.Owner, out var mover)) + return; + + PlayWaddleAnimationUsing( + (entity.Owner, entity.Comp), + CalculateAnimationLength(entity.Comp, mover), + CalculateTumbleIntensity(entity.Comp) + ); + } + + private void StopWaddling(Entity entity) + { + if (!_animation.HasRunningAnimation(entity.Owner, entity.Comp.KeyName)) + return; + + _animation.Stop(entity.Owner, entity.Comp.KeyName); + + if (!TryComp(entity.Owner, out var sprite)) + return; + + sprite.Offset = new Vector2(); + sprite.Rotation = Angle.FromDegrees(0); + } + + private void PlayWaddleAnimationUsing(Entity entity, float len, float tumbleIntensity) + { + entity.Comp.LastStep = !entity.Comp.LastStep; var anim = new Animation() { @@ -116,58 +137,13 @@ public sealed class WaddleAnimationSystem : EntitySystem KeyFrames = { new AnimationTrackProperty.KeyFrame(new Vector2(), 0), - new AnimationTrackProperty.KeyFrame(component.HopIntensity, len/2), + new AnimationTrackProperty.KeyFrame(entity.Comp.HopIntensity, len/2), new AnimationTrackProperty.KeyFrame(new Vector2(), len/2), } } } }; - _animation.Play(uid, anim, component.KeyName); - } - - private void OnStoppedWalking(EntityUid uid, WaddleAnimationComponent component, StoppedWaddlingEvent args) - { - StopWaddling(uid, component); - } - - private void OnAnimationCompleted(EntityUid uid, WaddleAnimationComponent component, AnimationCompletedEvent args) - { - var started = new StartedWaddlingEvent(uid); - - RaiseLocalEvent(uid, ref started); - } - - private void OnStunned(EntityUid uid, WaddleAnimationComponent component, StunnedEvent args) - { - StopWaddling(uid, component); - } - - private void OnKnockedDown(EntityUid uid, WaddleAnimationComponent component, KnockedDownEvent args) - { - StopWaddling(uid, component); - } - - private void OnBuckleChange(EntityUid uid, WaddleAnimationComponent component, BuckleChangeEvent args) - { - StopWaddling(uid, component); - } - - private void StopWaddling(EntityUid uid, WaddleAnimationComponent component) - { - if (!component.IsCurrentlyWaddling) - return; - - _animation.Stop(uid, component.KeyName); - - if (!TryComp(uid, out var sprite)) - { - return; - } - - sprite.Offset = new Vector2(); - sprite.Rotation = Angle.FromDegrees(0); - - component.IsCurrentlyWaddling = false; + _animation.Play(entity.Owner, anim, entity.Comp.KeyName); } } diff --git a/Content.Server/Movement/Systems/WaddleAnimationSystem.cs b/Content.Server/Movement/Systems/WaddleAnimationSystem.cs new file mode 100644 index 0000000000..e6083210e1 --- /dev/null +++ b/Content.Server/Movement/Systems/WaddleAnimationSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared.Movement.Systems; + +namespace Content.Server.Movement.Systems; + +public sealed class WaddleAnimationSystem : SharedWaddleAnimationSystem; diff --git a/Content.Shared/Clothing/Components/WaddleWhenWornComponent.cs b/Content.Shared/Clothing/Components/WaddleWhenWornComponent.cs index 5cd7a72457..fb7490ef4f 100644 --- a/Content.Shared/Clothing/Components/WaddleWhenWornComponent.cs +++ b/Content.Shared/Clothing/Components/WaddleWhenWornComponent.cs @@ -1,35 +1,36 @@ using System.Numerics; +using Robust.Shared.GameStates; namespace Content.Shared.Clothing.Components; /// /// Defines something as causing waddling when worn. /// -[RegisterComponent] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class WaddleWhenWornComponent : Component { /// /// How high should they hop during the waddle? Higher hop = more energy. /// - [DataField] + [DataField, AutoNetworkedField] public Vector2 HopIntensity = new(0, 0.25f); /// /// How far should they rock backward and forward during the waddle? /// Each step will alternate between this being a positive and negative rotation. More rock = more scary. /// - [DataField] + [DataField, AutoNetworkedField] public float TumbleIntensity = 20.0f; /// /// How long should a complete step take? Less time = more chaos. /// - [DataField] + [DataField, AutoNetworkedField] public float AnimationLength = 0.66f; /// /// How much shorter should the animation be when running? /// - [DataField] + [DataField, AutoNetworkedField] public float RunAnimationLengthMultiplier = 0.568f; } diff --git a/Content.Client/Clothing/Systems/WaddleClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/WaddleClothingSystem.cs similarity index 59% rename from Content.Client/Clothing/Systems/WaddleClothingSystem.cs rename to Content.Shared/Clothing/EntitySystems/WaddleClothingSystem.cs index b8ac3c207b..b445eb258e 100644 --- a/Content.Client/Clothing/Systems/WaddleClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/WaddleClothingSystem.cs @@ -1,8 +1,9 @@ -using Content.Shared.Clothing.Components; +using Content.Shared.Clothing; +using Content.Shared.Clothing.Components; using Content.Shared.Movement.Components; using Content.Shared.Inventory.Events; -namespace Content.Client.Clothing.Systems; +namespace Content.Shared.Clothing.EntitySystems; public sealed class WaddleClothingSystem : EntitySystem { @@ -10,13 +11,13 @@ public sealed class WaddleClothingSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnGotEquipped); - SubscribeLocalEvent(OnGotUnequipped); + SubscribeLocalEvent(OnGotEquipped); + SubscribeLocalEvent(OnGotUnequipped); } - private void OnGotEquipped(EntityUid entity, WaddleWhenWornComponent comp, GotEquippedEvent args) + private void OnGotEquipped(EntityUid entity, WaddleWhenWornComponent comp, ClothingGotEquippedEvent args) { - var waddleAnimComp = EnsureComp(args.Equipee); + var waddleAnimComp = EnsureComp(args.Wearer); waddleAnimComp.AnimationLength = comp.AnimationLength; waddleAnimComp.HopIntensity = comp.HopIntensity; @@ -24,8 +25,8 @@ public sealed class WaddleClothingSystem : EntitySystem waddleAnimComp.TumbleIntensity = comp.TumbleIntensity; } - private void OnGotUnequipped(EntityUid entity, WaddleWhenWornComponent comp, GotUnequippedEvent args) + private void OnGotUnequipped(EntityUid entity, WaddleWhenWornComponent comp, ClothingGotUnequippedEvent args) { - RemComp(args.Equipee); + RemComp(args.Wearer); } } diff --git a/Content.Shared/Movement/Components/WaddleAnimationComponent.cs b/Content.Shared/Movement/Components/WaddleAnimationComponent.cs index c43ef3042e..3cd9a3749e 100644 --- a/Content.Shared/Movement/Components/WaddleAnimationComponent.cs +++ b/Content.Shared/Movement/Components/WaddleAnimationComponent.cs @@ -1,31 +1,32 @@ using System.Numerics; +using Robust.Shared.Serialization; namespace Content.Shared.Movement.Components; /// /// Declares that an entity has started to waddle like a duck/clown. /// -/// The newly be-waddled. -[ByRefEvent] -public record struct StartedWaddlingEvent(EntityUid Entity) +/// The newly be-waddled. +[Serializable, NetSerializable] +public sealed class StartedWaddlingEvent(NetEntity entity) : EntityEventArgs { - public EntityUid Entity = Entity; + public NetEntity Entity = entity; } /// /// Declares that an entity has stopped waddling like a duck/clown. /// -/// The former waddle-er. -[ByRefEvent] -public record struct StoppedWaddlingEvent(EntityUid Entity) +/// The former waddle-er. +[Serializable, NetSerializable] +public sealed class StoppedWaddlingEvent(NetEntity entity) : EntityEventArgs { - public EntityUid Entity = Entity; + public NetEntity Entity = entity; } /// /// Defines something as having a waddle animation when it moves. /// -[RegisterComponent] +[RegisterComponent, AutoGenerateComponentState] public sealed partial class WaddleAnimationComponent : Component { /// @@ -38,26 +39,26 @@ public sealed partial class WaddleAnimationComponent : Component /// /// How high should they hop during the waddle? Higher hop = more energy. /// - [DataField] + [DataField, AutoNetworkedField] public Vector2 HopIntensity = new(0, 0.25f); /// /// How far should they rock backward and forward during the waddle? /// Each step will alternate between this being a positive and negative rotation. More rock = more scary. /// - [DataField] + [DataField, AutoNetworkedField] public float TumbleIntensity = 20.0f; /// /// How long should a complete step take? Less time = more chaos. /// - [DataField] + [DataField, AutoNetworkedField] public float AnimationLength = 0.66f; /// /// How much shorter should the animation be when running? /// - [DataField] + [DataField, AutoNetworkedField] public float RunAnimationLengthMultiplier = 0.568f; /// @@ -68,5 +69,6 @@ public sealed partial class WaddleAnimationComponent : Component /// /// Stores if we're currently waddling so we can start/stop as appropriate and can tell other systems our state. /// + [AutoNetworkedField] public bool IsCurrentlyWaddling; } diff --git a/Content.Shared/Movement/Systems/SharedWaddleAnimationSystem.cs b/Content.Shared/Movement/Systems/SharedWaddleAnimationSystem.cs new file mode 100644 index 0000000000..2fcb4fc60b --- /dev/null +++ b/Content.Shared/Movement/Systems/SharedWaddleAnimationSystem.cs @@ -0,0 +1,106 @@ +using Content.Shared.Buckle.Components; +using Content.Shared.Gravity; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Events; +using Content.Shared.Movement.Systems; +using Content.Shared.Standing; +using Content.Shared.Stunnable; +using Robust.Shared.Timing; + +namespace Content.Shared.Movement.Systems; + +public abstract class SharedWaddleAnimationSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + // Startup + SubscribeLocalEvent(OnComponentStartup); + + // Start moving possibilities + SubscribeLocalEvent(OnMovementInput); + SubscribeLocalEvent(OnStood); + + // Stop moving possibilities + SubscribeLocalEvent((Entity ent, ref StunnedEvent _) => StopWaddling(ent)); + SubscribeLocalEvent((Entity ent, ref DownedEvent _) => StopWaddling(ent)); + SubscribeLocalEvent((Entity ent, ref BuckleChangeEvent _) => StopWaddling(ent)); + SubscribeLocalEvent(OnGravityChanged); + } + + private void OnGravityChanged(Entity ent, ref GravityChangedEvent args) + { + if (!args.HasGravity && ent.Comp.IsCurrentlyWaddling) + StopWaddling(ent); + } + + private void OnComponentStartup(Entity entity, ref ComponentStartup args) + { + if (!TryComp(entity.Owner, out var moverComponent)) + return; + + // If the waddler is currently moving, make them start waddling + if ((moverComponent.HeldMoveButtons & MoveButtons.AnyDirection) == MoveButtons.AnyDirection) + { + RaiseNetworkEvent(new StartedWaddlingEvent(GetNetEntity(entity.Owner))); + } + } + + private void OnMovementInput(Entity entity, ref MoveInputEvent args) + { + // Prediction mitigation. Prediction means that MoveInputEvents are spammed repeatedly, even though you'd assume + // they're once-only for the user actually doing something. As such do nothing if we're just repeating this FoR. + if (!_timing.IsFirstTimePredicted) + { + return; + } + + if (!args.HasDirectionalMovement && entity.Comp.IsCurrentlyWaddling) + { + StopWaddling(entity); + + return; + } + + // Only start waddling if we're not currently AND we're actually moving. + if (entity.Comp.IsCurrentlyWaddling || !args.HasDirectionalMovement) + return; + + entity.Comp.IsCurrentlyWaddling = true; + + RaiseNetworkEvent(new StartedWaddlingEvent(GetNetEntity(entity.Owner))); + } + + private void OnStood(Entity entity, ref StoodEvent args) + { + // Prediction mitigation. Prediction means that MoveInputEvents are spammed repeatedly, even though you'd assume + // they're once-only for the user actually doing something. As such do nothing if we're just repeating this FoR. + if (!_timing.IsFirstTimePredicted) + { + return; + } + + if (!TryComp(entity.Owner, out var mover)) + { + return; + } + + if ((mover.HeldMoveButtons & MoveButtons.AnyDirection) == MoveButtons.None) + return; + + if (entity.Comp.IsCurrentlyWaddling) + return; + + entity.Comp.IsCurrentlyWaddling = true; + + RaiseNetworkEvent(new StartedWaddlingEvent(GetNetEntity(entity.Owner))); + } + + private void StopWaddling(Entity entity) + { + entity.Comp.IsCurrentlyWaddling = false; + + RaiseNetworkEvent(new StoppedWaddlingEvent(GetNetEntity(entity.Owner))); + } +} From 0b4fc7e298bc37cc7db053bf4d2c2adb7e873d0a Mon Sep 17 00:00:00 2001 From: Hannah Giovanna Dawson Date: Tue, 4 Jun 2024 14:26:19 +0100 Subject: [PATCH 61/63] Make projectile & hitscan reflection only try once with the best reflector (#28539) --- .../Weapons/Reflect/ReflectSystem.cs | 258 ++++++++++-------- .../Weapons/Reflect/ReflectUserComponent.cs | 5 +- 2 files changed, 147 insertions(+), 116 deletions(-) diff --git a/Content.Shared/Weapons/Reflect/ReflectSystem.cs b/Content.Shared/Weapons/Reflect/ReflectSystem.cs index 03ad97edff..9b89be6202 100644 --- a/Content.Shared/Weapons/Reflect/ReflectSystem.cs +++ b/Content.Shared/Weapons/Reflect/ReflectSystem.cs @@ -49,73 +49,123 @@ public sealed class ReflectSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnReflectCollide); - SubscribeLocalEvent(OnReflectHitscan); + SubscribeLocalEvent(OnObjectReflectProjectileAttempt); + SubscribeLocalEvent(OnObjectReflectHitscanAttempt); SubscribeLocalEvent(OnReflectEquipped); SubscribeLocalEvent(OnReflectUnequipped); SubscribeLocalEvent(OnReflectHandEquipped); SubscribeLocalEvent(OnReflectHandUnequipped); SubscribeLocalEvent(OnToggleReflect); - SubscribeLocalEvent(OnReflectUserCollide); - SubscribeLocalEvent(OnReflectUserHitscan); + SubscribeLocalEvent(OnUserProjectileReflectAttempt); + SubscribeLocalEvent(OnUserHitscanReflectAttempt); } - private void OnReflectUserHitscan(EntityUid uid, ReflectUserComponent component, ref HitScanReflectAttemptEvent args) + private void OnUserHitscanReflectAttempt(Entity user, ref HitScanReflectAttemptEvent args) { if (args.Reflected) return; - foreach (var ent in _inventorySystem.GetHandOrInventoryEntities(uid, SlotFlags.WITHOUT_POCKET)) - { - if (!TryReflectHitscan(uid, ent, args.Shooter, args.SourceItem, args.Direction, out var dir)) - continue; + if (!UserCanReflect(user, out var bestReflectorUid)) + return; - args.Direction = dir.Value; - args.Reflected = true; - break; - } + if (!TryReflectHitscan(user.Owner, bestReflectorUid.Value, args.Shooter, args.SourceItem, args.Direction, out var dir)) + return; + + args.Direction = dir.Value; + args.Reflected = true; } - private void OnReflectUserCollide(EntityUid uid, ReflectUserComponent component, ref ProjectileReflectAttemptEvent args) - { - foreach (var ent in _inventorySystem.GetHandOrInventoryEntities(uid, SlotFlags.WITHOUT_POCKET)) - { - if (!TryReflectProjectile(uid, ent, args.ProjUid)) - continue; - - args.Cancelled = true; - break; - } - } - - private void OnReflectCollide(EntityUid uid, ReflectComponent component, ref ProjectileReflectAttemptEvent args) + private void OnUserProjectileReflectAttempt(Entity user, ref ProjectileReflectAttemptEvent args) { if (args.Cancelled) return; - if (TryReflectProjectile(uid, uid, args.ProjUid, reflect: component)) - args.Cancelled = true; + if (!TryComp(args.ProjUid, out var reflectiveComponent)) + return; + + if (!UserCanReflect(user, out var bestReflectorUid, (args.ProjUid, reflectiveComponent))) + return; + + if (!TryReflectProjectile(user, bestReflectorUid.Value, (args.ProjUid, args.Component))) + return; + + args.Cancelled = true; } - private bool TryReflectProjectile(EntityUid user, EntityUid reflector, EntityUid projectile, ProjectileComponent? projectileComp = null, ReflectComponent? reflect = null) + private void OnObjectReflectHitscanAttempt(Entity obj, ref HitScanReflectAttemptEvent args) + { + if (args.Reflected || (obj.Comp.Reflects & args.Reflective) == 0x0) + return; + + if (!TryReflectHitscan(obj, obj, args.Shooter, args.SourceItem, args.Direction, out var dir)) + return; + + args.Direction = dir.Value; + args.Reflected = true; + } + + private void OnObjectReflectProjectileAttempt(Entity obj, ref ProjectileReflectAttemptEvent args) + { + if (args.Cancelled) + return; + + if (!TryReflectProjectile(obj, obj, (args.ProjUid, args.Component))) + return; + + args.Cancelled = true; + } + + /// + /// Can a user reflect something that's hit them? Returns true if so, and the best reflector available in the user's equipment. + /// + private bool UserCanReflect(Entity user, [NotNullWhen(true)] out Entity? bestReflector, Entity? projectile = null) + { + bestReflector = null; + + foreach (var entityUid in _inventorySystem.GetHandOrInventoryEntities(user.Owner, SlotFlags.WITHOUT_POCKET)) + { + if (!TryComp(entityUid, out var comp)) + continue; + + if (!comp.Enabled) + continue; + + if (bestReflector != null && bestReflector.Value.Comp.ReflectProb >= comp.ReflectProb) + continue; + + if (projectile != null && (comp.Reflects & projectile.Value.Comp.Reflective) == 0x0) + continue; + + bestReflector = (entityUid, comp); + } + + return bestReflector != null; + } + + private bool TryReflectProjectile(EntityUid user, Entity reflector, Entity projectile) { - // Do we have the components needed to try a reflect at all? if ( - !Resolve(reflector, ref reflect, false) || - !reflect.Enabled || + // Is it on? + !reflector.Comp.Enabled || + // Is the projectile deflectable? !TryComp(projectile, out var reflective) || - (reflect.Reflects & reflective.Reflective) == 0x0 || + // Does the deflector deflect the type of projecitle? + (reflector.Comp.Reflects & reflective.Reflective) == 0x0 || + // Is the projectile correctly set up with physics? !TryComp(projectile, out var physics) || - TryComp(reflector, out var staminaComponent) && staminaComponent.Critical || + // If the user of the reflector is a mob with stamina, is it capable of deflecting? + TryComp(user, out var staminaComponent) && staminaComponent.Critical || _standing.IsDown(reflector) ) return false; - if (!_random.Prob(CalcReflectChance(reflector, reflect))) + // If this dice roll fails, the shot isn't deflected + if (!_random.Prob(GetReflectChance(reflector))) return false; - var rotation = _random.NextAngle(-reflect.Spread / 2, reflect.Spread / 2).Opposite(); + // Below handles what happens after being deflected. + var rotation = _random.NextAngle(-reflector.Comp.Spread / 2, reflector.Comp.Spread / 2).Opposite(); var existingVelocity = _physics.GetMapLinearVelocity(projectile, component: physics); var relativeVelocity = existingVelocity - _physics.GetMapLinearVelocity(user); var newVelocity = rotation.RotateVec(relativeVelocity); @@ -132,98 +182,52 @@ public sealed class ReflectSystem : EntitySystem if (_netManager.IsServer) { _popup.PopupEntity(Loc.GetString("reflect-shot"), user); - _audio.PlayPvs(reflect.SoundOnReflect, user, AudioHelpers.WithVariation(0.05f, _random)); + _audio.PlayPvs(reflector.Comp.SoundOnReflect, user, AudioHelpers.WithVariation(0.05f, _random)); } - if (Resolve(projectile, ref projectileComp, false)) - { - _adminLogger.Add(LogType.BulletHit, LogImpact.Medium, $"{ToPrettyString(user)} reflected {ToPrettyString(projectile)} from {ToPrettyString(projectileComp.Weapon)} shot by {projectileComp.Shooter}"); + _adminLogger.Add(LogType.BulletHit, LogImpact.Medium, $"{ToPrettyString(user)} reflected {ToPrettyString(projectile)} from {ToPrettyString(projectile.Comp.Weapon)} shot by {projectile.Comp.Shooter}"); - projectileComp.Shooter = user; - projectileComp.Weapon = user; - Dirty(projectile, projectileComp); - } - else - { - _adminLogger.Add(LogType.BulletHit, LogImpact.Medium, $"{ToPrettyString(user)} reflected {ToPrettyString(projectile)}"); - } + projectile.Comp.Shooter = user; + projectile.Comp.Weapon = user; + Dirty(projectile); return true; } - private float CalcReflectChance(EntityUid reflector, ReflectComponent reflect) - { - /* - * The rules of deflection are as follows: - * If you innately reflect things via magic, biology etc., you always have a full chance. - * If you are standing up and standing still, you're prepared to deflect and have full chance. - * If you have velocity, your deflection chance depends on your velocity, clamped. - * If you are floating, your chance is the minimum value possible. - * You cannot deflect if you are knocked down or stunned. - */ - - if (reflect.Innate) - return reflect.ReflectProb; - - if (_gravity.IsWeightless(reflector)) - return reflect.MinReflectProb; - - if (!TryComp(reflector, out var reflectorPhysics)) - return reflect.ReflectProb; - - return MathHelper.Lerp( - reflect.MinReflectProb, - reflect.ReflectProb, - // Inverse progression between velocities fed in as progression between probabilities. We go high -> low so the output here needs to be _inverted_. - 1 - Math.Clamp((reflectorPhysics.LinearVelocity.Length() - reflect.VelocityBeforeNotMaxProb) / (reflect.VelocityBeforeMinProb - reflect.VelocityBeforeNotMaxProb), 0, 1) - ); - } - - private void OnReflectHitscan(EntityUid uid, ReflectComponent component, ref HitScanReflectAttemptEvent args) - { - if (args.Reflected || - (component.Reflects & args.Reflective) == 0x0) - { - return; - } - - if (TryReflectHitscan(uid, uid, args.Shooter, args.SourceItem, args.Direction, out var dir)) - { - args.Direction = dir.Value; - args.Reflected = true; - } - } - private bool TryReflectHitscan( EntityUid user, - EntityUid reflector, + Entity reflector, EntityUid? shooter, EntityUid shotSource, Vector2 direction, [NotNullWhen(true)] out Vector2? newDirection) { - if (!TryComp(reflector, out var reflect) || - !reflect.Enabled || - TryComp(reflector, out var staminaComponent) && staminaComponent.Critical || - _standing.IsDown(reflector)) + if ( + // Is the reflector enabled? + !reflector.Comp.Enabled || + // If the user is a mob with stamina, is it capable of deflecting? + TryComp(user, out var staminaComponent) && staminaComponent.Critical || + _standing.IsDown(user)) { newDirection = null; return false; } - if (!_random.Prob(CalcReflectChance(reflector, reflect))) + // If this dice roll fails, the shot is not deflected. + if (!_random.Prob(GetReflectChance(reflector))) { newDirection = null; return false; } + // Below handles what happens after being deflected. if (_netManager.IsServer) { _popup.PopupEntity(Loc.GetString("reflect-shot"), user); - _audio.PlayPvs(reflect.SoundOnReflect, user, AudioHelpers.WithVariation(0.05f, _random)); + _audio.PlayPvs(reflector.Comp.SoundOnReflect, user, AudioHelpers.WithVariation(0.05f, _random)); } - var spread = _random.NextAngle(-reflect.Spread / 2, reflect.Spread / 2); + var spread = _random.NextAngle(-reflector.Comp.Spread / 2, reflector.Comp.Spread / 2); newDirection = -spread.RotateVec(direction); if (shooter != null) @@ -234,51 +238,81 @@ public sealed class ReflectSystem : EntitySystem return true; } - private void OnReflectEquipped(EntityUid uid, ReflectComponent component, GotEquippedEvent args) + private float GetReflectChance(Entity reflector) + { + /* + * The rules of deflection are as follows: + * If you innately reflect things via magic, biology etc., you always have a full chance. + * If you are standing up and standing still, you're prepared to deflect and have full chance. + * If you have velocity, your deflection chance depends on your velocity, clamped. + * If you are floating, your chance is the minimum value possible. + */ + + if (reflector.Comp.Innate) + return reflector.Comp.ReflectProb; + + if (_gravity.IsWeightless(reflector)) + return reflector.Comp.MinReflectProb; + + if (!TryComp(reflector, out var reflectorPhysics)) + return reflector.Comp.ReflectProb; + + return MathHelper.Lerp( + reflector.Comp.MinReflectProb, + reflector.Comp.ReflectProb, + // Inverse progression between velocities fed in as progression between probabilities. We go high -> low so the output here needs to be _inverted_. + 1 - Math.Clamp((reflectorPhysics.LinearVelocity.Length() - reflector.Comp.VelocityBeforeNotMaxProb) / (reflector.Comp.VelocityBeforeMinProb - reflector.Comp.VelocityBeforeNotMaxProb), 0, 1) + ); + } + + private void OnReflectEquipped(Entity reflector, ref GotEquippedEvent args) { if (_gameTiming.ApplyingState) return; EnsureComp(args.Equipee); - if (component.Enabled) + if (reflector.Comp.Enabled) EnableAlert(args.Equipee); } - private void OnReflectUnequipped(EntityUid uid, ReflectComponent comp, GotUnequippedEvent args) + private void OnReflectUnequipped(Entity reflector, ref GotUnequippedEvent args) { RefreshReflectUser(args.Equipee); } - private void OnReflectHandEquipped(EntityUid uid, ReflectComponent component, GotEquippedHandEvent args) + private void OnReflectHandEquipped(Entity reflector, ref GotEquippedHandEvent args) { if (_gameTiming.ApplyingState) return; EnsureComp(args.User); - if (component.Enabled) + if (reflector.Comp.Enabled) EnableAlert(args.User); } - private void OnReflectHandUnequipped(EntityUid uid, ReflectComponent component, GotUnequippedHandEvent args) + private void OnReflectHandUnequipped(Entity reflector, ref GotUnequippedHandEvent args) { RefreshReflectUser(args.User); } - private void OnToggleReflect(EntityUid uid, ReflectComponent comp, ref ItemToggledEvent args) + private void OnToggleReflect(Entity reflector, ref ItemToggledEvent args) { - comp.Enabled = args.Activated; - Dirty(uid, comp); + reflector.Comp.Enabled = args.Activated; + Dirty(reflector); - if (comp.Enabled) - EnableAlert(uid); + if (args.User == null) + return; + + if (reflector.Comp.Enabled) + EnableAlert(args.User.Value); else - DisableAlert(uid); + DisableAlert(args.User.Value); } /// - /// Refreshes whether someone has reflection potential so we can raise directed events on them. + /// Refreshes whether someone has reflection potential, so we can raise directed events on them. /// private void RefreshReflectUser(EntityUid user) { diff --git a/Content.Shared/Weapons/Reflect/ReflectUserComponent.cs b/Content.Shared/Weapons/Reflect/ReflectUserComponent.cs index 44fe60813e..44ef481a37 100644 --- a/Content.Shared/Weapons/Reflect/ReflectUserComponent.cs +++ b/Content.Shared/Weapons/Reflect/ReflectUserComponent.cs @@ -7,7 +7,4 @@ namespace Content.Shared.Weapons.Reflect; /// Reflection events will then be relayed. /// [RegisterComponent, NetworkedComponent] -public sealed partial class ReflectUserComponent : Component -{ - -} +public sealed partial class ReflectUserComponent : Component; From b3cfd9b4ff7b1f06bd917c158058229773b92955 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 4 Jun 2024 13:27:27 +0000 Subject: [PATCH 62/63] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0ae775e193..6a20b3a411 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Dutch-VanDerLinde - changes: - - message: Romerol now properly works on the dead. - type: Tweak - id: 6179 - time: '2024-03-18T06:25:36.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26222 - author: ElectroJr changes: - message: Added an option to try and ignore some errors if a replay fails to load, @@ -3850,3 +3843,11 @@ id: 6678 time: '2024-06-03T18:48:44.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/27788 +- author: FairlySadPanda + changes: + - message: Stacking multiple deflecting items at once has been removed; now only + your best item is used. + type: Tweak + id: 6679 + time: '2024-06-04T13:26:20.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/28539 From d5019cee96a922f7e0547bc507fdfa1ed9471a39 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Tue, 4 Jun 2024 06:54:22 -0800 Subject: [PATCH 63/63] Add CVar to disable pow3r parallel processing (#28488) * Add CVar to disable pow3r parallel processing * Cache CVar value * Fix pointyhat * Move all CVar-ing to Content.Server --- .../Power/EntitySystems/PowerNetSystem.cs | 13 ++++++++++++- Content.Server/Power/Pow3r/BatteryRampPegSolver.cs | 9 +++++++-- Content.Shared/CCVar/CCVars.cs | 6 ++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Content.Server/Power/EntitySystems/PowerNetSystem.cs b/Content.Server/Power/EntitySystems/PowerNetSystem.cs index 7bd057951c..6c35ba2008 100644 --- a/Content.Server/Power/EntitySystems/PowerNetSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerNetSystem.cs @@ -3,9 +3,11 @@ using Content.Server.NodeContainer.EntitySystems; using Content.Server.Power.Components; using Content.Server.Power.NodeGroups; using Content.Server.Power.Pow3r; +using Content.Shared.CCVar; using Content.Shared.Power; using JetBrains.Annotations; using Robust.Server.GameObjects; +using Robust.Shared.Configuration; using Robust.Shared.Threading; namespace Content.Server.Power.EntitySystems @@ -18,6 +20,7 @@ namespace Content.Server.Power.EntitySystems { [Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly PowerNetConnectorSystem _powerNetConnector = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IParallelManager _parMan = default!; [Dependency] private readonly PowerReceiverSystem _powerReceiver = default!; @@ -25,13 +28,14 @@ namespace Content.Server.Power.EntitySystems private readonly HashSet _powerNetReconnectQueue = new(); private readonly HashSet _apcNetReconnectQueue = new(); - private readonly BatteryRampPegSolver _solver = new(); + private BatteryRampPegSolver _solver = new(); public override void Initialize() { base.Initialize(); UpdatesAfter.Add(typeof(NodeGroupSystem)); + _solver = new(_cfg.GetCVar(CCVars.DebugPow3rDisableParallel)); SubscribeLocalEvent(ApcPowerReceiverInit); SubscribeLocalEvent(ApcPowerReceiverShutdown); @@ -53,6 +57,13 @@ namespace Content.Server.Power.EntitySystems SubscribeLocalEvent(PowerSupplierShutdown); SubscribeLocalEvent(PowerSupplierPaused); SubscribeLocalEvent(PowerSupplierUnpaused); + + Subs.CVar(_cfg, CCVars.DebugPow3rDisableParallel, DebugPow3rDisableParallelChanged); + } + + private void DebugPow3rDisableParallelChanged(bool val) + { + _solver = new(val); } private void ApcPowerReceiverInit(EntityUid uid, ApcPowerReceiverComponent component, ComponentInit args) diff --git a/Content.Server/Power/Pow3r/BatteryRampPegSolver.cs b/Content.Server/Power/Pow3r/BatteryRampPegSolver.cs index 12118968b7..599c55b6ba 100644 --- a/Content.Server/Power/Pow3r/BatteryRampPegSolver.cs +++ b/Content.Server/Power/Pow3r/BatteryRampPegSolver.cs @@ -9,9 +9,11 @@ namespace Content.Server.Power.Pow3r public sealed class BatteryRampPegSolver : IPowerSolver { private UpdateNetworkJob _networkJob; + private bool _disableParallel; - public BatteryRampPegSolver() + public BatteryRampPegSolver(bool disableParallel = false) { + _disableParallel = disableParallel; _networkJob = new() { Solver = this, @@ -56,7 +58,10 @@ namespace Content.Server.Power.Pow3r // suppliers + discharger) Then decide based on total layer size whether its worth parallelizing that // layer? _networkJob.Networks = group; - parallel.ProcessNow(_networkJob, group.Count); + if (_disableParallel) + parallel.ProcessSerialNow(_networkJob, group.Count); + else + parallel.ProcessNow(_networkJob, group.Count); } ClearBatteries(state); diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index f41e0a1e6f..b3da71fde1 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -2062,5 +2062,11 @@ namespace Content.Shared.CCVar /// public static readonly CVarDef DebugOptionVisualizerTest = CVarDef.Create("debug.option_visualizer_test", false, CVar.CLIENTONLY); + + /// + /// Set to true to disable parallel processing in the pow3r solver. + /// + public static readonly CVarDef DebugPow3rDisableParallel = + CVarDef.Create("debug.pow3r_disable_parallel", true, CVar.SERVERONLY); } }