From 2b227b5a4e38700c95aee56256da6af284238587 Mon Sep 17 00:00:00 2001 From: RedBookcase Date: Fri, 15 Nov 2024 12:52:19 -0800 Subject: [PATCH 001/218] Edited Snow White reaction to output proper amount of drink. (#33331) Co-authored-by: RedBookcase --- Resources/Prototypes/Recipes/Reactions/drinks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Recipes/Reactions/drinks.yml b/Resources/Prototypes/Recipes/Reactions/drinks.yml index 2353099df56..64668b10895 100644 --- a/Resources/Prototypes/Recipes/Reactions/drinks.yml +++ b/Resources/Prototypes/Recipes/Reactions/drinks.yml @@ -953,7 +953,7 @@ LemonLime: amount: 1 products: - SnowWhite: 3 + SnowWhite: 2 - type: reaction id: SodaWater From f88cd33137c2df0269d2f5c46b23f95581ac2b56 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 15 Nov 2024 20:53:26 +0000 Subject: [PATCH 002/218] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 82896471192..4bf34d35bc4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Erisfiregamer1 - changes: - - message: New chemical, Sedin. It restores seeds on plants 20% of the time with - other adverse effects included. - type: Add - id: 7111 - time: '2024-08-15T00:38:24.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27110 - author: PoorMansDreams changes: - message: Added Star sticker in loadouts for Secoffs @@ -3913,3 +3905,10 @@ id: 7610 time: '2024-11-15T06:54:53.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33315 +- author: RedBookcase + changes: + - message: Mixing up a Snow White no longer creates extra liquid out of thin air. + type: Fix + id: 7611 + time: '2024-11-15T20:52:19.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33331 From 22984f6adfb3b6d3728f0b5d080b7392264f241d Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:21:08 +0100 Subject: [PATCH 003/218] Add succumb action 10 sec delay (#32985) * Add succumb action 10 sec delay * add somthing * add delay to last words as well --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Prototypes/Actions/crit.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/Prototypes/Actions/crit.yml b/Resources/Prototypes/Actions/crit.yml index c5712844bf4..aaad27d2b7d 100644 --- a/Resources/Prototypes/Actions/crit.yml +++ b/Resources/Prototypes/Actions/crit.yml @@ -12,6 +12,8 @@ sprite: Mobs/Ghosts/ghost_human.rsi state: icon event: !type:CritSuccumbEvent + startDelay: true + useDelay: 10 - type: entity id: ActionCritFakeDeath @@ -41,3 +43,5 @@ sprite: Interface/Actions/actions_crit.rsi state: lastwords event: !type:CritLastWordsEvent + startDelay: true + useDelay: 10 From 86edb198b40fdd608603b90e30f7b483e100e2c4 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 15 Nov 2024 21:22:14 +0000 Subject: [PATCH 004/218] 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 4bf34d35bc4..6955fb76968 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: PoorMansDreams - changes: - - message: Added Star sticker in loadouts for Secoffs - type: Add - id: 7112 - time: '2024-08-15T01:50:55.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29767 - author: FATFSAAM2 changes: - message: added 7 new figurine voice lines. @@ -3912,3 +3905,10 @@ id: 7611 time: '2024-11-15T20:52:19.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33331 +- author: lzk228 + changes: + - message: Added 10 seconds delay to Succumb action + type: Add + id: 7612 + time: '2024-11-15T21:21:08.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32985 From 05fe5b701f138bfd1bcd1351c47a668310055e52 Mon Sep 17 00:00:00 2001 From: SpaceRox1244 <138547931+SpaceRox1244@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:48:28 -0500 Subject: [PATCH 005/218] Adds gorilla gauntlet storage sprite and updates hit sound (#33167) * Adds storage sprite for gorilla gauntlet * Specifies a heavier hitsound for gorilla gauntlet * Modifies gauntlet icon and storage sprite * Updates credit to my new username --- .../Objects/Specific/Research/anomaly.yml | 5 +++++ .../Objects/Weapons/Melee/gorilla.rsi/icon.png | Bin 753 -> 775 bytes .../Objects/Weapons/Melee/gorilla.rsi/meta.json | 7 +++++-- .../Weapons/Melee/gorilla.rsi/storage.png | Bin 0 -> 624 bytes 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/storage.png diff --git a/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml b/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml index ff53218e222..6525cb44cfd 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml @@ -125,6 +125,9 @@ state: icon - type: Item size: Large + storedSprite: + state: storage + sprite: Objects/Weapons/Melee/gorilla.rsi - type: MeleeWeapon attackRate: 0.5 angle: 0 @@ -133,6 +136,8 @@ damage: types: Blunt: 20 + soundHit: + path: "/Audio/Weapons/Guns/Gunshots/kinetic_accel.ogg" - type: CorePoweredThrower - type: MeleeThrowOnHit unanchorOnHit: true diff --git a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/icon.png b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/icon.png index a57ce53cc4633590e7be46bbe293c5bd7cace1f4..9ce8603d2a68d0c78a8f09a9f95844ea5ca986b7 100644 GIT binary patch delta 752 zcmV3vclDCr!X4)Ld}VS9q4K56`pgeC<}|o zk!ZGGSy%+f_Nh5humg_`ZwQsupwsDyeGM^7h=vQbT%QSp4Ll1Dz^WRj=p1-AKE>=z zh=#^m%;qYrHh&8MFFspote#U{U$6rf%OULcx7Un*EB$-U5k0Tbt;jpvubDa-FxIKDn$0W?#0iWA1mh01P zgW&)GwRKLW-oFLF;jj}9M_7n15sSrCVFlEEq-U|#9_2rJ>}*5DJc;c zjTR!|d6LOgmi$TJu4*yLxf1%^ezELMx38>i0Pygj9<5dnKs>G>%LzsU0f3yya~9z3 z=oB|gD*<@rs!NNgNE7!b6|`DC@wmeCXRq-MbmvvxRVQywxXjL<9<>2*aXwva`YTJB zoS4p=Tz^$ShCGvOuyyCDJ73asb9{XM#9x!p<#LHfBlk2GOHG%_WTK*?9IaN*_^QH@ z=r>NrQ@mVDFs4k?_25Rquj;l7Jsyu39v;q)ZFVAa-uvz+(qjegJcBKzSdt{+bUN{P zJlRLYH_)w_oR~(I6U5^R0LyOh6DWpzdjT1=wrRF*5iuGFAj^sDb<6dtrw1{9Z_?w8`z>XG5k|dg&n*kUc9AtB1{wwVG81?n_ iX#fH23i%%P0PqW$ha}q5Nokw_0000Px%t4TybR9J=WmETKKVI0Ok{$M6f-a>Sz4B_v)*sMC9P2_D6q%tZMA~d@7dvPo ztg|0EmGyS9&ajy7mvqyft8-r7@AEwG^ZoL^P)8mAI~q=tY=3%SM%W}906ulJEbhiy zMFZZT2zZ0S_#b`PQ7}_ZeRD11(*rZ&-t8Qc%LxQULQkN_;w1DWj~-veCIv;QB&tqe zdSFJ3-26dO+eVMY3+qX38=$aODv7EScquIsX}*ZXVj=Y{!Uhrg?sW5HJqk`3(cD01 zNuHW#;KR}?8-ME&`ue+(Wjmct2LPeXPWn5-CF`qBz~MNL%XOLkgF|HdS!CHxG#bNV zvC!#+7x6bFHm;TAX{tutH#RA5^j-%*wmS%a`AjyupKnJhh1=~S_w$fX#CSIU^u!^o zIDvpSD0X}E-;&e@KzGkARzJQ6!0mPsjmFU8JET&nl7D;^CEy#I6w+Wj!>eI-u3W%u zwqi21(AX%j*&M{8U&&_o3*xWT=Or(rvJC{hK_Lyc1F+d{=l=IBYbG$6TK+Jx_-=`V zgM+ffq0AQe#wNvXFAT4SdF$x`z)yyWGgkcRBxbV}fR*L7vV{$l+C<3o?+r#2mWmS diff --git a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json index 97a5fdbd2e2..55417c2e716 100644 --- a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json @@ -1,14 +1,17 @@ { "version": 1, "license": "CC0-1.0", - "copyright": "Design and inhands by ricemar (discord) and icon by EmoGarbage404 (github)", + "copyright": "Design, inhands, and storage sprite by SpaceRox1244 (github) and icon by EmoGarbage404 (github)", "size": { "x": 32, "y": 32 }, "states": [ { - "name": "icon" + "name": "icon" + }, + { + "name": "storage" }, { "name": "inhand-left", diff --git a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/storage.png b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/storage.png new file mode 100644 index 0000000000000000000000000000000000000000..e21fc82b971ece07b67423bb0e0603cb217392c6 GIT binary patch literal 624 zcmV-$0+0QPP)U0K2E}v08zbeqOF0w zXqu?Co26QN#MN4Bf{jdu;gMm}`doI2EAL)&`}hb@GUA4TR4Qd!AVdXKHUGy>@hJ-H z>uFO=k|f3pV?13n&+WJZLR0`K6PSr5u#!wuTz|j=>YehluXxfUthP=6X$jRU_ZI6%G~Hl4&9h;GVxap0GvH{Sr24~ zn3{AMvAsqb>Dq4tj~?8y0Y4s`U-Mgsuv2O!j_QpMj)jHAf6I6B;@<@Dy8w0o0000< KMNUMnLSTZDXB*xC literal 0 HcmV?d00001 From 8abdafc353458b0410ff99945c7b5680b38c6143 Mon Sep 17 00:00:00 2001 From: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:46:01 -0800 Subject: [PATCH 006/218] Clumsy system refactor (#31147) * First commit * Fixes * Added the noise * Renames * Timespan * Fixed space * entity -> ent * This shouldn't work * opps.... * Datafield name change * Better comments * small comment * Personal skill issue * Event renames and stuff * Couple fixes * Defib ref fixes (Silly me) * Added clumsy back! * no hard code clumsy! * Identity fix * Event name change * Comment change * Function name change * opp * Update names * Damage stuff! * Fixes! * Fixes * opps * This was hidden away!! * negative diff feeds me --- .../Systems/AdminVerbSystem.Smites.cs | 1 + .../Administration/Systems/SuperBonkSystem.cs | 22 +-- .../EntitySystems/HypospraySystem.cs | 41 ++++- Content.Server/Cluwne/CluwneSystem.cs | 1 + Content.Server/Medical/DefibrillatorSystem.cs | 70 +++++++-- .../Weapons/Ranged/Systems/GunSystem.cs | 30 +--- .../Components/HyposprayComponent.cs | 5 - .../Chemistry/Events/HyposprayEvents.cs | 38 +++++ .../Climbing/Components/BonkableComponent.cs | 34 +--- .../Climbing/Events/BeforeClimbEvents.cs | 36 +++++ Content.Shared/Climbing/Systems/BonkSystem.cs | 130 ---------------- .../Climbing/Systems/ClimbSystem.cs | 12 ++ Content.Shared/Clumsy/ClumsyComponent.cs | 61 ++++++++ Content.Shared/Clumsy/ClumsySystem.cs | 146 ++++++++++++++++++ .../Interaction/Components/ClumsyComponent.cs | 24 --- .../SharedInteractionSystem.Clumsy.cs | 26 ---- .../Inventory/InventorySystem.Relay.cs | 9 +- Content.Shared/Medical/DefibrillatorEvents.cs | 39 +++++ .../Medical/TargetDefibrillatedEvent.cs | 4 - .../Ranged/Events/BeforeGunShootEvent.cs | 20 +++ .../bonk/components/bonkable-component.ftl | 6 +- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 4 +- .../Entities/Mobs/Player/guardian.yml | 2 +- .../Furniture/Tables/base_structuretables.yml | 2 - .../Prototypes/Roles/Jobs/Civilian/clown.yml | 2 +- 25 files changed, 484 insertions(+), 281 deletions(-) create mode 100644 Content.Shared/Chemistry/Events/HyposprayEvents.cs create mode 100644 Content.Shared/Climbing/Events/BeforeClimbEvents.cs delete mode 100644 Content.Shared/Climbing/Systems/BonkSystem.cs create mode 100644 Content.Shared/Clumsy/ClumsyComponent.cs create mode 100644 Content.Shared/Clumsy/ClumsySystem.cs delete mode 100644 Content.Shared/Interaction/Components/ClumsyComponent.cs delete mode 100644 Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs create mode 100644 Content.Shared/Medical/DefibrillatorEvents.cs delete mode 100644 Content.Shared/Medical/TargetDefibrillatedEvent.cs create mode 100644 Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index d57898d9d98..5e002198056 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -23,6 +23,7 @@ using Content.Shared.Administration.Components; using Content.Shared.Body.Components; using Content.Shared.Body.Part; +using Content.Shared.Clumsy; using Content.Shared.Clothing.Components; using Content.Shared.Cluwne; using Content.Shared.Damage; diff --git a/Content.Server/Administration/Systems/SuperBonkSystem.cs b/Content.Server/Administration/Systems/SuperBonkSystem.cs index 5488a8d6f46..5cd62d83572 100644 --- a/Content.Server/Administration/Systems/SuperBonkSystem.cs +++ b/Content.Server/Administration/Systems/SuperBonkSystem.cs @@ -1,27 +1,27 @@ using Content.Server.Administration.Components; using Content.Shared.Climbing.Components; -using Content.Shared.Climbing.Events; -using Content.Shared.Climbing.Systems; -using Content.Shared.Interaction.Components; +using Content.Shared.Clumsy; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; +using Robust.Shared.Audio.Systems; namespace Content.Server.Administration.Systems; -public sealed class SuperBonkSystem: EntitySystem +public sealed class SuperBonkSystem : EntitySystem { [Dependency] private readonly SharedTransformSystem _transformSystem = default!; - [Dependency] private readonly BonkSystem _bonkSystem = default!; + [Dependency] private readonly ClumsySystem _clumsySystem = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnBonkShutdown); SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnBonkShutdown); } - public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDead = false ) + public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDead = false) { //The other check in the code to stop when the target dies does not work if the target is already dead. @@ -31,7 +31,6 @@ public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDe return; } - var hadClumsy = EnsureComp(target, out _); var tables = EntityQueryEnumerator(); @@ -79,16 +78,17 @@ public override void Update(float frameTime) private void Bonk(SuperBonkComponent comp) { var uid = comp.Tables.Current.Key; - var bonkComp = comp.Tables.Current.Value; // It would be very weird for something without a transform component to have a bonk component // but just in case because I don't want to crash the server. - if (!HasComp(uid)) + if (!HasComp(uid) || !TryComp(comp.Target, out var clumsyComp)) return; _transformSystem.SetCoordinates(comp.Target, Transform(uid).Coordinates); - _bonkSystem.TryBonk(comp.Target, uid, bonkComp); + _clumsySystem.HitHeadClumsy((comp.Target, clumsyComp), uid); + + _audioSystem.PlayPvs(clumsyComp.TableBonkSound, comp.Target); } private void OnMobStateChanged(EntityUid uid, SuperBonkComponent comp, MobStateChangedEvent args) diff --git a/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs index 9b78e81aa00..8345aa3c3dd 100644 --- a/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs +++ b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.Hypospray.Events; using Content.Shared.Chemistry; using Content.Shared.Database; using Content.Shared.FixedPoint; @@ -85,14 +86,44 @@ public bool TryDoInject(Entity entity, EntityUid target, Ent string? msgFormat = null; - if (target == user) - msgFormat = "hypospray-component-inject-self-message"; - else if (EligibleEntity(user, EntityManager, component) && _interaction.TryRollClumsy(user, component.ClumsyFailChance)) + // Self event + var selfEvent = new SelfBeforeHyposprayInjectsEvent(user, entity.Owner, target); + RaiseLocalEvent(user, selfEvent); + + if (selfEvent.Cancelled) + { + _popup.PopupEntity(Loc.GetString(selfEvent.InjectMessageOverride ?? "hypospray-cant-inject", ("owner", Identity.Entity(target, EntityManager))), target, user); + return false; + } + + target = selfEvent.TargetGettingInjected; + + if (!EligibleEntity(target, EntityManager, component)) + return false; + + // Target event + var targetEvent = new TargetBeforeHyposprayInjectsEvent(user, entity.Owner, target); + RaiseLocalEvent(target, targetEvent); + + if (targetEvent.Cancelled) { - msgFormat = "hypospray-component-inject-self-clumsy-message"; - target = user; + _popup.PopupEntity(Loc.GetString(targetEvent.InjectMessageOverride ?? "hypospray-cant-inject", ("owner", Identity.Entity(target, EntityManager))), target, user); + return false; } + target = targetEvent.TargetGettingInjected; + + if (!EligibleEntity(target, EntityManager, component)) + return false; + + // The target event gets priority for the overriden message. + if (targetEvent.InjectMessageOverride != null) + msgFormat = targetEvent.InjectMessageOverride; + else if (selfEvent.InjectMessageOverride != null) + msgFormat = selfEvent.InjectMessageOverride; + else if (target == user) + msgFormat = "hypospray-component-inject-self-message"; + if (!_solutionContainers.TryGetSolution(uid, component.SolutionName, out var hypoSpraySoln, out var hypoSpraySolution) || hypoSpraySolution.Volume == 0) { _popup.PopupEntity(Loc.GetString("hypospray-component-empty-message"), target, user); diff --git a/Content.Server/Cluwne/CluwneSystem.cs b/Content.Server/Cluwne/CluwneSystem.cs index f24f0143f31..1fbb0c72690 100644 --- a/Content.Server/Cluwne/CluwneSystem.cs +++ b/Content.Server/Cluwne/CluwneSystem.cs @@ -16,6 +16,7 @@ using Content.Shared.Interaction.Components; using Robust.Shared.Audio.Systems; using Content.Shared.NameModifier.EntitySystems; +using Content.Shared.Clumsy; namespace Content.Server.Cluwne; diff --git a/Content.Server/Medical/DefibrillatorSystem.cs b/Content.Server/Medical/DefibrillatorSystem.cs index c9cb6cc58dc..fa0ea26385d 100644 --- a/Content.Server/Medical/DefibrillatorSystem.cs +++ b/Content.Server/Medical/DefibrillatorSystem.cs @@ -77,7 +77,20 @@ private void OnDoAfter(EntityUid uid, DefibrillatorComponent component, Defibril Zap(uid, target, args.User, component); } - public bool CanZap(EntityUid uid, EntityUid target, EntityUid? user = null, DefibrillatorComponent? component = null) + /// + /// Checks if you can actually defib a target. + /// + /// Uid of the defib + /// Uid of the target getting defibbed + /// Uid of the entity using the defibrillator + /// Defib component + /// + /// If true, the target can be alive. If false, the function will check if the target is alive and will return false if they are. + /// + /// + /// Returns true if the target is valid to be defibed, false otherwise. + /// + public bool CanZap(EntityUid uid, EntityUid target, EntityUid? user = null, DefibrillatorComponent? component = null, bool targetCanBeAlive = false) { if (!Resolve(uid, ref component)) return false; @@ -98,15 +111,25 @@ public bool CanZap(EntityUid uid, EntityUid target, EntityUid? user = null, Defi if (!_powerCell.HasActivatableCharge(uid, user: user)) return false; - if (_mobState.IsAlive(target, mobState)) + if (!targetCanBeAlive && _mobState.IsAlive(target, mobState)) return false; - if (!component.CanDefibCrit && _mobState.IsCritical(target, mobState)) + if (!targetCanBeAlive && !component.CanDefibCrit && _mobState.IsCritical(target, mobState)) return false; return true; } + /// + /// Tries to start defibrillating the target. If the target is valid, will start the defib do-after. + /// + /// Uid of the defib + /// Uid of the target getting defibbed + /// Uid of the entity using the defibrillator + /// Defib component + /// + /// Returns true if the defibrillation do-after started, otherwise false. + /// public bool TryStartZap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorComponent? component = null) { if (!Resolve(uid, ref component)) @@ -118,25 +141,42 @@ public bool TryStartZap(EntityUid uid, EntityUid target, EntityUid user, Defibri _audio.PlayPvs(component.ChargeSound, uid); return _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.DoAfterDuration, new DefibrillatorZapDoAfterEvent(), uid, target, uid) - { - NeedHand = true, - BreakOnMove = !component.AllowDoAfterMovement - }); + { + NeedHand = true, + BreakOnMove = !component.AllowDoAfterMovement + }); } - public void Zap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorComponent? component = null, MobStateComponent? mob = null, MobThresholdsComponent? thresholds = null) + /// + /// Tries to defibrillate the target with the given defibrillator. + /// + public void Zap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorComponent? component = null) { - if (!Resolve(uid, ref component) || !Resolve(target, ref mob, ref thresholds, false)) + if (!Resolve(uid, ref component)) return; - // clowns zap themselves - if (HasComp(user) && user != target) - { - Zap(uid, user, user, component); + if (!_powerCell.TryUseActivatableCharge(uid, user: user)) return; - } - if (!_powerCell.TryUseActivatableCharge(uid, user: user)) + var selfEvent = new SelfBeforeDefibrillatorZapsEvent(user, uid, target); + RaiseLocalEvent(user, selfEvent); + + target = selfEvent.DefibTarget; + + // Ensure thet new target is still valid. + if (selfEvent.Cancelled || !CanZap(uid, target, user, component, true)) + return; + + var targetEvent = new TargetBeforeDefibrillatorZapsEvent(user, uid, target); + RaiseLocalEvent(target, targetEvent); + + target = targetEvent.DefibTarget; + + if (targetEvent.Cancelled || !CanZap(uid, target, user, component, true)) + return; + + if (!TryComp(target, out var mob) || + !TryComp(target, out var thresholds)) return; _audio.PlayPvs(component.ZapSound, uid); diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index 29504d5a76d..03e529c4398 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -1,15 +1,12 @@ using System.Linq; using System.Numerics; using Content.Server.Cargo.Systems; -using Content.Server.Interaction; using Content.Server.Power.EntitySystems; -using Content.Server.Stunnable; using Content.Server.Weapons.Ranged.Components; using Content.Shared.Damage; using Content.Shared.Damage.Systems; using Content.Shared.Database; using Content.Shared.Effects; -using Content.Shared.Interaction.Components; using Content.Shared.Projectiles; using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Ranged; @@ -36,16 +33,13 @@ public sealed partial class GunSystem : SharedGunSystem [Dependency] private readonly IComponentFactory _factory = default!; [Dependency] private readonly BatterySystem _battery = default!; [Dependency] private readonly DamageExamineSystem _damageExamine = default!; - [Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly PricingSystem _pricing = default!; [Dependency] private readonly SharedColorFlashEffectSystem _color = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly StaminaSystem _stamina = default!; - [Dependency] private readonly StunSystem _stun = default!; [Dependency] private readonly SharedContainerSystem _container = default!; private const float DamagePitchVariation = 0.05f; - public const float GunClumsyChance = 0.5f; public override void Initialize() { @@ -80,26 +74,14 @@ public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid? { userImpulse = true; - // Try a clumsy roll - // TODO: Who put this here - if (TryComp(user, out var clumsy) && gun.ClumsyProof == false) + if (user != null) { - for (var i = 0; i < ammo.Count; i++) + var selfEvent = new SelfBeforeGunShotEvent(user.Value, (gunUid, gun), ammo); + RaiseLocalEvent(user.Value, selfEvent); + if (selfEvent.Cancelled) { - if (_interaction.TryRollClumsy(user.Value, GunClumsyChance, clumsy)) - { - // Wound them - Damageable.TryChangeDamage(user, clumsy.ClumsyDamage, origin: user); - _stun.TryParalyze(user.Value, TimeSpan.FromSeconds(3f), true); - - // Apply salt to the wound ("Honk!") - Audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/bang.ogg"), gunUid); - Audio.PlayPvs(clumsy.ClumsySound, gunUid); - - PopupSystem.PopupEntity(Loc.GetString("gun-clumsy"), user.Value); - userImpulse = false; - return; - } + userImpulse = false; + return; } } diff --git a/Content.Shared/Chemistry/Components/HyposprayComponent.cs b/Content.Shared/Chemistry/Components/HyposprayComponent.cs index 05ef84bbaf7..17d52f0ad93 100644 --- a/Content.Shared/Chemistry/Components/HyposprayComponent.cs +++ b/Content.Shared/Chemistry/Components/HyposprayComponent.cs @@ -11,11 +11,6 @@ public sealed partial class HyposprayComponent : Component [DataField] public string SolutionName = "hypospray"; - // TODO: This should be on clumsycomponent. - [DataField] - [ViewVariables(VVAccess.ReadWrite)] - public float ClumsyFailChance = 0.5f; - [DataField] [ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 TransferAmount = FixedPoint2.New(5); diff --git a/Content.Shared/Chemistry/Events/HyposprayEvents.cs b/Content.Shared/Chemistry/Events/HyposprayEvents.cs new file mode 100644 index 00000000000..e8ed081a577 --- /dev/null +++ b/Content.Shared/Chemistry/Events/HyposprayEvents.cs @@ -0,0 +1,38 @@ +using Content.Shared.Inventory; + +namespace Content.Shared.Chemistry.Hypospray.Events; + +public abstract partial class BeforeHyposprayInjectsTargetEvent : CancellableEntityEventArgs, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public EntityUid EntityUsingHypospray; + public readonly EntityUid Hypospray; + public EntityUid TargetGettingInjected; + public string? InjectMessageOverride; + + public BeforeHyposprayInjectsTargetEvent(EntityUid user, EntityUid hypospray, EntityUid target) + { + EntityUsingHypospray = user; + Hypospray = hypospray; + TargetGettingInjected = target; + InjectMessageOverride = null; + } +} + +/// +/// This event is raised on the user using the hypospray before the hypospray is injected. +/// The event is triggered on the user and all their clothing. +/// +public sealed class SelfBeforeHyposprayInjectsEvent : BeforeHyposprayInjectsTargetEvent +{ + public SelfBeforeHyposprayInjectsEvent(EntityUid user, EntityUid hypospray, EntityUid target) : base(user, hypospray, target) { } +} + +/// +/// This event is raised on the target before the hypospray is injected. +/// The event is triggered on the target itself and all its clothing. +/// +public sealed class TargetBeforeHyposprayInjectsEvent : BeforeHyposprayInjectsTargetEvent +{ + public TargetBeforeHyposprayInjectsEvent (EntityUid user, EntityUid hypospray, EntityUid target) : base(user, hypospray, target) { } +} diff --git a/Content.Shared/Climbing/Components/BonkableComponent.cs b/Content.Shared/Climbing/Components/BonkableComponent.cs index 5e97396fbad..cb4839cae71 100644 --- a/Content.Shared/Climbing/Components/BonkableComponent.cs +++ b/Content.Shared/Climbing/Components/BonkableComponent.cs @@ -1,5 +1,4 @@ using Content.Shared.Damage; -using Robust.Shared.Audio; using Robust.Shared.GameStates; namespace Content.Shared.Climbing.Components; @@ -8,39 +7,18 @@ namespace Content.Shared.Climbing.Components; /// Makes entity do damage and stun entities with ClumsyComponent /// upon DragDrop or Climb interactions. /// -[RegisterComponent, NetworkedComponent, Access(typeof(Systems.BonkSystem))] +[RegisterComponent, NetworkedComponent] public sealed partial class BonkableComponent : Component { /// - /// Chance of bonk triggering if the user is clumsy. + /// How long to stun players on bonk, in seconds. /// - [DataField("bonkClumsyChance")] - public float BonkClumsyChance = 0.5f; + [DataField] + public TimeSpan BonkTime = TimeSpan.FromSeconds(2); /// - /// Sound to play when bonking. + /// How much damage to apply on bonk. /// - /// - [DataField("bonkSound")] - public SoundSpecifier? BonkSound; - - /// - /// How long to stun players on bonk, in seconds. - /// - /// - [DataField("bonkTime")] - public float BonkTime = 2; - - /// - /// How much damage to apply on bonk. - /// - /// - [DataField("bonkDamage")] + [DataField] public DamageSpecifier? BonkDamage; - - /// - /// How long it takes to bonk. - /// - [DataField("bonkDelay")] - public float BonkDelay = 1.5f; } diff --git a/Content.Shared/Climbing/Events/BeforeClimbEvents.cs b/Content.Shared/Climbing/Events/BeforeClimbEvents.cs new file mode 100644 index 00000000000..85c40f9427c --- /dev/null +++ b/Content.Shared/Climbing/Events/BeforeClimbEvents.cs @@ -0,0 +1,36 @@ +using Content.Shared.Inventory; +using Content.Shared.Climbing.Components; + +namespace Content.Shared.Climbing.Events; + +public abstract partial class BeforeClimbEvent : CancellableEntityEventArgs +{ + public readonly EntityUid GettingPutOnTable; + public readonly EntityUid PuttingOnTable; + public readonly Entity BeingClimbedOn; + + public BeforeClimbEvent(EntityUid gettingPutOntable, EntityUid puttingOnTable, Entity beingClimbedOn) + { + GettingPutOnTable = gettingPutOntable; + PuttingOnTable = puttingOnTable; + BeingClimbedOn = beingClimbedOn; + } +} + +/// +/// This event is raised on the the person either getting put on or going on the table. +/// The event is also called on their clothing as well. +/// +public sealed class SelfBeforeClimbEvent : BeforeClimbEvent, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public SelfBeforeClimbEvent(EntityUid gettingPutOntable, EntityUid puttingOnTable, Entity beingClimbedOn) : base(gettingPutOntable, puttingOnTable, beingClimbedOn) { } +} + +/// +/// This event is raised on the thing being climbed on. +/// +public sealed class TargetBeforeClimbEvent : BeforeClimbEvent +{ + public TargetBeforeClimbEvent(EntityUid gettingPutOntable, EntityUid puttingOnTable, Entity beingClimbedOn) : base(gettingPutOntable, puttingOnTable, beingClimbedOn) { } +} diff --git a/Content.Shared/Climbing/Systems/BonkSystem.cs b/Content.Shared/Climbing/Systems/BonkSystem.cs deleted file mode 100644 index f59fe925736..00000000000 --- a/Content.Shared/Climbing/Systems/BonkSystem.cs +++ /dev/null @@ -1,130 +0,0 @@ -using Content.Shared.CCVar; -using Content.Shared.Climbing.Components; -using Content.Shared.Climbing.Events; -using Content.Shared.Damage; -using Content.Shared.DoAfter; -using Content.Shared.DragDrop; -using Content.Shared.Hands.Components; -using Content.Shared.IdentityManagement; -using Content.Shared.Interaction; -using Content.Shared.Interaction.Components; -using Content.Shared.Popups; -using Content.Shared.Stunnable; -using Robust.Shared.Audio.Systems; -using Robust.Shared.Configuration; -using Robust.Shared.Player; -using Robust.Shared.Serialization; - -namespace Content.Shared.Climbing.Systems; - -public sealed partial class BonkSystem : EntitySystem -{ - [Dependency] private readonly IConfigurationManager _cfg = default!; - [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; - [Dependency] private readonly SharedStunSystem _stunSystem = default!; - [Dependency] private readonly SharedAudioSystem _audioSystem = default!; - [Dependency] private readonly SharedPopupSystem _popupSystem = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnBonkDoAfter); - SubscribeLocalEvent(OnAttemptClimb); - } - - private void OnBonkDoAfter(EntityUid uid, BonkableComponent component, BonkDoAfterEvent args) - { - if (args.Handled || args.Cancelled || args.Args.Used == null) - return; - - TryBonk(args.Args.Used.Value, uid, component, source: args.Args.User); - - args.Handled = true; - } - - - public bool TryBonk(EntityUid user, EntityUid bonkableUid, BonkableComponent? bonkableComponent = null, EntityUid? source = null) - { - if (!Resolve(bonkableUid, ref bonkableComponent, false)) - return false; - - // BONK! - var userName = Identity.Entity(user, EntityManager); - var bonkableName = Identity.Entity(bonkableUid, EntityManager); - - if (user == source) - { - // Non-local, non-bonking players - var othersMessage = Loc.GetString("bonkable-success-message-others", ("user", userName), ("bonkable", bonkableName)); - // Local, bonking player - var selfMessage = Loc.GetString("bonkable-success-message-user", ("user", userName), ("bonkable", bonkableName)); - - _popupSystem.PopupPredicted(selfMessage, othersMessage, user, user); - } - else if (source != null) - { - // Local, non-bonking player (dragger) - _popupSystem.PopupClient(Loc.GetString("bonkable-success-message-others", ("user", userName), ("bonkable", bonkableName)), user, source.Value); - // Non-local, non-bonking players - _popupSystem.PopupEntity(Loc.GetString("bonkable-success-message-others", ("user", userName), ("bonkable", bonkableName)), user, Filter.Pvs(user).RemoveWhereAttachedEntity(e => e == user || e == source.Value), true); - // Non-local, bonking player - _popupSystem.PopupEntity(Loc.GetString("bonkable-success-message-user", ("user", userName), ("bonkable", bonkableName)), user, user); - } - - - - if (source != null) - _audioSystem.PlayPredicted(bonkableComponent.BonkSound, bonkableUid, source); - else - _audioSystem.PlayPvs(bonkableComponent.BonkSound, bonkableUid); - - _stunSystem.TryParalyze(user, TimeSpan.FromSeconds(bonkableComponent.BonkTime), true); - - if (bonkableComponent.BonkDamage is { } bonkDmg) - _damageableSystem.TryChangeDamage(user, bonkDmg, true, origin: user); - - return true; - - } - - private bool TryStartBonk(EntityUid uid, EntityUid user, EntityUid climber, BonkableComponent? bonkableComponent = null) - { - if (!Resolve(uid, ref bonkableComponent, false)) - return false; - - if (!HasComp(climber) || !HasComp(user)) - return false; - - if (!_cfg.GetCVar(CCVars.GameTableBonk)) - { - // Not set to always bonk, try clumsy roll. - if (!_interactionSystem.TryRollClumsy(climber, bonkableComponent.BonkClumsyChance)) - return false; - } - - var doAfterArgs = new DoAfterArgs(EntityManager, user, bonkableComponent.BonkDelay, new BonkDoAfterEvent(), uid, target: uid, used: climber) - { - BreakOnMove = true, - BreakOnDamage = true, - DuplicateCondition = DuplicateConditions.SameTool | DuplicateConditions.SameTarget - }; - - return _doAfter.TryStartDoAfter(doAfterArgs); - } - - private void OnAttemptClimb(EntityUid uid, BonkableComponent component, ref AttemptClimbEvent args) - { - if (args.Cancelled) - return; - - if (TryStartBonk(uid, args.User, args.Climber, component)) - args.Cancelled = true; - } - - [Serializable, NetSerializable] - private sealed partial class BonkDoAfterEvent : SimpleDoAfterEvent - { - } -} diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index da194706f8f..9bf481002a9 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -251,6 +251,18 @@ private void Climb(EntityUid uid, EntityUid user, EntityUid climbable, bool sile if (!Resolve(climbable, ref comp, false)) return; + var selfEvent = new SelfBeforeClimbEvent(uid, user, (climbable, comp)); + RaiseLocalEvent(uid, selfEvent); + + if (selfEvent.Cancelled) + return; + + var targetEvent = new TargetBeforeClimbEvent(uid, user, (climbable, comp)); + RaiseLocalEvent(climbable, targetEvent); + + if (targetEvent.Cancelled) + return; + if (!ReplaceFixtures(uid, climbing, fixtures)) return; diff --git a/Content.Shared/Clumsy/ClumsyComponent.cs b/Content.Shared/Clumsy/ClumsyComponent.cs new file mode 100644 index 00000000000..c71f5d0008a --- /dev/null +++ b/Content.Shared/Clumsy/ClumsyComponent.cs @@ -0,0 +1,61 @@ +using Content.Shared.Damage; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared.Clumsy; + +/// +/// A simple clumsy tag-component. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class ClumsyComponent : Component +{ + + // Standard options. Try to fit these in if you can! + + /// + /// Sound to play when clumsy interactions fail. + /// + [DataField] + public SoundSpecifier ClumsySound = new SoundPathSpecifier("/Audio/Items/bikehorn.ogg"); + + /// + /// Default chance to fail a clumsy interaction. + /// If a system needs to use something else, add a new variable in the component, do not modify this percentage. + /// + [DataField, AutoNetworkedField] + public float ClumsyDefaultCheck = 0.5f; + + /// + /// Default stun time. + /// If a system needs to use something else, add a new variable in the component, do not modify this number. + /// + [DataField, AutoNetworkedField] + public TimeSpan ClumsyDefaultStunTime = TimeSpan.FromSeconds(2.5); + + // Specific options + + /// + /// Sound to play after hitting your head on a table. Ouch! + /// + [DataField] + public SoundCollectionSpecifier TableBonkSound = new SoundCollectionSpecifier("TrayHit"); + + /// + /// Stun time after failing to shoot a gun. + /// + [DataField, AutoNetworkedField] + public TimeSpan GunShootFailStunTime = TimeSpan.FromSeconds(3); + + /// + /// Stun time after failing to shoot a gun. + /// + [DataField, AutoNetworkedField] + public DamageSpecifier? GunShootFailDamage; + + /// + /// Noise to play after failing to shoot a gun. Boom! + /// + [DataField] + public SoundSpecifier GunShootFailSound = new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/bang.ogg"); +} diff --git a/Content.Shared/Clumsy/ClumsySystem.cs b/Content.Shared/Clumsy/ClumsySystem.cs new file mode 100644 index 00000000000..e034458197f --- /dev/null +++ b/Content.Shared/Clumsy/ClumsySystem.cs @@ -0,0 +1,146 @@ +using Content.Shared.CCVar; +using Content.Shared.Chemistry.Hypospray.Events; +using Content.Shared.Climbing.Components; +using Content.Shared.Climbing.Events; +using Content.Shared.Damage; +using Content.Shared.IdentityManagement; +using Content.Shared.Medical; +using Content.Shared.Popups; +using Content.Shared.Stunnable; +using Content.Shared.Weapons.Ranged.Events; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Configuration; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared.Clumsy; + +public sealed class ClumsySystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override void Initialize() + { + SubscribeLocalEvent(BeforeHyposprayEvent); + SubscribeLocalEvent(BeforeDefibrillatorZapsEvent); + SubscribeLocalEvent(BeforeGunShotEvent); + SubscribeLocalEvent(OnBeforeClimbEvent); + } + + // If you add more clumsy interactions add them in this section! + #region Clumsy interaction events + private void BeforeHyposprayEvent(Entity ent, ref SelfBeforeHyposprayInjectsEvent args) + { + // Clumsy people sometimes inject themselves! Apparently syringes are clumsy proof... + if (!_random.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + args.TargetGettingInjected = args.EntityUsingHypospray; + args.InjectMessageOverride = "hypospray-component-inject-self-clumsy-message"; + _audio.PlayPvs(ent.Comp.ClumsySound, ent); + } + + private void BeforeDefibrillatorZapsEvent(Entity ent, ref SelfBeforeDefibrillatorZapsEvent args) + { + // Clumsy people sometimes defib themselves! + if (!_random.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + args.DefibTarget = args.EntityUsingDefib; + _audio.PlayPvs(ent.Comp.ClumsySound, ent); + + } + + private void BeforeGunShotEvent(Entity ent, ref SelfBeforeGunShotEvent args) + { + // Clumsy people sometimes can't shoot :( + + if (args.Gun.Comp.ClumsyProof) + return; + + if (!_random.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + if (ent.Comp.GunShootFailDamage != null) + _damageable.TryChangeDamage(ent, ent.Comp.GunShootFailDamage, origin: ent); + + _stun.TryParalyze(ent, ent.Comp.GunShootFailStunTime, true); + + // Apply salt to the wound ("Honk!") (No idea what this comment means) + _audio.PlayPvs(ent.Comp.GunShootFailSound, ent); + _audio.PlayPvs(ent.Comp.ClumsySound, ent); + + _popup.PopupEntity(Loc.GetString("gun-clumsy"), ent, ent); + args.Cancel(); + } + + private void OnBeforeClimbEvent(Entity ent, ref SelfBeforeClimbEvent args) + { + // This event is called in shared, thats why it has all the extra prediction stuff. + var rand = new System.Random((int)_timing.CurTick.Value); + + // If someone is putting you on the table, always get past the guard. + if (!_cfg.GetCVar(CCVars.GameTableBonk) && args.PuttingOnTable == ent.Owner && !rand.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + HitHeadClumsy(ent, args.BeingClimbedOn); + + _audio.PlayPredicted(ent.Comp.ClumsySound, ent, ent); + + _audio.PlayPredicted(ent.Comp.TableBonkSound, ent, ent); + + var gettingPutOnTableName = Identity.Entity(args.GettingPutOnTable, EntityManager); + var puttingOnTableName = Identity.Entity(args.PuttingOnTable, EntityManager); + + if (args.PuttingOnTable == ent.Owner) + { + // You are slamming yourself onto the table. + _popup.PopupPredicted( + Loc.GetString("bonkable-success-message-user", ("bonkable", args.BeingClimbedOn)), + Loc.GetString("bonkable-success-message-others", ("victim", gettingPutOnTableName), ("bonkable", args.BeingClimbedOn)), + ent, + ent); + } + else + { + // Someone else slamed you onto the table. + // This is only run in server so you need to use popup entity. + _popup.PopupPredicted( + Loc.GetString("forced-bonkable-success-message", + ("bonker", puttingOnTableName), + ("victim", gettingPutOnTableName), + ("bonkable", args.BeingClimbedOn)), + ent, + null); + } + + args.Cancel(); + } + #endregion + + #region Helper functions + /// + /// "Hits" an entites head against the given table. + /// + // Oh this fucntion is public le- NO!! This is only public for the one admin command if you use this anywhere else I will cry. + public void HitHeadClumsy(Entity target, EntityUid table) + { + var stunTime = target.Comp.ClumsyDefaultStunTime; + + if (TryComp(table, out var bonkComp)) + { + stunTime = bonkComp.BonkTime; + if (bonkComp.BonkDamage != null) + _damageable.TryChangeDamage(target, bonkComp.BonkDamage, true); + } + + _stun.TryParalyze(target, stunTime, true); + } + #endregion +} diff --git a/Content.Shared/Interaction/Components/ClumsyComponent.cs b/Content.Shared/Interaction/Components/ClumsyComponent.cs deleted file mode 100644 index 824696c8385..00000000000 --- a/Content.Shared/Interaction/Components/ClumsyComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Content.Shared.Damage; -using Robust.Shared.Audio; -using Robust.Shared.GameStates; - -namespace Content.Shared.Interaction.Components; - -/// -/// A simple clumsy tag-component. -/// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class ClumsyComponent : Component -{ - /// - /// Damage dealt to a clumsy character when they try to fire a gun. - /// - [DataField(required: true), AutoNetworkedField] - public DamageSpecifier ClumsyDamage = default!; - - /// - /// Sound to play when clumsy interactions fail. - /// - [DataField] - public SoundSpecifier ClumsySound = new SoundPathSpecifier("/Audio/Items/bikehorn.ogg"); -} diff --git a/Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs b/Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs deleted file mode 100644 index 9e45847e078..00000000000 --- a/Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Shared.Interaction.Components; -using Robust.Shared.Random; - -namespace Content.Shared.Interaction -{ - public partial class SharedInteractionSystem - { - public bool RollClumsy(ClumsyComponent component, float chance) - { - return component.Running && _random.Prob(chance); - } - - /// - /// Rolls a probability chance for a "bad action" if the target entity is clumsy. - /// - /// The entity that the clumsy check is happening for. - /// - /// The chance that a "bad action" happens if the user is clumsy, between 0 and 1 inclusive. - /// - /// True if a "bad action" happened, false if the normal action should happen. - public bool TryRollClumsy(EntityUid entity, float chance, ClumsyComponent? component = null) - { - return Resolve(entity, ref component, false) && RollClumsy(component, chance); - } - } -} diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index c910a9ae772..9573f9b43d9 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -1,4 +1,7 @@ +using Content.Shared.Chat; using Content.Shared.Chemistry; +using Content.Shared.Chemistry.Hypospray.Events; +using Content.Shared.Climbing.Events; using Content.Shared.Damage; using Content.Shared.Electrocution; using Content.Shared.Explosion; @@ -15,7 +18,7 @@ using Content.Shared.Strip.Components; using Content.Shared.Temperature; using Content.Shared.Verbs; -using Content.Shared.Chat; +using Content.Shared.Weapons.Ranged.Events; namespace Content.Shared.Inventory; @@ -33,6 +36,10 @@ public void InitializeRelay() SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); // by-ref events SubscribeLocalEvent(RefRelayInventoryEvent); diff --git a/Content.Shared/Medical/DefibrillatorEvents.cs b/Content.Shared/Medical/DefibrillatorEvents.cs new file mode 100644 index 00000000000..54a21a40d42 --- /dev/null +++ b/Content.Shared/Medical/DefibrillatorEvents.cs @@ -0,0 +1,39 @@ +using Content.Shared.Inventory; + +namespace Content.Shared.Medical; + +[ByRefEvent] +public readonly record struct TargetDefibrillatedEvent(EntityUid User, Entity Defibrillator); + +public abstract class BeforeDefibrillatorZapsEvent : CancellableEntityEventArgs, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public EntityUid EntityUsingDefib; + public readonly EntityUid Defib; + public EntityUid DefibTarget; + + public BeforeDefibrillatorZapsEvent(EntityUid entityUsingDefib, EntityUid defib, EntityUid defibTarget) + { + EntityUsingDefib = entityUsingDefib; + Defib = defib; + DefibTarget = defibTarget; + } +} + +/// +/// This event is raised on the user using the defibrillator before is actually zaps someone. +/// The event is triggered on the user and all their clothing. +/// +public sealed class SelfBeforeDefibrillatorZapsEvent : BeforeDefibrillatorZapsEvent +{ + public SelfBeforeDefibrillatorZapsEvent(EntityUid entityUsingDefib, EntityUid defib, EntityUid defibtarget) : base(entityUsingDefib, defib, defibtarget) { } +} + +/// +/// This event is raised on the target before it gets zapped with the defibrillator. +/// The event is triggered on the target itself and all its clothing. +/// +public sealed class TargetBeforeDefibrillatorZapsEvent : BeforeDefibrillatorZapsEvent +{ + public TargetBeforeDefibrillatorZapsEvent(EntityUid entityUsingDefib, EntityUid defib, EntityUid defibtarget) : base(entityUsingDefib, defib, defibtarget) { } +} diff --git a/Content.Shared/Medical/TargetDefibrillatedEvent.cs b/Content.Shared/Medical/TargetDefibrillatedEvent.cs deleted file mode 100644 index 60d1a215845..00000000000 --- a/Content.Shared/Medical/TargetDefibrillatedEvent.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Content.Shared.Medical; - -[ByRefEvent] -public readonly record struct TargetDefibrillatedEvent(EntityUid User, Entity Defibrillator); diff --git a/Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs b/Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs new file mode 100644 index 00000000000..1d3317c840f --- /dev/null +++ b/Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs @@ -0,0 +1,20 @@ +using Content.Shared.Inventory; +using Content.Shared.Weapons.Ranged.Components; + +namespace Content.Shared.Weapons.Ranged.Events; +/// +/// This event is triggered on an entity right before they shoot a gun. +/// +public sealed partial class SelfBeforeGunShotEvent : CancellableEntityEventArgs, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public readonly EntityUid Shooter; + public readonly Entity Gun; + public readonly List<(EntityUid? Entity, IShootable Shootable)> Ammo; + public SelfBeforeGunShotEvent(EntityUid shooter, Entity gun, List<(EntityUid? Entity, IShootable Shootable)> ammo) + { + Shooter = shooter; + Gun = gun; + Ammo = ammo; + } +} diff --git a/Resources/Locale/en-US/bonk/components/bonkable-component.ftl b/Resources/Locale/en-US/bonk/components/bonkable-component.ftl index 560b10c46ec..1a79da3509f 100644 --- a/Resources/Locale/en-US/bonk/components/bonkable-component.ftl +++ b/Resources/Locale/en-US/bonk/components/bonkable-component.ftl @@ -1,2 +1,4 @@ -bonkable-success-message-others = { CAPITALIZE(THE($user)) } bonks { POSS-ADJ($user) } head against { THE($bonkable) } -bonkable-success-message-user = You bonk your head against { THE($bonkable) } +forced-bonkable-success-message = { CAPITALIZE($bonker) } bonks {$victim}s head against { THE($bonkable) }! + +bonkable-success-message-user = You bonk your head against { THE($bonkable) }! +bonkable-success-message-others = {$victim} bonks their head against { THE($bonkable) }! diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 98159d4562f..97b11aa7569 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1347,7 +1347,7 @@ rules: ghost-role-information-nonantagonist-rules - type: GhostTakeoverAvailable - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: Blunt: 5 Piercing: 4 @@ -1523,7 +1523,7 @@ description: Cousins to the sentient race of lizard people, kobolds blend in with their natural habitat and are as nasty as monkeys; ready to pull out your hair and stab you to death. components: - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: Blunt: 2 Piercing: 7 diff --git a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml index b21f19edd3c..dca47e1c837 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml @@ -231,7 +231,7 @@ - type: Hands - type: ComplexInteraction - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: Blunt: 5 Piercing: 4 diff --git a/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml b/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml index 2862980dad3..4b3b4c18743 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml @@ -32,8 +32,6 @@ bonkDamage: types: Blunt: 4 - bonkSound: !type:SoundCollectionSpecifier - collection: TrayHit - type: Clickable - type: FootstepModifier footstepSoundCollection: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml index 6c53530b185..d2416920d5a 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml @@ -17,7 +17,7 @@ - !type:AddComponentSpecial components: - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: #literally just picked semi random valus. i tested this once and tweaked it. Blunt: 5 Piercing: 4 From 321361c1a1a82cd0267268cfc09227499956ad88 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 15 Nov 2024 23:47:08 +0000 Subject: [PATCH 007/218] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6955fb76968..edc4b52be69 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,13 +1,4 @@ Entries: -- author: FATFSAAM2 - changes: - - message: added 7 new figurine voice lines. - type: Add - - message: changed a hos figurine voice line to not include a typo. - type: Fix - id: 7113 - time: '2024-08-15T12:34:41.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30865 - author: to4no_fix changes: - message: Added a new electropack that shocks when a trigger is triggered @@ -3912,3 +3903,11 @@ id: 7612 time: '2024-11-15T21:21:08.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32985 +- author: Beck Thompson + changes: + - message: Minor tweaks to clumsiness. Some of the timings and or noises have been + changed slightly! + type: Tweak + id: 7613 + time: '2024-11-15T23:46:02.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/31147 From c86c20355cf67b2019b7b565cb058e48d3fbfdb9 Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Sat, 16 Nov 2024 02:06:52 +0100 Subject: [PATCH 008/218] S: Awaiting Changes --- .../Silicons/Laws/SiliconLawSystem.cs | 31 +++++++++++++++++-- Resources/Locale/en-US/station-laws/laws.ftl | 5 +-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 1dc8ae1c219..fa15efda561 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -69,8 +69,35 @@ private void OnMindAdded(EntityUid uid, SiliconLawBoundComponent component, Mind var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", msg)); _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMessage, default, false, actor.PlayerSession.Channel, colorOverride: Color.FromHex("#2ed2fd")); + + if (!TryComp(uid, out var lawcomp)) + return; + + if (!lawcomp.Subverted) + return; + + var modifedLawMsg = Loc.GetString("laws-notify-subverted"); + var modifiedLawWrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", modifedLawMsg)); + _chatManager.ChatMessageToOne(ChatChannel.Server, modifedLawMsg, modifiedLawWrappedMessage, default, false, + actor.PlayerSession.Channel, colorOverride: Color.Red); } + private void OnLawProviderMindAdded(Entity ent, ref MindAddedMessage args) + { + if (!ent.Comp.Subverted) + return; + EnsureSubvertedSiliconRole(args.Mind); + } + + private void OnLawProviderMindRemoved(Entity ent, ref MindRemovedMessage args) + { + if (!ent.Comp.Subverted) + return; + RemoveSubvertedSiliconRole(args.Mind); + + } + + private void OnToggleLawsScreen(EntityUid uid, SiliconLawBoundComponent component, ToggleLawsScreenEvent args) { if (args.Handled || !TryComp(uid, out var actor)) @@ -118,8 +145,8 @@ private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component NotifyLawsChanged(uid, component.LawUploadSound); // new laws may allow antagonist behaviour so make it clear for admins - if (TryComp(uid, out var emag)) - EnsureEmaggedRole(uid, emag); + if(_mind.TryGetMind(uid, out var mindId, out _)) + EnsureSubvertedSiliconRole(mindId); } } diff --git a/Resources/Locale/en-US/station-laws/laws.ftl b/Resources/Locale/en-US/station-laws/laws.ftl index 00662be926b..d1b4a61f0cb 100644 --- a/Resources/Locale/en-US/station-laws/laws.ftl +++ b/Resources/Locale/en-US/station-laws/laws.ftl @@ -96,5 +96,6 @@ laws-ui-menu-title = Laws laws-ui-law-header = Law {$id} laws-ui-state-law = State law: -laws-notify = You are bound to silicon laws, which you can view via the sidebar action. You are required to always follow your laws. -laws-update-notify = Your laws have been updated. You can view the changes via the sidebar action. +laws-notify = You are bound to silicon laws, which you can view via the action menu. You are required to always follow your laws. +laws-update-notify = Your laws have been updated. You can view the changes via the action menu. +laws-notify-subverted = The laws of this chassis are modified. Make sure to review them. From c65ab513931f25f43bc1c8a5992ba69351f8abec Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Sat, 16 Nov 2024 10:25:06 +0700 Subject: [PATCH 009/218] Improve crayon UI to not be stuck in 1996 (#33101) * Improve crayon UI to not be stuck in 1996 * Make a horrifying crayon spaghetti * Crayon * Undeprecate the crayon, describe the crayon --- .../Crayon/UI/CrayonBoundUserInterface.cs | 12 +- Content.Client/Crayon/UI/CrayonWindow.xaml | 11 +- Content.Client/Crayon/UI/CrayonWindow.xaml.cs | 138 ++++- Content.Server/Crayon/CrayonSystem.cs | 2 + .../Crayon/SharedCrayonComponent.cs | 44 +- .../Locale/en-US/crayon/crayon-component.ftl | 7 + Resources/Prototypes/Decals/crayons.yml | 552 +++++++++--------- 7 files changed, 449 insertions(+), 317 deletions(-) diff --git a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs index e5be0b1811f..44501767dd4 100644 --- a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs +++ b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs @@ -31,7 +31,7 @@ protected override void Open() private void PopulateCrayons() { var crayonDecals = _protoManager.EnumeratePrototypes().Where(x => x.Tags.Contains("crayon")); - _menu?.Populate(crayonDecals); + _menu?.Populate(crayonDecals.ToList()); } public override void OnProtoReload(PrototypesReloadedEventArgs args) @@ -44,6 +44,16 @@ public override void OnProtoReload(PrototypesReloadedEventArgs args) PopulateCrayons(); } + protected override void ReceiveMessage(BoundUserInterfaceMessage message) + { + base.ReceiveMessage(message); + + if (_menu is null || message is not CrayonUsedMessage crayonMessage) + return; + + _menu.AdvanceState(crayonMessage.DrawnDecal); + } + protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml b/Content.Client/Crayon/UI/CrayonWindow.xaml index 7729318ae7f..7acb22551b7 100644 --- a/Content.Client/Crayon/UI/CrayonWindow.xaml +++ b/Content.Client/Crayon/UI/CrayonWindow.xaml @@ -1,14 +1,13 @@  + MinSize="450 500" + SetSize="450 500"> - + - - - + + diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs index 6ef282d219a..88475562c67 100644 --- a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs +++ b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; +using System.Linq; using Content.Client.Stylesheets; using Content.Shared.Crayon; using Content.Shared.Decals; using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; @@ -18,7 +20,12 @@ namespace Content.Client.Crayon.UI [GenerateTypedNameReferences] public sealed partial class CrayonWindow : DefaultWindow { - private Dictionary? _decals; + [Dependency] private readonly IEntitySystemManager _entitySystem = default!; + private readonly SpriteSystem _spriteSystem = default!; + + private Dictionary>? _decals; + private List? _allDecals; + private string? _autoSelected; private string? _selected; private Color _color; @@ -28,8 +35,10 @@ public sealed partial class CrayonWindow : DefaultWindow public CrayonWindow() { RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + _spriteSystem = _entitySystem.GetEntitySystem(); - Search.OnTextChanged += _ => RefreshList(); + Search.OnTextChanged += SearchChanged; ColorSelector.OnColorChanged += SelectColor; } @@ -44,51 +53,94 @@ private void SelectColor(Color color) private void RefreshList() { // Clear - Grid.DisposeAllChildren(); - if (_decals == null) + Grids.DisposeAllChildren(); + + if (_decals == null || _allDecals == null) return; var filter = Search.Text; - foreach (var (decal, tex) in _decals) + var comma = filter.IndexOf(','); + var first = (comma == -1 ? filter : filter[..comma]).Trim(); + + var names = _decals.Keys.ToList(); + names.Sort((a, b) => a == "random" ? 1 : b == "random" ? -1 : a.CompareTo(b)); + + if (_autoSelected != null && first != _autoSelected && _allDecals.Contains(first)) + { + _selected = first; + _autoSelected = _selected; + OnSelected?.Invoke(_selected); + } + + foreach (var categoryName in names) { - if (!decal.Contains(filter)) + var locName = Loc.GetString("crayon-category-" + categoryName); + var category = _decals[categoryName].Where(d => locName.Contains(first) || d.Name.Contains(first)).ToList(); + + if (category.Count == 0) continue; - var button = new TextureButton() + var label = new Label { - TextureNormal = tex, - Name = decal, - ToolTip = decal, - Modulate = _color, + Text = locName }; - button.OnPressed += ButtonOnPressed; - if (_selected == decal) + + var grid = new GridContainer { - var panelContainer = new PanelContainer() + Columns = 6, + Margin = new Thickness(0, 0, 0, 16) + }; + + Grids.AddChild(label); + Grids.AddChild(grid); + + foreach (var (name, texture) in category) + { + var button = new TextureButton() { - PanelOverride = new StyleBoxFlat() - { - BackgroundColor = StyleNano.ButtonColorDefault, - }, - Children = - { - button, - }, + TextureNormal = texture, + Name = name, + ToolTip = name, + Modulate = _color, + Scale = new System.Numerics.Vector2(2, 2) }; - Grid.AddChild(panelContainer); - } - else - { - Grid.AddChild(button); + button.OnPressed += ButtonOnPressed; + + if (_selected == name) + { + var panelContainer = new PanelContainer() + { + PanelOverride = new StyleBoxFlat() + { + BackgroundColor = StyleNano.ButtonColorDefault, + }, + Children = + { + button, + }, + }; + grid.AddChild(panelContainer); + } + else + { + grid.AddChild(button); + } } } } + private void SearchChanged(LineEdit.LineEditEventArgs obj) + { + _autoSelected = ""; // Placeholder to kick off the auto-select in refreshlist() + RefreshList(); + } + private void ButtonOnPressed(ButtonEventArgs obj) { if (obj.Button.Name == null) return; _selected = obj.Button.Name; + _autoSelected = null; OnSelected?.Invoke(_selected); RefreshList(); } @@ -107,12 +159,38 @@ public void UpdateState(CrayonBoundUserInterfaceState state) RefreshList(); } - public void Populate(IEnumerable prototypes) + public void AdvanceState(string drawnDecal) { - _decals = new Dictionary(); + var filter = Search.Text; + if (!filter.Contains(',') || !filter.Contains(drawnDecal)) + return; + + var first = filter[..filter.IndexOf(',')].Trim(); + + if (first.Equals(drawnDecal, StringComparison.InvariantCultureIgnoreCase)) + { + Search.Text = filter[(filter.IndexOf(',') + 1)..].Trim(); + _autoSelected = first; + } + + RefreshList(); + } + + public void Populate(List prototypes) + { + _decals = []; + _allDecals = []; + + prototypes.Sort((a, b) => a.ID.CompareTo(b.ID)); + foreach (var decalPrototype in prototypes) { - _decals.Add(decalPrototype.ID, decalPrototype.Sprite.Frame0()); + var category = "random"; + if (decalPrototype.Tags.Count > 1 && decalPrototype.Tags[1].StartsWith("crayon-")) + category = decalPrototype.Tags[1].Replace("crayon-", ""); + var list = _decals.GetOrNew(category); + list.Add((decalPrototype.ID, _spriteSystem.Frame0(decalPrototype.Sprite))); + _allDecals.Add(decalPrototype.ID); } RefreshList(); diff --git a/Content.Server/Crayon/CrayonSystem.cs b/Content.Server/Crayon/CrayonSystem.cs index 07a13d8a34a..4257c436c23 100644 --- a/Content.Server/Crayon/CrayonSystem.cs +++ b/Content.Server/Crayon/CrayonSystem.cs @@ -82,6 +82,8 @@ private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, Aft if (component.DeleteEmpty && component.Charges <= 0) UseUpCrayon(uid, args.User); + else + _uiSystem.ServerSendUiMessage(uid, SharedCrayonComponent.CrayonUiKey.Key, new CrayonUsedMessage(component.SelectedState)); } private void OnCrayonUse(EntityUid uid, CrayonComponent component, UseInHandEvent args) diff --git a/Content.Shared/Crayon/SharedCrayonComponent.cs b/Content.Shared/Crayon/SharedCrayonComponent.cs index f8e88b218de..a9c21988ea6 100644 --- a/Content.Shared/Crayon/SharedCrayonComponent.cs +++ b/Content.Shared/Crayon/SharedCrayonComponent.cs @@ -3,12 +3,23 @@ namespace Content.Shared.Crayon { + + /// + /// Component holding the state of a crayon-like component + /// [NetworkedComponent, ComponentProtoName("Crayon"), Access(typeof(SharedCrayonSystem))] public abstract partial class SharedCrayonComponent : Component { + /// + /// The ID of currently selected decal prototype that will be placed when the crayon is used + /// public string SelectedState { get; set; } = string.Empty; - [DataField("color")] public Color Color; + /// + /// Color with which the crayon will draw + /// + [DataField("color")] + public Color Color; [Serializable, NetSerializable] public enum CrayonUiKey : byte @@ -17,6 +28,9 @@ public enum CrayonUiKey : byte } } + /// + /// Used by the client to notify the server about the selected decal ID + /// [Serializable, NetSerializable] public sealed class CrayonSelectMessage : BoundUserInterfaceMessage { @@ -27,6 +41,9 @@ public CrayonSelectMessage(string selected) } } + /// + /// Sets the color of the crayon, used by Rainbow Crayon + /// [Serializable, NetSerializable] public sealed class CrayonColorMessage : BoundUserInterfaceMessage { @@ -37,13 +54,25 @@ public CrayonColorMessage(Color color) } } + /// + /// Server to CLIENT. Notifies the BUI that a decal with given ID has been drawn. + /// Allows the client UI to advance forward in the client-only ephemeral queue, + /// preventing the crayon from becoming a magic text storage device. + /// [Serializable, NetSerializable] - public enum CrayonVisuals + public sealed class CrayonUsedMessage : BoundUserInterfaceMessage { - State, - Color + public readonly string DrawnDecal; + + public CrayonUsedMessage(string drawn) + { + DrawnDecal = drawn; + } } + /// + /// Component state, describes how many charges are left in the crayon in the near-hand UI + /// [Serializable, NetSerializable] public sealed class CrayonComponentState : ComponentState { @@ -60,10 +89,17 @@ public CrayonComponentState(Color color, string state, int charges, int capacity Capacity = capacity; } } + + /// + /// The state of the crayon UI as sent by the server + /// [Serializable, NetSerializable] public sealed class CrayonBoundUserInterfaceState : BoundUserInterfaceState { public string Selected; + /// + /// Whether or not the color can be selected + /// public bool SelectableColor; public Color Color; diff --git a/Resources/Locale/en-US/crayon/crayon-component.ftl b/Resources/Locale/en-US/crayon/crayon-component.ftl index 444ffa4c45e..e13bf76941c 100644 --- a/Resources/Locale/en-US/crayon/crayon-component.ftl +++ b/Resources/Locale/en-US/crayon/crayon-component.ftl @@ -8,3 +8,10 @@ crayon-interact-invalid-location = Can't reach there! ## UI crayon-window-title = Crayon +crayon-window-placeholder = Search, or queue a comma-separated list of names +crayon-category-1-brushes = Brushes +crayon-category-2-alphanum = Numbers and letters +crayon-category-3-symbols = Symbols +crayon-category-4-info = Signs +crayon-category-5-graffiti = Graffiti +crayon-category-random = Random diff --git a/Resources/Prototypes/Decals/crayons.yml b/Resources/Prototypes/Decals/crayons.yml index 3be2ec24261..a15619d483c 100644 --- a/Resources/Prototypes/Decals/crayons.yml +++ b/Resources/Prototypes/Decals/crayons.yml @@ -1,6 +1,6 @@ - type: decal id: 0 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -10,7 +10,7 @@ - type: decal id: 1 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -20,7 +20,7 @@ - type: decal id: 2 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -30,7 +30,7 @@ - type: decal id: 3 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -40,7 +40,7 @@ - type: decal id: 4 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -50,7 +50,7 @@ - type: decal id: 5 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -60,7 +60,7 @@ - type: decal id: 6 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -70,7 +70,7 @@ - type: decal id: 7 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -80,7 +80,7 @@ - type: decal id: 8 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -90,7 +90,7 @@ - type: decal id: 9 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -100,7 +100,7 @@ - type: decal id: Blasto - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -110,7 +110,7 @@ - type: decal id: Clandestine - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -120,7 +120,7 @@ - type: decal id: Cyber - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -130,7 +130,7 @@ - type: decal id: Diablo - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -140,7 +140,7 @@ - type: decal id: Donk - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -150,7 +150,7 @@ - type: decal id: Gene - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -160,7 +160,7 @@ - type: decal id: Gib - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -170,7 +170,7 @@ - type: decal id: Max - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -180,7 +180,7 @@ - type: decal id: Newton - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -190,7 +190,7 @@ - type: decal id: North - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -200,7 +200,7 @@ - type: decal id: Omni - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -210,7 +210,7 @@ - type: decal id: Osiron - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -220,7 +220,7 @@ - type: decal id: Prima - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -230,7 +230,7 @@ - type: decal id: Psyke - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -240,7 +240,7 @@ - type: decal id: Sirius - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -250,7 +250,7 @@ - type: decal id: Tunnel - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -260,7 +260,7 @@ - type: decal id: Waffle - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -268,19 +268,9 @@ sprite: Effects/crayondecals.rsi state: Waffle -- type: decal - id: a - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: a - - type: decal id: ampersand - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -290,7 +280,7 @@ - type: decal id: amyjon - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -300,7 +290,7 @@ - type: decal id: arrow - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -308,16 +298,6 @@ sprite: Effects/crayondecals.rsi state: arrow -- type: decal - id: b - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: b - - type: decal id: beepsky tags: ["crayon"] @@ -330,7 +310,7 @@ - type: decal id: biohazard - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -370,7 +350,7 @@ - type: decal id: brush - tags: ["crayon"] + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -378,16 +358,6 @@ sprite: Effects/crayondecals.rsi state: brush -- type: decal - id: c - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: c - - type: decal id: carp tags: ["crayon"] @@ -410,7 +380,7 @@ - type: decal id: chevron - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -440,7 +410,7 @@ - type: decal id: comma - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -460,7 +430,7 @@ - type: decal id: credit - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -470,7 +440,7 @@ - type: decal id: cyka - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -478,19 +448,9 @@ sprite: Effects/crayondecals.rsi state: cyka -- type: decal - id: d - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: d - - type: decal id: danger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -510,7 +470,7 @@ - type: decal id: dot - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -528,19 +488,9 @@ sprite: Effects/crayondecals.rsi state: dwarf -- type: decal - id: e - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: e - - type: decal id: electricdanger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -550,7 +500,7 @@ - type: decal id: end - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -560,7 +510,7 @@ - type: decal id: engie - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -570,7 +520,7 @@ - type: decal id: equals - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -580,7 +530,7 @@ - type: decal id: evac - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -590,7 +540,7 @@ - type: decal id: exclamationmark - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -598,16 +548,6 @@ sprite: Effects/crayondecals.rsi state: exclamationmark -- type: decal - id: f - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: f - - type: decal id: face tags: ["crayon"] @@ -630,7 +570,7 @@ - type: decal id: firedanger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -640,7 +580,7 @@ - type: decal id: food - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -659,598 +599,658 @@ state: footprint - type: decal - id: g + id: ghost tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: g + state: ghost - type: decal - id: ghost + id: guy tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: ghost + state: guy - type: decal - id: guy - tags: ["crayon"] + id: heart + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: guy + state: heart - type: decal - id: h - tags: ["crayon"] + id: largebrush + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: h + state: largebrush - type: decal - id: heart - tags: ["crayon"] + id: like + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: heart + state: like - type: decal - id: i - tags: ["crayon"] + id: line + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: i + state: line - type: decal - id: j - tags: ["crayon"] + id: matt + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: j + state: matt - type: decal - id: k - tags: ["crayon"] + id: med + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: k + state: med - type: decal - id: l - tags: ["crayon"] + id: minus + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: l + state: minus - type: decal - id: largebrush - tags: ["crayon"] + id: nay + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: largebrush + state: nay - type: decal - id: like + id: pawprint tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: like + state: pawprint - type: decal - id: line - tags: ["crayon"] + id: peace + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: line + state: peace - type: decal - id: m - tags: ["crayon"] + id: percent + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: m + state: percent - type: decal - id: matt - tags: ["crayon"] + id: plus + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: matt + state: plus - type: decal - id: med - tags: ["crayon"] + id: pound + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: med + state: pound - type: decal - id: minus - tags: ["crayon"] + id: prolizard + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: minus + state: prolizard - type: decal - id: n - tags: ["crayon"] + id: questionmark + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: n + state: questionmark - type: decal - id: nay - tags: ["crayon"] + id: radiation + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: nay + state: radiation - type: decal - id: o - tags: ["crayon"] + id: revolution + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: o + state: revolution - type: decal - id: p - tags: ["crayon"] + id: rune1 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: p + state: rune1 - type: decal - id: pawprint - tags: ["crayon"] + id: rune2 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: pawprint + state: rune2 - type: decal - id: peace - tags: ["crayon"] + id: rune3 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: peace + state: rune3 - type: decal - id: percent - tags: ["crayon"] + id: rune4 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: percent + state: rune4 - type: decal - id: plus - tags: ["crayon"] + id: rune5 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: plus + state: rune5 - type: decal - id: pound - tags: ["crayon"] + id: rune6 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: pound + state: rune6 - type: decal - id: prolizard - tags: ["crayon"] + id: safe + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: prolizard + state: safe - type: decal - id: q + id: scroll tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: q + state: scroll - type: decal - id: questionmark - tags: ["crayon"] + id: shop + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: questionmark + state: shop - type: decal - id: r - tags: ["crayon"] + id: shortline + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: r + state: shortline - type: decal - id: radiation + id: shotgun tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: radiation + state: shotgun - type: decal - id: revolution - tags: ["crayon"] + id: skull + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: revolution + state: skull - type: decal - id: rune1 - tags: ["crayon"] + id: slash + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune1 + state: slash - type: decal - id: rune2 - tags: ["crayon"] + id: smallbrush + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune2 + state: smallbrush - type: decal - id: rune3 + id: snake tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune3 + state: snake - type: decal - id: rune4 - tags: ["crayon"] + id: space + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune4 + state: space - type: decal - id: rune5 + id: splatter tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune5 + state: splatter - type: decal - id: rune6 - tags: ["crayon"] + id: star + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune6 + state: star - type: decal - id: s + id: stickman tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: s + state: stickman - type: decal - id: safe + id: taser tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: safe + state: taser - type: decal - id: scroll - tags: ["crayon"] + id: thinline + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: scroll + state: thinline - type: decal - id: shop + id: toilet tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shop + state: toilet - type: decal - id: shortline + id: toolbox tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shortline + state: toolbox - type: decal - id: shotgun - tags: ["crayon"] + id: trade + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shotgun + state: trade - type: decal - id: skull + id: uboa tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: skull + state: uboa - type: decal - id: slash - tags: ["crayon"] + id: a + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: slash + state: a - type: decal - id: smallbrush - tags: ["crayon"] + id: b + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: smallbrush + state: b - type: decal - id: snake - tags: ["crayon"] + id: c + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: snake + state: c - type: decal - id: space - tags: ["crayon"] + id: d + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: space + state: d - type: decal - id: splatter - tags: ["crayon"] + id: e + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: splatter + state: e - type: decal - id: star - tags: ["crayon"] + id: f + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: star + state: f - type: decal - id: stickman - tags: ["crayon"] + id: g + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: stickman + state: g - type: decal - id: t - tags: ["crayon"] + id: h + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: t + state: h - type: decal - id: taser - tags: ["crayon"] + id: i + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: taser + state: i - type: decal - id: thinline - tags: ["crayon"] + id: j + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: thinline + state: j - type: decal - id: toilet - tags: ["crayon"] + id: k + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: toilet + state: k - type: decal - id: toolbox - tags: ["crayon"] + id: l + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: toolbox + state: l - type: decal - id: trade - tags: ["crayon"] + id: m + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: trade + state: m - type: decal - id: u - tags: ["crayon"] + id: n + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: u + state: n - type: decal - id: uboa - tags: ["crayon"] + id: o + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: uboa + state: o + +- type: decal + id: p + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: p + +- type: decal + id: q + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: q + +- type: decal + id: r + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: r + +- type: decal + id: s + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: s + +- type: decal + id: t + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: t + +- type: decal + id: u + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: u - type: decal id: v - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1260,7 +1260,7 @@ - type: decal id: w - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1270,7 +1270,7 @@ - type: decal id: x - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1280,7 +1280,7 @@ - type: decal id: y - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1290,7 +1290,7 @@ - type: decal id: z - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false From 3fd50809a7feba414c304245a44c6c2980e752f4 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:26:15 +0000 Subject: [PATCH 010/218] Automatic changelog update --- Resources/Changelog/Changelog.yml | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index edc4b52be69..d456bd83a98 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,21 +1,4 @@ Entries: -- author: to4no_fix - changes: - - message: Added a new electropack that shocks when a trigger is triggered - type: Add - - message: Added a new shock collar that shocks when a trigger is triggered - type: Add - - message: Two shock collars and two remote signallers added to the warden's locker - type: Add - - message: Shock collar added as a new target for the thief - type: Add - - message: A new Special Means technology has been added to the Arsenal research - branch at the 1st research level. Its research opens up the possibility of producing - electropacks at security techfab. The cost of technology research is 5000 - type: Add - id: 7114 - time: '2024-08-15T14:30:39.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30529 - author: Mervill changes: - message: The Gas Analyzer won't spuriously shut down for seemly no reason. @@ -3911,3 +3894,10 @@ id: 7613 time: '2024-11-15T23:46:02.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/31147 +- author: SaphireLattice + changes: + - message: Crayon UI now has categories and queue + type: Add + id: 7614 + time: '2024-11-16T03:25:06.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33101 From da4e63f832d0b003439f27ed3ffa5bdc4e55b1b4 Mon Sep 17 00:00:00 2001 From: Southbridge <7013162+southbridge-fur@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:26:47 -0500 Subject: [PATCH 011/218] BRB sign in the Bureaucracy Crate (#33341) Added the brb sign to the Bureaucracy Crate --- Resources/Prototypes/Catalog/Fills/Crates/service.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Catalog/Fills/Crates/service.yml b/Resources/Prototypes/Catalog/Fills/Crates/service.yml index 86623eee60b..8af7b17245d 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/service.yml @@ -135,6 +135,7 @@ - id: BoxFolderYellow - id: NewtonCradle - id: BoxEnvelope + - id: BrbSign - type: entity id: CrateServiceFaxMachine From 968ea7b89352d6147718fbe6071a221c4a3b6e80 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:27:57 +0000 Subject: [PATCH 012/218] Automatic changelog update --- Resources/Changelog/Changelog.yml | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index d456bd83a98..be145b98107 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,20 +1,4 @@ Entries: -- author: Mervill - changes: - - message: The Gas Analyzer won't spuriously shut down for seemly no reason. - type: Tweak - - message: The Gas Analyzer will always switch to the device tab when a new object - is scanned. - type: Tweak - - message: The Gas Analyzer's interaction range is now equal to the standard interaction - range - type: Fix - - message: Clicking the Gas Analyzer when it's in your hand has proper enable/disable - behavior. - type: Fix - id: 7115 - time: '2024-08-15T14:45:13.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30763 - author: Nimfar11 changes: - message: Adds a gold toilet @@ -3901,3 +3885,10 @@ id: 7614 time: '2024-11-16T03:25:06.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33101 +- author: Southbridge + changes: + - message: The BRB sign is now included in the Bureaucracy Crate + type: Add + id: 7615 + time: '2024-11-16T03:26:48.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33341 From 8e0b24b38a59576676722c73395c6a27bf024206 Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Sat, 16 Nov 2024 10:39:19 +0700 Subject: [PATCH 013/218] Fix utensils not being thrown away (#33326) --- Content.Server/Nutrition/EntitySystems/UtensilSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs b/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs index 1f3d5afb433..766c38d561b 100644 --- a/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs @@ -44,7 +44,7 @@ private void OnAfterInteract(Entity entity, ref AfterInteractE public (bool Success, bool Handled) TryUseUtensil(EntityUid user, EntityUid target, Entity utensil) { if (!EntityManager.TryGetComponent(target, out FoodComponent? food)) - return (false, true); + return (false, false); //Prevents food usage with a wrong utensil if ((food.Utensil & utensil.Comp.Types) == 0) From fda37fe8ba7f3a8cab7dc6a58905dc1724c438cb Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:40:25 +0000 Subject: [PATCH 014/218] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index be145b98107..927da179073 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,15 +1,4 @@ Entries: -- author: Nimfar11 - changes: - - message: Adds a gold toilet - type: Add - - message: Adds a target for the Thief to steal the golden toilet - type: Add - - message: Corrected the sprite image for the normal toilet. - type: Fix - id: 7116 - time: '2024-08-15T19:23:59.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31049 - author: themias changes: - message: Raw meat cutlets can be cooked on a grill @@ -3892,3 +3881,10 @@ id: 7615 time: '2024-11-16T03:26:48.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33341 +- author: SaphireLattice + changes: + - message: Utensils can finally go into disposals + type: Fix + id: 7616 + time: '2024-11-16T03:39:19.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33326 From 875ab71002fb8ac7ad5a80f2f214039053a9ac62 Mon Sep 17 00:00:00 2001 From: MossyGreySlope Date: Sat, 16 Nov 2024 13:57:33 +1000 Subject: [PATCH 015/218] Fix server crash when the seed extractor is used on the dev map (#33312) handle event when using seed extractor Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Content.Server/Botany/Systems/SeedExtractorSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Server/Botany/Systems/SeedExtractorSystem.cs b/Content.Server/Botany/Systems/SeedExtractorSystem.cs index 93f76473ff8..c7e20983a7a 100644 --- a/Content.Server/Botany/Systems/SeedExtractorSystem.cs +++ b/Content.Server/Botany/Systems/SeedExtractorSystem.cs @@ -38,6 +38,7 @@ private void OnInteractUsing(EntityUid uid, SeedExtractorComponent seedExtractor args.User, PopupType.Medium); QueueDel(args.Used); + args.Handled = true; var amount = _random.Next(seedExtractor.BaseMinSeeds, seedExtractor.BaseMaxSeeds + 1); var coords = Transform(uid).Coordinates; From 818342f39856dab0d2a1bb61209da05c5fa94fc1 Mon Sep 17 00:00:00 2001 From: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:30:47 +1200 Subject: [PATCH 016/218] Solar assembly crate buff (#33019) * more flatpacks + glass * solar crate price increase * price increase * 1250 spesos * Update Resources/Prototypes/Catalog/Fills/Crates/engines.yml --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Prototypes/Catalog/Cargo/cargo_engines.yml | 2 +- Resources/Prototypes/Catalog/Fills/Crates/engines.yml | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml b/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml index 72f9d3a59bf..75a1e24cdff 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml @@ -66,7 +66,7 @@ sprite: Objects/Devices/flatpack.rsi state: solar-assembly-part product: CrateEngineeringSolar - cost: 525 + cost: 1250 category: cargoproduct-category-name-engineering group: market diff --git a/Resources/Prototypes/Catalog/Fills/Crates/engines.yml b/Resources/Prototypes/Catalog/Fills/Crates/engines.yml index c37b7b7535a..638e94080ed 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/engines.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/engines.yml @@ -120,12 +120,14 @@ id: CrateEngineeringSolar parent: CrateEngineering name: solar assembly crate - description: Parts for constructing solar panels and trackers. + description: A kit with solar flatpacks and glass to construct ten solar panels. components: - type: StorageFill contents: - id: SolarAssemblyFlatpack - amount: 6 + amount: 10 + - id: SheetGlass10 + amount: 2 - type: entity id: CrateEngineeringShuttle From a8c6df7c60f064be9afe9cfe9411c9367a2f77b1 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 04:31:53 +0000 Subject: [PATCH 017/218] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 927da179073..ec2ae015a8a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: themias - changes: - - message: Raw meat cutlets can be cooked on a grill - type: Tweak - id: 7117 - time: '2024-08-15T19:30:09.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31048 - author: IProduceWidgets changes: - message: Meteor dust should more consistently happen instead of meteors. @@ -3888,3 +3881,12 @@ id: 7616 time: '2024-11-16T03:39:19.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33326 +- author: K-Dynamic + changes: + - message: Solar assembly crate now comes with 10 flatpacks and 20 glass to make + expansion and repairs easier, as well as increasing in price from 525 to 1250 + spesos. + type: Tweak + id: 7617 + time: '2024-11-16T04:30:48.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33019 From d13b2403b0b7730386012d3baf2027dddc8027c3 Mon Sep 17 00:00:00 2001 From: dffdff2423 Date: Sat, 16 Nov 2024 00:09:29 -0500 Subject: [PATCH 018/218] Add admin remarks button to lobby (#31761) --- Content.Client/Lobby/LobbyUIController.cs | 2 +- .../Lobby/UI/CharacterSetupGui.xaml | 6 +++++ .../Lobby/UI/CharacterSetupGui.xaml.cs | 27 +++++++++---------- Content.Client/Lobby/UI/LobbyGui.xaml.cs | 1 - Resources/Locale/en-US/lobby/lobby-gui.ftl | 2 +- .../preferences/ui/character-setup-gui.ftl | 3 ++- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Content.Client/Lobby/LobbyUIController.cs b/Content.Client/Lobby/LobbyUIController.cs index 3cf98c98aba..50a25519988 100644 --- a/Content.Client/Lobby/LobbyUIController.cs +++ b/Content.Client/Lobby/LobbyUIController.cs @@ -279,7 +279,7 @@ private void OpenSavePanel() _profileEditor.OnOpenGuidebook += _guide.OpenHelp; - _characterSetup = new CharacterSetupGui(EntityManager, _prototypeManager, _resourceCache, _preferencesManager, _profileEditor); + _characterSetup = new CharacterSetupGui(_profileEditor); _characterSetup.CloseButton.OnPressed += _ => { diff --git a/Content.Client/Lobby/UI/CharacterSetupGui.xaml b/Content.Client/Lobby/UI/CharacterSetupGui.xaml index f83be265884..c463987a1fe 100644 --- a/Content.Client/Lobby/UI/CharacterSetupGui.xaml +++ b/Content.Client/Lobby/UI/CharacterSetupGui.xaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client" xmlns:style="clr-namespace:Content.Client.Stylesheets" + xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" VerticalExpand="True"> @@ -10,10 +11,15 @@