From: Bakke Date: Thu, 4 Jan 2024 13:10:04 +0000 (+0100) Subject: Fix robusted dionas not being recoverable (#21636) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=a9b797a0917868fc888b612e59fd22d07b5f8118;p=space-station-14.git Fix robusted dionas not being recoverable (#21636) * Fix robusted dionas not being recoverable * Implement a polymorph cooldown field, used for TreeMorph Allows the polymorphed Diona some time to work off robust harvest without immediately polymorphing again. * Minor adjustment to polymorph cooldown timing * Apply suggestions from code review Co-authored-by: Kara * fix: trigger polymorph revert on destruction As suggested by mirrorcult, DamageThresholdReached is not the ideal candidate for reverting a polymorph on destruction, as there exists a DestructionEventArgs to listen for instead. --------- Co-authored-by: Kara --- diff --git a/Content.Server/Polymorph/Components/PolymorphableComponent.cs b/Content.Server/Polymorph/Components/PolymorphableComponent.cs index c05d36a842..2e9c5fee0a 100644 --- a/Content.Server/Polymorph/Components/PolymorphableComponent.cs +++ b/Content.Server/Polymorph/Components/PolymorphableComponent.cs @@ -12,6 +12,12 @@ namespace Content.Server.Polymorph.Components /// public Dictionary? PolymorphActions = null; + /// + /// Timestamp for when the most recent polymorph ended. + /// + [ViewVariables(VVAccess.ReadOnly)] + public TimeSpan? LastPolymorphEnd = null; + /// /// The polymorphs that the entity starts out being able to do. /// diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs index 5b8a7b7165..4d3bbcdf78 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs @@ -7,6 +7,7 @@ using Content.Server.Polymorph.Components; using Content.Shared.Actions; using Content.Shared.Buckle; using Content.Shared.Damage; +using Content.Shared.Destructible; using Content.Shared.Hands.EntitySystems; using Content.Shared.IdentityManagement; using Content.Shared.Mind; @@ -20,6 +21,7 @@ using Robust.Server.Containers; using Robust.Server.GameObjects; using Robust.Shared.Map; using Robust.Shared.Prototypes; +using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Server.Polymorph.Systems @@ -44,6 +46,7 @@ namespace Content.Server.Polymorph.Systems [Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly SharedMindSystem _mindSystem = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; private ISawmill _sawmill = default!; @@ -59,6 +62,7 @@ namespace Content.Server.Polymorph.Systems SubscribeLocalEvent(OnBeforeFullyEaten); SubscribeLocalEvent(OnBeforeFullySliced); SubscribeLocalEvent(OnRevertPolymorphActionEvent); + SubscribeLocalEvent(OnDestruction); InitializeCollide(); InitializeMap(); @@ -122,6 +126,24 @@ namespace Content.Server.Polymorph.Systems } } + /// + /// It is possible to be polymorphed into an entity that can't "die", but is instead + /// destroyed. This handler ensures that destruction is treated like death. + /// + private void OnDestruction(EntityUid uid, PolymorphedEntityComponent comp, DestructionEventArgs args) + { + if (!_proto.TryIndex(comp.Prototype, out var proto)) + { + _sawmill.Error($"Invalid polymorph prototype {comp.Prototype}"); + return; + } + + if (proto.RevertOnDeath) + { + Revert(uid, comp); + } + } + private void OnBeforeFullySliced(EntityUid uid, PolymorphedEntityComponent comp, BeforeFullySlicedEvent args) { if (!_proto.TryIndex(comp.Prototype, out var proto)) @@ -164,6 +186,13 @@ namespace Content.Server.Polymorph.Systems if (!proto.AllowRepeatedMorphs && HasComp(uid)) return null; + // If this polymorph has a cooldown, check if that amount of time has passed since the + // last polymorph ended. + if (TryComp(uid, out var polymorphableComponent) && + polymorphableComponent.LastPolymorphEnd != null && + _gameTiming.CurTime < polymorphableComponent.LastPolymorphEnd + proto.Cooldown) + return null; + // mostly just for vehicles _buckle.TryUnbuckle(uid, uid, true); @@ -302,6 +331,9 @@ namespace Content.Server.Polymorph.Systems if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) _mindSystem.TransferTo(mindId, parent, mind: mind); + if (TryComp(parent, out var polymorphableComponent)) + polymorphableComponent.LastPolymorphEnd = _gameTiming.CurTime; + // if an item polymorph was picked up, put it back down after reverting Transform(parent).AttachToGridOrMap(); diff --git a/Content.Shared/Polymorph/PolymorphPrototype.cs b/Content.Shared/Polymorph/PolymorphPrototype.cs index 75c6d58d24..f093489b04 100644 --- a/Content.Shared/Polymorph/PolymorphPrototype.cs +++ b/Content.Shared/Polymorph/PolymorphPrototype.cs @@ -97,6 +97,14 @@ namespace Content.Shared.Polymorph [DataField("allowRepeatedMorphs", serverOnly: true)] public bool AllowRepeatedMorphs = false; + + /// + /// The amount of time that should pass after this polymorph has ended, before a new one + /// can occur. + /// + [DataField("cooldown", serverOnly: true)] + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan Cooldown = TimeSpan.Zero; } public enum PolymorphInventoryChange : byte diff --git a/Resources/Prototypes/Polymorphs/polymorph.yml b/Resources/Prototypes/Polymorphs/polymorph.yml index 8593c2194d..46590248ae 100644 --- a/Resources/Prototypes/Polymorphs/polymorph.yml +++ b/Resources/Prototypes/Polymorphs/polymorph.yml @@ -101,7 +101,8 @@ forced: true transferName: true revertOnDeath: true - + inventory: Drop + cooldown: 160 # this is the monkey polymorph for artifact. - type: polymorph