From 620c40e087e8365e4c4741e9534467b1b1c316c7 Mon Sep 17 00:00:00 2001 From: Slava0135 <40753025+Slava0135@users.noreply.github.com> Date: Thu, 23 Mar 2023 18:54:14 +0300 Subject: [PATCH] Add explosive banana peel 2 (#14491) --- .../Components/TriggerOnSlipComponent.cs | 6 + .../Explosion/EntitySystems/TriggerSystem.cs | 7 + Content.Shared/Slippery/SlipperySystem.cs | 203 +++++++++--------- .../Locale/en-US/store/uplink-catalog.ftl | 3 + .../Prototypes/Catalog/uplink_catalog.yml | 14 ++ .../Objects/Consumable/Food/produce.yml | 19 ++ .../Specific/Hydroponics/banana.rsi/meta.json | 9 + .../Hydroponics/banana.rsi/primed.png | Bin 0 -> 940 bytes 8 files changed, 162 insertions(+), 99 deletions(-) create mode 100644 Content.Server/Explosion/Components/TriggerOnSlipComponent.cs create mode 100644 Resources/Textures/Objects/Specific/Hydroponics/banana.rsi/primed.png diff --git a/Content.Server/Explosion/Components/TriggerOnSlipComponent.cs b/Content.Server/Explosion/Components/TriggerOnSlipComponent.cs new file mode 100644 index 0000000000..da9d30240c --- /dev/null +++ b/Content.Server/Explosion/Components/TriggerOnSlipComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Server.Explosion.Components; + +[RegisterComponent] +public sealed class TriggerOnSlipComponent : Component +{ +} diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs index 965f1b6dc1..10539dd860 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.Database; using Content.Shared.Implants.Components; using Content.Shared.Interaction; using Content.Shared.Payload.Components; +using Content.Shared.Slippery; using Content.Shared.StepTrigger.Systems; using Content.Shared.Trigger; using JetBrains.Annotations; @@ -61,6 +62,7 @@ namespace Content.Server.Explosion.EntitySystems SubscribeLocalEvent(OnActivate); SubscribeLocalEvent(OnImplantTrigger); SubscribeLocalEvent(OnStepTriggered); + SubscribeLocalEvent(OnSlipTriggered); SubscribeLocalEvent(HandleDeleteTrigger); SubscribeLocalEvent(HandleExplodeTrigger); @@ -122,6 +124,11 @@ namespace Content.Server.Explosion.EntitySystems Trigger(uid, args.Tripper); } + private void OnSlipTriggered(EntityUid uid, TriggerOnSlipComponent component, ref SlipEvent args) + { + Trigger(uid, args.Slipped); + } + public bool Trigger(EntityUid trigger, EntityUid? user = null) { var triggerEvent = new TriggerEvent(trigger, user); diff --git a/Content.Shared/Slippery/SlipperySystem.cs b/Content.Shared/Slippery/SlipperySystem.cs index 276f797299..df636a38bd 100644 --- a/Content.Shared/Slippery/SlipperySystem.cs +++ b/Content.Shared/Slippery/SlipperySystem.cs @@ -11,110 +11,115 @@ using Robust.Shared.GameStates; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; -namespace Content.Shared.Slippery +namespace Content.Shared.Slippery; + +[UsedImplicitly] +public sealed class SlipperySystem : EntitySystem { - [UsedImplicitly] - public sealed class SlipperySystem : EntitySystem + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + + public override void Initialize() { - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly SharedStunSystem _stunSystem = default!; - [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!; - [Dependency] private readonly SharedContainerSystem _container = default!; - [Dependency] private readonly SharedPhysicsSystem _physics = default!; + base.Initialize(); - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(HandleAttemptCollide); - SubscribeLocalEvent(HandleStepTrigger); - SubscribeLocalEvent(OnNoSlipAttempt); - // as long as slip-resistant mice are never added, this should be fine (otherwise a mouse-hat will transfer it's power to the wearer). - SubscribeLocalEvent>((e, c, ev) => OnNoSlipAttempt(e, c, ev.Args)); - SubscribeLocalEvent(OnSlipperyGetState); - SubscribeLocalEvent(OnSlipperyHandleState); - } - - private void OnSlipperyHandleState(EntityUid uid, SlipperyComponent component, ref ComponentHandleState args) - { - if (args.Current is not SlipperyComponentState state) return; - - component.ParalyzeTime = state.ParalyzeTime; - component.LaunchForwardsMultiplier = state.LaunchForwardsMultiplier; - component.SlipSound = new SoundPathSpecifier(state.SlipSound); - } - - private void OnSlipperyGetState(EntityUid uid, SlipperyComponent component, ref ComponentGetState args) - { - args.State = new SlipperyComponentState(component.ParalyzeTime, component.LaunchForwardsMultiplier, _audio.GetSound(component.SlipSound)); - } - - private void HandleStepTrigger(EntityUid uid, SlipperyComponent component, ref StepTriggeredEvent args) - { - TrySlip(component, args.Tripper); - } - - private void HandleAttemptCollide( - EntityUid uid, - SlipperyComponent component, - ref StepTriggerAttemptEvent args) - { - args.Continue |= CanSlip(uid, args.Tripper); - } - - private static void OnNoSlipAttempt(EntityUid uid, NoSlipComponent component, SlipAttemptEvent args) - { - args.Cancel(); - } - - private bool CanSlip(EntityUid uid, EntityUid toSlip) - { - return !_container.IsEntityInContainer(uid) - && _statusEffectsSystem.CanApplyEffect(toSlip, "Stun"); //Should be KnockedDown instead? - } - - private void TrySlip(SlipperyComponent component, EntityUid other) - { - if (HasComp(other)) - return; - - var ev = new SlipAttemptEvent(); - RaiseLocalEvent(other, ev, false); - if (ev.Cancelled) - return; - - if (TryComp(other, out PhysicsComponent? physics)) - _physics.SetLinearVelocity(other, physics.LinearVelocity * component.LaunchForwardsMultiplier, body: physics); - - var playSound = !_statusEffectsSystem.HasStatusEffect(other, "KnockedDown"); - - _stunSystem.TryParalyze(other, TimeSpan.FromSeconds(component.ParalyzeTime), true); - - // Preventing from playing the slip sound when you are already knocked down. - if (playSound) - { - _audio.PlayPredicted(component.SlipSound, other, other); - } - - _adminLogger.Add(LogType.Slip, LogImpact.Low, - $"{ToPrettyString(other):mob} slipped on collision with {ToPrettyString(component.Owner):entity}"); - } - - public void CopyConstruct(EntityUid destUid, SlipperyComponent srcSlip) - { - var destEvaporation = EntityManager.EnsureComponent(destUid); - destEvaporation.SlipSound = srcSlip.SlipSound; - destEvaporation.ParalyzeTime = srcSlip.ParalyzeTime; - destEvaporation.LaunchForwardsMultiplier = srcSlip.LaunchForwardsMultiplier; - } + SubscribeLocalEvent(HandleAttemptCollide); + SubscribeLocalEvent(HandleStepTrigger); + SubscribeLocalEvent(OnNoSlipAttempt); + // as long as slip-resistant mice are never added, this should be fine (otherwise a mouse-hat will transfer it's power to the wearer). + SubscribeLocalEvent>((e, c, ev) => OnNoSlipAttempt(e, c, ev.Args)); + SubscribeLocalEvent(OnSlipperyGetState); + SubscribeLocalEvent(OnSlipperyHandleState); } - /// - /// Raised on an entity to determine if it can slip or not. - /// - public sealed class SlipAttemptEvent : CancellableEntityEventArgs, IInventoryRelayEvent + private void OnSlipperyHandleState(EntityUid uid, SlipperyComponent component, ref ComponentHandleState args) { - public SlotFlags TargetSlots { get; } = SlotFlags.FEET; + if (args.Current is not SlipperyComponentState state) return; + + component.ParalyzeTime = state.ParalyzeTime; + component.LaunchForwardsMultiplier = state.LaunchForwardsMultiplier; + component.SlipSound = new SoundPathSpecifier(state.SlipSound); + } + + private void OnSlipperyGetState(EntityUid uid, SlipperyComponent component, ref ComponentGetState args) + { + args.State = new SlipperyComponentState(component.ParalyzeTime, component.LaunchForwardsMultiplier, _audio.GetSound(component.SlipSound)); + } + + private void HandleStepTrigger(EntityUid uid, SlipperyComponent component, ref StepTriggeredEvent args) + { + TrySlip(uid, component, args.Tripper); + } + + private void HandleAttemptCollide( + EntityUid uid, + SlipperyComponent component, + ref StepTriggerAttemptEvent args) + { + args.Continue |= CanSlip(uid, args.Tripper); + } + + private static void OnNoSlipAttempt(EntityUid uid, NoSlipComponent component, SlipAttemptEvent args) + { + args.Cancel(); + } + + private bool CanSlip(EntityUid uid, EntityUid toSlip) + { + return !_container.IsEntityInContainer(uid) + && _statusEffects.CanApplyEffect(toSlip, "Stun"); //Should be KnockedDown instead? + } + + private void TrySlip(EntityUid uid, SlipperyComponent component, EntityUid other) + { + if (HasComp(other)) + return; + + var attemptEv = new SlipAttemptEvent(); + RaiseLocalEvent(other, attemptEv); + if (attemptEv.Cancelled) + return; + + var ev = new SlipEvent(other); + RaiseLocalEvent(uid, ref ev); + + if (TryComp(other, out PhysicsComponent? physics)) + _physics.SetLinearVelocity(other, physics.LinearVelocity * component.LaunchForwardsMultiplier, body: physics); + + var playSound = !_statusEffects.HasStatusEffect(other, "KnockedDown"); + + _stun.TryParalyze(other, TimeSpan.FromSeconds(component.ParalyzeTime), true); + + // Preventing from playing the slip sound when you are already knocked down. + if (playSound) + { + _audio.PlayPredicted(component.SlipSound, other, other); + } + + _adminLogger.Add(LogType.Slip, LogImpact.Low, + $"{ToPrettyString(other):mob} slipped on collision with {ToPrettyString(uid):entity}"); + } + + public void CopyConstruct(EntityUid destUid, SlipperyComponent srcSlip) + { + var destEvaporation = EntityManager.EnsureComponent(destUid); + destEvaporation.SlipSound = srcSlip.SlipSound; + destEvaporation.ParalyzeTime = srcSlip.ParalyzeTime; + destEvaporation.LaunchForwardsMultiplier = srcSlip.LaunchForwardsMultiplier; } } + +/// +/// Raised on an entity to determine if it can slip or not. +/// +public sealed class SlipAttemptEvent : CancellableEntityEventArgs, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.FEET; +} + +[ByRefEvent] +public readonly record struct SlipEvent(EntityUid Slipped); diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index 55cb414003..88e130bc19 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -151,6 +151,9 @@ uplink-necronomicon-desc = An unholy book capable of summoning a demonic familia uplink-revolver-cap-gun-fake-name = Fake Cap Gun uplink-revolver-cap-gun-fake-desc = Fool your enemy! It can use both cap and magnum bullets. Comes loaded with magnum bullets. +uplink-banana-peel-explosive-name = Explosive Banana Peel +uplink-banana-peel-explosive-desc = They will burst into laughter when they slip on it! + # Armor uplink-chameleon-name = Chameleon Kit uplink-chameleon-desc = A backpack full of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index fb638897b7..8d432087c7 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -594,6 +594,20 @@ - Mime - Clown +- type: listing + id: uplinkBananaPeelExplosive + name: uplink-banana-peel-explosive-name + description: uplink-banana-peel-explosive-desc + productEntity: TrashBananaPeelExplosive + cost: + Telecrystal: 2 + categories: + - UplinkJob + conditions: + - !type:BuyerJobCondition + whitelist: + - Clown + # Armor - type: listing diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml index baa1350196..631e9aba59 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml @@ -216,6 +216,25 @@ - type: Recyclable - type: SpaceGarbage +- type: entity + name: banana peel + suffix: Explosive + parent: TrashBananaPeel + id: TrashBananaPeelExplosive + components: + - type: Sprite + sprite: Objects/Specific/Hydroponics/banana.rsi + state: primed + - type: TriggerOnSlip + - type: ExplodeOnTrigger + - type: Explosive + explosionType: Default + maxIntensity: 2 + totalIntensity: 10 + canCreateVacuum: false + - type: DeleteOnTrigger + - type: AnimationPlayer + - type: entity name: carrot parent: FoodProduceBase diff --git a/Resources/Textures/Objects/Specific/Hydroponics/banana.rsi/meta.json b/Resources/Textures/Objects/Specific/Hydroponics/banana.rsi/meta.json index f981b7e426..88c277fde7 100644 --- a/Resources/Textures/Objects/Specific/Hydroponics/banana.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Hydroponics/banana.rsi/meta.json @@ -53,6 +53,15 @@ }, { "name": "stage-6" + }, + { + "name": "primed", + "delays": [ + [ + 4.9, + 0.1 + ] + ] } ] } diff --git a/Resources/Textures/Objects/Specific/Hydroponics/banana.rsi/primed.png b/Resources/Textures/Objects/Specific/Hydroponics/banana.rsi/primed.png new file mode 100644 index 0000000000000000000000000000000000000000..93c3e389f7121fc5f015f38b95e856e2ad7ffc89 GIT binary patch literal 940 zcmV;d15^BoP)x``7_tYyrc@UXBimn~}bdDNG{k0x(}5~euPWW?(iwJ2RvQgzW&@?0_g{?(QJ8J=^yCAh>p+Qnu~yW81Erfb$71^9}#H&3ILE%68~Fyq!VU67<|c$4V`$`Z=c$5ZjbrbOZYbFeLXqt3O;IXf#sK z@zMYQ010qNS#tmY3labT3lag+-G2N400HDlL_t(&1!G_s1*0J_8UmvsFd71*Aut*O zqai>>2>3Wy{0Ct&v{FUOK-90s``S}w;arnBo|w50QMj#_CWyv0@jc!5$@Nc=f5#b-T0a)^WmCsFlcE%Ne*mG zlKc=sZgqsKI|BWcYZX!~jHzfto?Ltr!nMnhmU1V%$(Gz3ONU^E2i83F*j3l)*|iiD^D O0000