From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:17:02 +0000 (-0400) Subject: Cleanups PolymorphSystem/Components/Prototypes (#23721) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=b8f0ed3975a4b887ca8dd75dcc07e0ac5ee11646;p=space-station-14.git Cleanups PolymorphSystem/Components/Prototypes (#23721) * Cleanups PolymorphSystem * forgot this * Nah * Fix test --------- Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> --- diff --git a/Content.Server/Administration/Commands/AddPolymorphActionCommand.cs b/Content.Server/Administration/Commands/AddPolymorphActionCommand.cs index 6223df7a6c..b92cbfc0de 100644 --- a/Content.Server/Administration/Commands/AddPolymorphActionCommand.cs +++ b/Content.Server/Administration/Commands/AddPolymorphActionCommand.cs @@ -32,7 +32,7 @@ public sealed class AddPolymorphActionCommand : IConsoleCommand var polySystem = _entityManager.EntitySysManager.GetEntitySystem(); - _entityManager.EnsureComponent(entityUid.Value); - polySystem.CreatePolymorphAction(args[1], entityUid.Value); + var polymorphable = _entityManager.EnsureComponent(entityUid.Value); + polySystem.CreatePolymorphAction(args[1], (entityUid.Value, polymorphable)); } } diff --git a/Content.Server/Chemistry/ReagentEffects/Polymorph.cs b/Content.Server/Chemistry/ReagentEffects/Polymorph.cs index 569da51e39..fea372125e 100644 --- a/Content.Server/Chemistry/ReagentEffects/Polymorph.cs +++ b/Content.Server/Chemistry/ReagentEffects/Polymorph.cs @@ -18,7 +18,7 @@ public sealed partial class Polymorph : ReagentEffect protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-make-polymorph", ("chance", Probability), ("entityname", - prototype.Index(prototype.Index(PolymorphPrototype).Entity).Name)); + prototype.Index(prototype.Index(PolymorphPrototype).Configuration.Entity).Name)); public override void Effect(ReagentEffectArgs args) { diff --git a/Content.Server/Polymorph/Components/PolymorphOnCollideComponent.cs b/Content.Server/Polymorph/Components/PolymorphOnCollideComponent.cs index 5d513df933..577dadb5c8 100644 --- a/Content.Server/Polymorph/Components/PolymorphOnCollideComponent.cs +++ b/Content.Server/Polymorph/Components/PolymorphOnCollideComponent.cs @@ -1,21 +1,24 @@ +using Content.Server.Polymorph.Systems; using Content.Shared.Polymorph; using Content.Shared.Whitelist; using Robust.Shared.Audio; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Prototypes; namespace Content.Server.Polymorph.Components; [RegisterComponent] +[Access(typeof(PolymorphSystem))] public sealed partial class PolymorphOnCollideComponent : Component { - [DataField("polymorph", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] - public string Polymorph = default!; + [DataField(required: true)] + public ProtoId Polymorph; - [DataField("whitelist", required: true)] + [DataField(required: true)] public EntityWhitelist Whitelist = default!; - [DataField("blacklist")] + [DataField] public EntityWhitelist? Blacklist; + [DataField] public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg"); } diff --git a/Content.Server/Polymorph/Components/PolymorphableComponent.cs b/Content.Server/Polymorph/Components/PolymorphableComponent.cs index 2e9c5fee0a..d28aa5a4fb 100644 --- a/Content.Server/Polymorph/Components/PolymorphableComponent.cs +++ b/Content.Server/Polymorph/Components/PolymorphableComponent.cs @@ -1,27 +1,28 @@ +using Content.Server.Polymorph.Systems; using Content.Shared.Polymorph; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; -namespace Content.Server.Polymorph.Components +namespace Content.Server.Polymorph.Components; + +[RegisterComponent] +[Access(typeof(PolymorphSystem))] +public sealed partial class PolymorphableComponent : Component { - [RegisterComponent] - public sealed partial class PolymorphableComponent : Component - { - /// - /// A list of all the polymorphs that the entity has. - /// Used to manage them and remove them if needed. - /// - public Dictionary? PolymorphActions = null; + /// + /// A list of all the polymorphs that the entity has. + /// Used to manage them and remove them if needed. + /// + public Dictionary, EntityUid>? PolymorphActions = null; - /// - /// Timestamp for when the most recent polymorph ended. - /// - [ViewVariables(VVAccess.ReadOnly)] - public TimeSpan? LastPolymorphEnd = 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. - /// - [DataField("innatePolymorphs", customTypeSerializer : typeof(PrototypeIdListSerializer))] - public List? InnatePolymorphs; - } + /// The polymorphs that the entity starts out being able to do. + /// + [DataField] + public List>? InnatePolymorphs; } diff --git a/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs b/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs index c155c538d1..7620203a86 100644 --- a/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs +++ b/Content.Server/Polymorph/Components/PolymorphedEntityComponent.cs @@ -1,31 +1,32 @@ +using Content.Server.Polymorph.Systems; using Content.Shared.Polymorph; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.Polymorph.Components +namespace Content.Server.Polymorph.Components; + +[RegisterComponent] +[Access(typeof(PolymorphSystem))] +public sealed partial class PolymorphedEntityComponent : Component { - [RegisterComponent] - public sealed partial class PolymorphedEntityComponent : Component - { - /// - /// The polymorph prototype, used to track various information - /// about the polymorph - /// - [DataField("prototype", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] - public string Prototype = string.Empty; + /// + /// The polymorph prototype, used to track various information + /// about the polymorph + /// + [DataField(required: true)] + public PolymorphConfiguration Configuration = new(); - /// - /// The original entity that the player will revert back into - /// - [DataField("parent", required: true)] - public EntityUid Parent; + /// + /// The original entity that the player will revert back into + /// + [DataField(required: true)] + public EntityUid Parent; - /// - /// The amount of time that has passed since the entity was created - /// used for tracking the duration - /// - [DataField("time")] - public float Time; + /// + /// The amount of time that has passed since the entity was created + /// used for tracking the duration + /// + [DataField] + public float Time; - [DataField] public EntityUid? Action; - } + [DataField] + public EntityUid? Action; } diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs index 46b962b20e..b4240d409a 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.Collide.cs @@ -1,16 +1,25 @@ using Content.Server.Polymorph.Components; +using Content.Shared.Polymorph; using Content.Shared.Projectiles; using Robust.Shared.Audio; using Robust.Shared.Physics.Events; +using Robust.Shared.Prototypes; namespace Content.Server.Polymorph.Systems; public partial class PolymorphSystem { - // Need to do this so we don't get a collection enumeration error in physics by polymorphing - // an entity we're colliding with + /// + /// Need to do this so we don't get a collection enumeration error in physics by polymorphing + /// an entity we're colliding with + /// private Queue _queuedPolymorphUpdates = new(); + private void InitializeCollide() + { + SubscribeLocalEvent(OnPolymorphCollide); + } + public void UpdateCollide() { while (_queuedPolymorphUpdates.TryDequeue(out var data)) @@ -20,25 +29,18 @@ public partial class PolymorphSystem var ent = PolymorphEntity(data.Ent, data.Polymorph); if (ent != null) - { _audio.PlayPvs(data.Sound, ent.Value); - } } } - private void InitializeCollide() - { - SubscribeLocalEvent(OnPolymorphCollide); - } - private void OnPolymorphCollide(EntityUid uid, PolymorphOnCollideComponent component, ref StartCollideEvent args) { if (args.OurFixtureId != SharedProjectileSystem.ProjectileFixture) return; var other = args.OtherEntity; - if (!component.Whitelist.IsValid(other) - || component.Blacklist != null && component.Blacklist.IsValid(other)) + if (!component.Whitelist.IsValid(other, EntityManager) + || component.Blacklist != null && component.Blacklist.IsValid(other, EntityManager)) return; _queuedPolymorphUpdates.Enqueue(new (other, component.Sound, component.Polymorph)); @@ -49,9 +51,9 @@ public struct PolymorphQueuedData { public EntityUid Ent; public SoundSpecifier Sound; - public string Polymorph; + public ProtoId Polymorph; - public PolymorphQueuedData(EntityUid ent, SoundSpecifier sound, string polymorph) + public PolymorphQueuedData(EntityUid ent, SoundSpecifier sound, ProtoId polymorph) { Ent = ent; Sound = sound; diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs index a6f658524d..120e04eeb0 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs @@ -1,39 +1,38 @@ using Content.Shared.GameTicking; -namespace Content.Server.Polymorph.Systems +namespace Content.Server.Polymorph.Systems; + +public sealed partial class PolymorphSystem { - public sealed partial class PolymorphSystem - { - public EntityUid? PausedMap { get; private set; } + public EntityUid? PausedMap { get; private set; } - /// - /// Used to subscribe to the round restart event - /// - private void InitializeMap() - { - SubscribeLocalEvent(OnRoundRestart); - } + /// + /// Used to subscribe to the round restart event + /// + private void InitializeMap() + { + SubscribeLocalEvent(OnRoundRestart); + } - private void OnRoundRestart(RoundRestartCleanupEvent _) - { - if (PausedMap == null || !Exists(PausedMap)) - return; + private void OnRoundRestart(RoundRestartCleanupEvent _) + { + if (PausedMap == null || !Exists(PausedMap)) + return; - EntityManager.DeleteEntity(PausedMap.Value); - } + Del(PausedMap.Value); + } - /// - /// Used internally to ensure a paused map that is - /// stores polymorphed entities. - /// - private void EnsurePausesdMap() - { - if (PausedMap != null && Exists(PausedMap)) - return; + /// + /// Used internally to ensure a paused map that is + /// stores polymorphed entities. + /// + private void EnsurePausedMap() + { + if (PausedMap != null && Exists(PausedMap)) + return; - var newmap = _mapManager.CreateMap(); - _mapManager.SetMapPaused(newmap, true); - PausedMap = _mapManager.GetMapEntityId(newmap); - } + var newmap = _mapManager.CreateMap(); + _mapManager.SetMapPaused(newmap, true); + PausedMap = _mapManager.GetMapEntityId(newmap); } } diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs index 4d3bbcdf78..66dc9dab99 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs @@ -15,7 +15,6 @@ using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Polymorph; using Content.Shared.Popups; -using JetBrains.Annotations; using Robust.Server.Audio; using Robust.Server.Containers; using Robust.Server.GameObjects; @@ -24,410 +23,359 @@ using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Utility; -namespace Content.Server.Polymorph.Systems +namespace Content.Server.Polymorph.Systems; + +public sealed partial class PolymorphSystem : EntitySystem { - public sealed partial class PolymorphSystem : EntitySystem + [Dependency] private readonly IComponentFactory _compFact = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly ActionsSystem _actions = default!; + [Dependency] private readonly ActionContainerSystem _actionContainer = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly SharedBuckleSystem _buckle = default!; + [Dependency] private readonly ContainerSystem _container = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly HumanoidAppearanceSystem _humanoid = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; + [Dependency] private readonly ServerInventorySystem _inventory = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly SharedMindSystem _mindSystem = default!; + [Dependency] private readonly MetaDataSystem _metaData = default!; + + private const string RevertPolymorphId = "ActionRevertPolymorph"; + + public override void Initialize() { - [Dependency] private readonly IComponentFactory _compFact = default!; - [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly IPrototypeManager _proto = default!; - [Dependency] private readonly ActionsSystem _actions = default!; - [Dependency] private readonly ActionContainerSystem _actionContainer = default!; - [Dependency] private readonly AudioSystem _audio = default!; - [Dependency] private readonly SharedBuckleSystem _buckle = default!; - [Dependency] private readonly ContainerSystem _container = default!; - [Dependency] private readonly DamageableSystem _damageable = default!; - [Dependency] private readonly HumanoidAppearanceSystem _humanoid = default!; - [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; - [Dependency] private readonly ServerInventorySystem _inventory = default!; - [Dependency] private readonly SharedHandsSystem _hands = default!; - [Dependency] private readonly SharedPopupSystem _popup = default!; - [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!; - - private const string RevertPolymorphId = "ActionRevertPolymorph"; - - public override void Initialize() - { - base.Initialize(); + SubscribeLocalEvent(OnComponentStartup); + SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnPolymorphActionEvent); - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnBeforeFullyEaten); - SubscribeLocalEvent(OnBeforeFullySliced); - SubscribeLocalEvent(OnRevertPolymorphActionEvent); - SubscribeLocalEvent(OnDestruction); + SubscribeLocalEvent(OnPolymorphActionEvent); + SubscribeLocalEvent(OnRevertPolymorphActionEvent); - InitializeCollide(); - InitializeMap(); - - _sawmill = Logger.GetSawmill("polymorph"); - } + SubscribeLocalEvent(OnBeforeFullyEaten); + SubscribeLocalEvent(OnBeforeFullySliced); + SubscribeLocalEvent(OnDestruction); - private void OnStartup(EntityUid uid, PolymorphableComponent component, ComponentStartup args) - { - if (component.InnatePolymorphs != null) - { - foreach (var morph in component.InnatePolymorphs) - { - CreatePolymorphAction(morph, uid); - } - } - } + InitializeCollide(); + InitializeMap(); + } - private void OnPolymorphActionEvent(EntityUid uid, PolymorphableComponent component, PolymorphActionEvent args) - { - PolymorphEntity(uid, args.Prototype); - } + public override void Update(float frameTime) + { + base.Update(frameTime); - private void OnRevertPolymorphActionEvent(EntityUid uid, PolymorphedEntityComponent component, RevertPolymorphActionEvent args) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) { - Revert(uid, component); - } + comp.Time += frameTime; - private void OnMapInit(EntityUid uid, PolymorphedEntityComponent component, MapInitEvent args) - { - if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto)) + if (comp.Configuration.Duration != null && comp.Time >= comp.Configuration.Duration) { - // warning instead of error because of the all-comps one entity test. - _sawmill.Warning($"{nameof(PolymorphSystem)} encountered an improperly set up polymorph component while initializing. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}"); - RemCompDeferred(uid, component); - return; + Revert((uid, comp)); + continue; } - if (proto.Forced) - return; + if (!TryComp(uid, out var mob)) + continue; - if (_actions.AddAction(uid, ref component.Action, out var action, RevertPolymorphId)) + if (comp.Configuration.RevertOnDeath && _mobState.IsDead(uid, mob) || + comp.Configuration.RevertOnCrit && _mobState.IsIncapacitated(uid, mob)) { - action.EntityIcon = component.Parent; - action.UseDelay = TimeSpan.FromSeconds(proto.Delay); + Revert((uid, comp)); } } - private void OnBeforeFullyEaten(EntityUid uid, PolymorphedEntityComponent comp, BeforeFullyEatenEvent args) - { - if (!_proto.TryIndex(comp.Prototype, out var proto)) - { - _sawmill.Error($"Invalid polymorph prototype {comp.Prototype}"); - return; - } + UpdateCollide(); + } - if (proto.RevertOnEat) + private void OnComponentStartup(Entity ent, ref ComponentStartup args) + { + if (ent.Comp.InnatePolymorphs != null) + { + foreach (var morph in ent.Comp.InnatePolymorphs) { - args.Cancel(); - Revert(uid, comp); + CreatePolymorphAction(morph, ent); } } + } - /// - /// 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; - } + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + var (uid, component) = ent; + if (component.Configuration.Forced) + return; - if (proto.RevertOnDeath) - { - Revert(uid, comp); - } + if (_actions.AddAction(uid, ref component.Action, out var action, RevertPolymorphId)) + { + action.EntityIcon = component.Parent; + action.UseDelay = TimeSpan.FromSeconds(component.Configuration.Delay); } + } - private void OnBeforeFullySliced(EntityUid uid, PolymorphedEntityComponent comp, BeforeFullySlicedEvent args) - { - if (!_proto.TryIndex(comp.Prototype, out var proto)) - { - _sawmill.Error("Invalid polymorph prototype {comp.Prototype}"); - return; - } + private void OnPolymorphActionEvent(Entity ent, ref PolymorphActionEvent args) + { + PolymorphEntity(ent, args.Prototype.Configuration); + } - if (proto.RevertOnEat) - { - args.Cancel(); - Revert(uid, comp); - } - } + private void OnRevertPolymorphActionEvent(Entity ent, + ref RevertPolymorphActionEvent args) + { + Revert((ent, ent)); + } - /// - /// Polymorphs the target entity into the specific polymorph prototype - /// - /// The entity that will be transformed - /// The id of the polymorph prototype - public EntityUid? PolymorphEntity(EntityUid target, string id) + private void OnBeforeFullyEaten(Entity ent, ref BeforeFullyEatenEvent args) + { + var (_, comp) = ent; + if (comp.Configuration.RevertOnEat) { - if (!_proto.TryIndex(id, out var proto)) - { - _sawmill.Error("Invalid polymorph prototype {id}"); - return null; - } + args.Cancel(); + Revert((ent, ent)); + } + } - return PolymorphEntity(target, proto); + private void OnBeforeFullySliced(Entity ent, ref BeforeFullySlicedEvent args) + { + var (_, comp) = ent; + if (comp.Configuration.RevertOnEat) + { + args.Cancel(); + Revert((ent, ent)); } + } - /// - /// Polymorphs the target entity into the specific polymorph prototype - /// - /// The entity that will be transformed - /// The polymorph prototype - public EntityUid? PolymorphEntity(EntityUid uid, PolymorphPrototype proto) + /// + /// 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(Entity ent, ref DestructionEventArgs args) + { + if (ent.Comp.Configuration.RevertOnDeath) { - // if it's already morphed, don't allow it again with this condition active. - if (!proto.AllowRepeatedMorphs && HasComp(uid)) - return null; + Revert((ent, ent)); + } + } - // 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; + /// + /// Polymorphs the target entity into the specific polymorph prototype + /// + /// The entity that will be transformed + /// The id of the polymorph prototype + public EntityUid? PolymorphEntity(EntityUid uid, ProtoId protoId) + { + var config = _proto.Index(protoId).Configuration; + return PolymorphEntity(uid, config); + } - // mostly just for vehicles - _buckle.TryUnbuckle(uid, uid, true); + /// + /// Polymorphs the target entity into another + /// + /// The entity that will be transformed + /// Polymorph data + /// + public EntityUid? PolymorphEntity(EntityUid uid, PolymorphConfiguration configuration) + { + // if it's already morphed, don't allow it again with this condition active. + if (!configuration.AllowRepeatedMorphs && HasComp(uid)) + return null; - var targetTransformComp = Transform(uid); + // 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 + configuration.Cooldown) + return null; - var child = Spawn(proto.Entity, targetTransformComp.Coordinates); - MakeSentientCommand.MakeSentient(child, EntityManager); + // mostly just for vehicles + _buckle.TryUnbuckle(uid, uid, true); - var comp = _compFact.GetComponent(); - comp.Parent = uid; - comp.Prototype = proto.ID; - AddComp(child, comp); + var targetTransformComp = Transform(uid); - var childXform = Transform(child); - childXform.LocalRotation = targetTransformComp.LocalRotation; + var child = Spawn(configuration.Entity, targetTransformComp.Coordinates); - if (_container.TryGetContainingContainer(uid, out var cont)) - _container.Insert(child, cont); + MakeSentientCommand.MakeSentient(child, EntityManager); - //Transfers all damage from the original to the new one - if (proto.TransferDamage && - TryComp(child, out var damageParent) && - _mobThreshold.GetScaledDamage(uid, child, out var damage) && - damage != null) - { - _damageable.SetDamage(child, damageParent, damage); - } + var polymorphedComp = _compFact.GetComponent(); + polymorphedComp.Parent = uid; + polymorphedComp.Configuration = configuration; + AddComp(child, polymorphedComp); + + var childXform = Transform(child); + _transform.SetLocalRotation(child, targetTransformComp.LocalRotation, childXform); + + if (_container.TryGetContainingContainer(uid, out var cont)) + _container.Insert(child, cont); + + //Transfers all damage from the original to the new one + if (configuration.TransferDamage && + TryComp(child, out var damageParent) && + _mobThreshold.GetScaledDamage(uid, child, out var damage) && + damage != null) + { + _damageable.SetDamage(child, damageParent, damage); + } - if (proto.Inventory == PolymorphInventoryChange.Transfer) + if (configuration.Inventory == PolymorphInventoryChange.Transfer) + { + _inventory.TransferEntityInventories(uid, child); + foreach (var hand in _hands.EnumerateHeld(uid)) { - _inventory.TransferEntityInventories(uid, child); - foreach (var hand in _hands.EnumerateHeld(uid)) - { - _hands.TryDrop(uid, hand, checkActionBlocker: false); - _hands.TryPickupAnyHand(child, hand); - } + _hands.TryDrop(uid, hand, checkActionBlocker: false); + _hands.TryPickupAnyHand(child, hand); } - else if (proto.Inventory == PolymorphInventoryChange.Drop) + } + else if (configuration.Inventory == PolymorphInventoryChange.Drop) + { + if (_inventory.TryGetContainerSlotEnumerator(uid, out var enumerator)) { - if (_inventory.TryGetContainerSlotEnumerator(uid, out var enumerator)) - { - while (enumerator.MoveNext(out var slot)) - { - _inventory.TryUnequip(uid, slot.ID, true, true); - } - } - - foreach (var held in _hands.EnumerateHeld(uid)) + while (enumerator.MoveNext(out var slot)) { - _hands.TryDrop(uid, held); + _inventory.TryUnequip(uid, slot.ID, true, true); } } - if (proto.TransferName && TryComp(uid, out var targetMeta)) - _metaData.SetEntityName(child, targetMeta.EntityName); - - if (proto.TransferHumanoidAppearance) + foreach (var held in _hands.EnumerateHeld(uid)) { - _humanoid.CloneAppearance(uid, child); + _hands.TryDrop(uid, held); } + } - if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) - _mindSystem.TransferTo(mindId, child, mind: mind); - - //Ensures a map to banish the entity to - EnsurePausesdMap(); - if (PausedMap != null) - _transform.SetParent(uid, targetTransformComp, PausedMap.Value); + if (configuration.TransferName && TryComp(uid, out var targetMeta)) + _metaData.SetEntityName(child, targetMeta.EntityName); - return child; + if (configuration.TransferHumanoidAppearance) + { + _humanoid.CloneAppearance(uid, child); } - /// - /// Reverts a polymorphed entity back into its original form - /// - /// The entityuid of the entity being reverted - /// - public EntityUid? Revert(EntityUid uid, PolymorphedEntityComponent? component = null) - { - if (Deleted(uid)) - return null; + if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) + _mindSystem.TransferTo(mindId, child, mind: mind); - if (!Resolve(uid, ref component)) - return null; + //Ensures a map to banish the entity to + EnsurePausedMap(); + if (PausedMap != null) + _transform.SetParent(uid, targetTransformComp, PausedMap.Value); - var parent = component.Parent; - if (Deleted(parent)) - return null; + return child; + } - if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto)) - { - _sawmill.Error($"{nameof(PolymorphSystem)} encountered an improperly initialized polymorph component while reverting. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}"); - return null; - } + /// + /// Reverts a polymorphed entity back into its original form + /// + /// The entityuid of the entity being reverted + /// + public EntityUid? Revert(Entity ent) + { + var (uid, component) = ent; + if (!Resolve(ent, ref component)) + return null; - var uidXform = Transform(uid); - var parentXform = Transform(parent); + if (Deleted(uid)) + return null; - _transform.SetParent(parent, parentXform, uidXform.ParentUid); - parentXform.Coordinates = uidXform.Coordinates; - parentXform.LocalRotation = uidXform.LocalRotation; + var parent = component.Parent; + if (Deleted(parent)) + return null; - if (proto.TransferDamage && - TryComp(parent, out var damageParent) && - _mobThreshold.GetScaledDamage(uid, parent, out var damage) && - damage != null) - { - _damageable.SetDamage(parent, damageParent, damage); - } + var uidXform = Transform(uid); + var parentXform = Transform(parent); + + _transform.SetParent(parent, parentXform, uidXform.ParentUid); + _transform.SetCoordinates(parent, parentXform, uidXform.Coordinates, uidXform.LocalRotation); - if (proto.Inventory == PolymorphInventoryChange.Transfer) + if (component.Configuration.TransferDamage && + TryComp(parent, out var damageParent) && + _mobThreshold.GetScaledDamage(uid, parent, out var damage) && + damage != null) + { + _damageable.SetDamage(parent, damageParent, damage); + } + + if (component.Configuration.Inventory == PolymorphInventoryChange.Transfer) + { + _inventory.TransferEntityInventories(uid, parent); + foreach (var held in _hands.EnumerateHeld(uid)) { - _inventory.TransferEntityInventories(uid, parent); - foreach (var held in _hands.EnumerateHeld(uid)) - { - _hands.TryDrop(uid, held); - _hands.TryPickupAnyHand(parent, held, checkActionBlocker: false); - } + _hands.TryDrop(uid, held); + _hands.TryPickupAnyHand(parent, held, checkActionBlocker: false); } - else if (proto.Inventory == PolymorphInventoryChange.Drop) + } + else if (component.Configuration.Inventory == PolymorphInventoryChange.Drop) + { + if (_inventory.TryGetContainerSlotEnumerator(uid, out var enumerator)) { - if (_inventory.TryGetContainerSlotEnumerator(uid, out var enumerator)) - { - while (enumerator.MoveNext(out var slot)) - { - _inventory.TryUnequip(uid, slot.ID); - } - } - - foreach (var held in _hands.EnumerateHeld(uid)) + while (enumerator.MoveNext(out var slot)) { - _hands.TryDrop(uid, held); + _inventory.TryUnequip(uid, slot.ID); } } - 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(); - - _popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic", - ("parent", Identity.Entity(uid, EntityManager)), - ("child", Identity.Entity(parent, EntityManager))), - parent); - QueueDel(uid); - - return parent; - } - - /// - /// Creates a sidebar action for an entity to be able to polymorph at will - /// - /// The string of the id of the polymorph action - /// The entity that will be gaining the action - public void CreatePolymorphAction(string id, EntityUid target) - { - if (!_proto.TryIndex(id, out var polyproto)) + foreach (var held in _hands.EnumerateHeld(uid)) { - _sawmill.Error("Invalid polymorph prototype"); - return; + _hands.TryDrop(uid, held); } + } - if (!TryComp(target, out var polycomp)) - return; - - polycomp.PolymorphActions ??= new Dictionary(); - if (polycomp.PolymorphActions.ContainsKey(id)) - return; + if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) + _mindSystem.TransferTo(mindId, parent, mind: mind); - var entproto = _proto.Index(polyproto.Entity); + if (TryComp(parent, out var polymorphableComponent)) + polymorphableComponent.LastPolymorphEnd = _gameTiming.CurTime; - EntityUid? actionId = default!; - if (!_actions.AddAction(target, ref actionId, RevertPolymorphId, target)) - return; + // if an item polymorph was picked up, put it back down after reverting + _transform.AttachToGridOrMap(parent, parentXform); - polycomp.PolymorphActions.Add(id, actionId.Value); - _metaData.SetEntityName(actionId.Value, Loc.GetString("polymorph-self-action-name", ("target", entproto.Name))); - _metaData.SetEntityDescription(actionId.Value, Loc.GetString("polymorph-self-action-description", ("target", entproto.Name))); + _popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic", + ("parent", Identity.Entity(uid, EntityManager)), + ("child", Identity.Entity(parent, EntityManager))), + parent); + QueueDel(uid); - if (!_actions.TryGetActionData(actionId, out var baseAction)) - return; + return parent; + } - baseAction.Icon = new SpriteSpecifier.EntityPrototype(polyproto.Entity); - if (baseAction is InstantActionComponent action) - action.Event = new PolymorphActionEvent { Prototype = polyproto }; - } + /// + /// Creates a sidebar action for an entity to be able to polymorph at will + /// + /// The string of the id of the polymorph action + /// The entity that will be gaining the action + public void CreatePolymorphAction(ProtoId id, Entity target) + { + target.Comp.PolymorphActions ??= new(); + if (target.Comp.PolymorphActions.ContainsKey(id)) + return; - [PublicAPI] - public void RemovePolymorphAction(string id, EntityUid target, PolymorphableComponent? component = null) - { - if (!Resolve(target, ref component, false)) - return; - if (component.PolymorphActions == null) - return; - if (component.PolymorphActions.TryGetValue(id, out var val)) - _actions.RemoveAction(target, val); - } + var polyProto = _proto.Index(id); + var entProto = _proto.Index(polyProto.Configuration.Entity); - public override void Update(float frameTime) - { - base.Update(frameTime); + EntityUid? actionId = default!; + if (!_actions.AddAction(target, ref actionId, RevertPolymorphId, target)) + return; - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var comp)) - { - comp.Time += frameTime; + target.Comp.PolymorphActions.Add(id, actionId.Value); - if (!_proto.TryIndex(comp.Prototype, out PolymorphPrototype? proto)) - { - _sawmill.Error($"{nameof(PolymorphSystem)} encountered an improperly initialized polymorph component while updating. Entity {ToPrettyString(uid)}. Prototype: {comp.Prototype}"); - RemCompDeferred(uid, comp); - continue; - } + var metaDataCache = MetaData(actionId.Value); + _metaData.SetEntityName(actionId.Value, Loc.GetString("polymorph-self-action-name", ("target", entProto.Name)), metaDataCache); + _metaData.SetEntityDescription(actionId.Value, Loc.GetString("polymorph-self-action-description", ("target", entProto.Name)), metaDataCache); - if (proto.Duration != null && comp.Time >= proto.Duration) - { - Revert(uid, comp); - continue; - } + if (!_actions.TryGetActionData(actionId, out var baseAction)) + return; - if (!TryComp(uid, out var mob)) - continue; + baseAction.Icon = new SpriteSpecifier.EntityPrototype(polyProto.Configuration.Entity); + if (baseAction is InstantActionComponent action) + action.Event = new PolymorphActionEvent(prototype: polyProto); + } - if (proto.RevertOnDeath && _mobState.IsDead(uid, mob) || - proto.RevertOnCrit && _mobState.IsIncapacitated(uid, mob)) - { - Revert(uid, comp); - } - } + public void RemovePolymorphAction(ProtoId id, Entity target) + { + if (target.Comp.PolymorphActions == null) + return; - UpdateCollide(); - } + if (target.Comp.PolymorphActions.TryGetValue(id, out var val)) + _actions.RemoveAction(target, val); } } diff --git a/Content.Server/Polymorph/Toolshed/PolymorphCommand.cs b/Content.Server/Polymorph/Toolshed/PolymorphCommand.cs index e1eca01aa3..f741c24571 100644 --- a/Content.Server/Polymorph/Toolshed/PolymorphCommand.cs +++ b/Content.Server/Polymorph/Toolshed/PolymorphCommand.cs @@ -24,7 +24,7 @@ public sealed class PolymorphCommand : ToolshedCommand { _system ??= GetSys(); - return _system.PolymorphEntity(input, prototype.Value); + return _system.PolymorphEntity(input, prototype.Value.Configuration); } [CommandImplementation] diff --git a/Content.Server/Polymorph/Toolshed/UnpolymorphCommand.cs b/Content.Server/Polymorph/Toolshed/UnpolymorphCommand.cs index 1f3117fe67..54ebf1b577 100644 --- a/Content.Server/Polymorph/Toolshed/UnpolymorphCommand.cs +++ b/Content.Server/Polymorph/Toolshed/UnpolymorphCommand.cs @@ -2,9 +2,7 @@ using Content.Server.Administration; using Content.Server.Polymorph.Systems; using Content.Shared.Administration; -using Content.Shared.Polymorph; using Robust.Shared.Toolshed; -using Robust.Shared.Toolshed.TypeParsers; namespace Content.Server.Polymorph.Toolshed; diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/PolyArtifactComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/PolyOthersArtifactComponent.cs similarity index 81% rename from Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/PolyArtifactComponent.cs rename to Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/PolyOthersArtifactComponent.cs index 8edeb77a67..2611d78b08 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/PolyArtifactComponent.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/PolyOthersArtifactComponent.cs @@ -1,3 +1,4 @@ +using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems; using Robust.Shared.Audio; using Content.Shared.Polymorph; using Robust.Shared.Prototypes; @@ -8,7 +9,8 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; /// Artifact polymorphs surrounding entities when triggered. /// [RegisterComponent] -public sealed partial class PolyArtifactComponent : Component +[Access(typeof(PolyOthersArtifactSystem))] +public sealed partial class PolyOthersArtifactComponent : Component { /// /// The polymorph effect to trigger. diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/PolyArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/PolyOthersArtifactSystem.cs similarity index 68% rename from Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/PolyArtifactSystem.cs rename to Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/PolyOthersArtifactSystem.cs index 662abfee62..3831bea06c 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/PolyArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/PolyOthersArtifactSystem.cs @@ -7,7 +7,7 @@ using Robust.Shared.Audio.Systems; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems; -public sealed class PolyArtifactSystem : EntitySystem +public sealed class PolyOthersArtifactSystem : EntitySystem { [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly MobStateSystem _mob = default!; @@ -19,25 +19,25 @@ public sealed class PolyArtifactSystem : EntitySystem /// public override void Initialize() { - SubscribeLocalEvent(OnActivate); + SubscribeLocalEvent(OnActivate); } /// /// Provided target is alive and is not a zombie, polymorphs the target. /// - private void OnActivate(EntityUid uid, PolyArtifactComponent component, ArtifactActivatedEvent args) + private void OnActivate(Entity ent, ref ArtifactActivatedEvent args) { - var xform = Transform(uid); + var xform = Transform(ent); var humanoids = new HashSet>(); - _lookup.GetEntitiesInRange(xform.Coordinates, component.Range, humanoids); + _lookup.GetEntitiesInRange(xform.Coordinates, ent.Comp.Range, humanoids); foreach (var comp in humanoids) { var target = comp.Owner; if (_mob.IsAlive(target)) { - _poly.PolymorphEntity(target, component.PolymorphPrototypeName); - _audio.PlayPvs(component.PolySound, uid); + _poly.PolymorphEntity(target, ent.Comp.PolymorphPrototypeName); + _audio.PlayPvs(ent.Comp.PolySound, ent); } } } diff --git a/Content.Shared/Polymorph/PolymorphActions.cs b/Content.Shared/Polymorph/PolymorphActions.cs index bae2c3e4dd..0f230868f0 100644 --- a/Content.Shared/Polymorph/PolymorphActions.cs +++ b/Content.Shared/Polymorph/PolymorphActions.cs @@ -9,6 +9,11 @@ public sealed partial class PolymorphActionEvent : InstantActionEvent /// the specific polymorph. /// public PolymorphPrototype Prototype = default!; + + public PolymorphActionEvent(PolymorphPrototype prototype) : this() + { + Prototype = prototype; + } } public sealed partial class RevertPolymorphActionEvent : InstantActionEvent diff --git a/Content.Shared/Polymorph/PolymorphPrototype.cs b/Content.Shared/Polymorph/PolymorphPrototype.cs index f093489b04..6d010711d2 100644 --- a/Content.Shared/Polymorph/PolymorphPrototype.cs +++ b/Content.Shared/Polymorph/PolymorphPrototype.cs @@ -1,116 +1,125 @@ using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; -namespace Content.Shared.Polymorph +namespace Content.Shared.Polymorph; + +/// +/// Polymorphs generally describe any type of transformation that can be applied to an entity. +/// +[Prototype] +[DataDefinition] +public sealed partial class PolymorphPrototype : IPrototype, IInheritingPrototype +{ + [ViewVariables] + [IdDataField] + public string ID { get; private set; } = default!; + + [ParentDataField(typeof(AbstractPrototypeIdArraySerializer))] + public string[]? Parents { get; private set; } + + [NeverPushInheritance] + [AbstractDataField] + public bool Abstract { get; private set; } + + [DataField(required: true, serverOnly: true)] + public PolymorphConfiguration Configuration = new(); + +} + +/// +/// Defines information about the polymorph +/// +[DataDefinition] +public sealed partial record PolymorphConfiguration { /// - /// Polymorphs generally describe any type of transformation that can be applied to an entity. + /// What entity the polymorph will turn the target into + /// must be in here because it makes no sense if it isn't + /// + [DataField(required: true, serverOnly: true)] + public EntProtoId Entity; + + /// + /// The delay between the polymorph's uses in seconds + /// Slightly weird as of right now. + /// + [DataField(serverOnly: true)] + public int Delay = 60; + + /// + /// The duration of the transformation in seconds + /// can be null if there is not one + /// + [DataField(serverOnly: true)] + public int? Duration; + + /// + /// whether or not the target can transform as will + /// set to true for things like polymorph spells and curses + /// + [DataField(serverOnly: true)] + public bool Forced; + + /// + /// Whether or not the entity transfers its damage between forms. + /// + [DataField(serverOnly: true)] + public bool TransferDamage = true; + + /// + /// Whether or not the entity transfers its name between forms. /// - [Prototype("polymorph")] - [DataDefinition] - public sealed partial class PolymorphPrototype : IPrototype, IInheritingPrototype - { - [ViewVariables] - [IdDataField] - public string ID { get; private set; } = default!; - - [DataField("name")] - public string Name { get; private set; } = string.Empty; - - [ParentDataField(typeof(AbstractPrototypeIdArraySerializer))] - public string[]? Parents { get; private set; } - - [NeverPushInheritance] - [AbstractDataFieldAttribute] - public bool Abstract { get; private set; } - - /// - /// What entity the polymorph will turn the target into - /// must be in here because it makes no sense if it isn't - /// - [DataField("entity", required: true, serverOnly: true, customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Entity = string.Empty; - - /// - /// The delay between the polymorph's uses in seconds - /// Slightly weird as of right now. - /// - [DataField("delay", serverOnly: true)] - public int Delay = 60; - - /// - /// The duration of the transformation in seconds - /// can be null if there is not one - /// - [DataField("duration", serverOnly: true)] - public int? Duration = null; - - /// - /// whether or not the target can transform as will - /// set to true for things like polymorph spells and curses - /// - [DataField("forced", serverOnly: true)] - public bool Forced = false; - - /// - /// Whether or not the entity transfers its damage between forms. - /// - [DataField("transferDamage", serverOnly: true)] - public bool TransferDamage = true; - - /// - /// Whether or not the entity transfers its name between forms. - /// - [DataField("transferName", serverOnly: true)] - public bool TransferName = false; - - /// - /// Whether or not the entity transfers its hair, skin color, hair color, etc. - /// - [DataField("transferHumanoidAppearance", serverOnly: true)] - public bool TransferHumanoidAppearance = false; - - /// - /// Whether or not the entity transfers its inventory and equipment between forms. - /// - [DataField("inventory", serverOnly: true)] - public PolymorphInventoryChange Inventory = PolymorphInventoryChange.None; - - /// - /// Whether or not the polymorph reverts when the entity goes into crit. - /// - [DataField("revertOnCrit", serverOnly: true)] - public bool RevertOnCrit = true; - - /// - /// Whether or not the polymorph reverts when the entity dies. - /// - [DataField("revertOnDeath", serverOnly: true)] - public bool RevertOnDeath = true; - - /// - /// Whether or not the polymorph reverts when the entity is eaten or fully sliced. - /// - [DataField("revertOnEat", serverOnly: true)] - public bool RevertOnEat = false; - - [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 - { - None, - Drop, - Transfer, - } + [DataField(serverOnly: true)] + public bool TransferName; + + /// + /// Whether or not the entity transfers its hair, skin color, hair color, etc. + /// + [DataField(serverOnly: true)] + public bool TransferHumanoidAppearance; + + /// + /// Whether or not the entity transfers its inventory and equipment between forms. + /// + [DataField(serverOnly: true)] + public PolymorphInventoryChange Inventory = PolymorphInventoryChange.None; + + /// + /// Whether or not the polymorph reverts when the entity goes into crit. + /// + [DataField(serverOnly: true)] + public bool RevertOnCrit = true; + + /// + /// Whether or not the polymorph reverts when the entity dies. + /// + [DataField(serverOnly: true)] + public bool RevertOnDeath = true; + + /// + /// Whether or not the polymorph reverts when the entity is eaten or fully sliced. + /// + [DataField(serverOnly: true)] + public bool RevertOnEat; + + /// + /// Whether or not an already polymorphed entity is able to be polymorphed again + /// + [DataField(serverOnly: true)] + public bool AllowRepeatedMorphs; + + /// + /// The amount of time that should pass after this polymorph has ended, before a new one + /// can occur. + /// + [DataField(serverOnly: true)] + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan Cooldown = TimeSpan.Zero; +} + +public enum PolymorphInventoryChange : byte +{ + None, + Drop, + Transfer, } diff --git a/Resources/Prototypes/Polymorphs/admin.yml b/Resources/Prototypes/Polymorphs/admin.yml index 0ae5426244..cb274ec7d4 100644 --- a/Resources/Prototypes/Polymorphs/admin.yml +++ b/Resources/Prototypes/Polymorphs/admin.yml @@ -1,43 +1,49 @@ - type: polymorph id: AdminLizardSmite - entity: MobReptilian - forced: true - transferName: true - transferHumanoidAppearance: true - inventory: Transfer - allowRepeatedMorphs: true + configuration: + entity: MobReptilian + forced: true + transferName: true + transferHumanoidAppearance: true + inventory: Transfer + allowRepeatedMorphs: true - type: polymorph id: AdminMonkeySmite - entity: MobMonkey - forced: true - inventory: Drop - allowRepeatedMorphs: true + configuration: + entity: MobMonkey + forced: true + inventory: Drop + allowRepeatedMorphs: true - type: polymorph id: AdminBreadSmite - entity: FoodBreadPlain - forced: true - inventory: Drop - allowRepeatedMorphs: true + configuration: + entity: FoodBreadPlain + forced: true + inventory: Drop + allowRepeatedMorphs: true - type: polymorph id: AdminInstrumentSmite - entity: SuperSynthesizerInstrument - forced: true - inventory: Drop - allowRepeatedMorphs: true + configuration: + entity: SuperSynthesizerInstrument + forced: true + inventory: Drop + allowRepeatedMorphs: true - type: polymorph id: AdminMouseSmite - entity: MobMouse - forced: true - inventory: Drop - allowRepeatedMorphs: true + configuration: + entity: MobMouse + forced: true + inventory: Drop + allowRepeatedMorphs: true - type: polymorph id: AdminDisposalsSmite - entity: DisposalUnit - forced: true - inventory: Drop - allowRepeatedMorphs: true + configuration: + entity: DisposalUnit + forced: true + inventory: Drop + allowRepeatedMorphs: true diff --git a/Resources/Prototypes/Polymorphs/polymorph.yml b/Resources/Prototypes/Polymorphs/polymorph.yml index 46590248ae..b4249f8a3e 100644 --- a/Resources/Prototypes/Polymorphs/polymorph.yml +++ b/Resources/Prototypes/Polymorphs/polymorph.yml @@ -1,150 +1,166 @@ - type: polymorph id: Mouse - entity: MobMouse - forced: true - duration: 30 + configuration: + entity: MobMouse + forced: true + duration: 30 - type: polymorph id: Chicken - entity: MobChicken - forced: true - inventory: Drop + configuration: + entity: MobChicken + forced: true + inventory: Drop - type: polymorph id: Monkey - entity: MobMonkey - forced: true - inventory: Drop - revertOnCrit: true - revertOnDeath: true + configuration: + entity: MobMonkey + forced: true + inventory: Drop + revertOnCrit: true + revertOnDeath: true - type: polymorph id: WizardForcedCarp - entity: MobCarpMagic - forced: true - inventory: None - transferName: true - transferDamage: true - revertOnCrit: false - revertOnDeath: true + configuration: + entity: MobCarpMagic + forced: true + inventory: None + transferName: true + transferDamage: true + revertOnCrit: false + revertOnDeath: true - type: polymorph id: WizardForcedSkeleton - entity: MobSkeletonPerson - forced: true - inventory: Drop - transferName: true - transferDamage: true - revertOnCrit: false - revertOnDeath: false + configuration: + entity: MobSkeletonPerson + forced: true + inventory: Drop + transferName: true + transferDamage: true + revertOnCrit: false + revertOnDeath: false - type: polymorph id: WizardForcedMonkey - entity: MobMonkey - forced: true - inventory: None - transferName: true - transferDamage: true - revertOnCrit: false - revertOnDeath: true + configuration: + entity: MobMonkey + forced: true + inventory: None + transferName: true + transferDamage: true + revertOnCrit: false + revertOnDeath: true - type: polymorph id: WizardWallDoor - entity: WoodDoor - forced: true - inventory: None - transferName: false - transferDamage: false - revertOnCrit: false - revertOnDeath: false + configuration: + entity: WoodDoor + forced: true + inventory: None + transferName: false + transferDamage: false + revertOnCrit: false + revertOnDeath: false - type: polymorph id: WizardForcedCluwne - entity: MobCluwne - forced: true - transferName: true - transferHumanoidAppearance: true - inventory: Transfer - revertOnDeath: true + configuration: + entity: MobCluwne + forced: true + transferName: true + transferHumanoidAppearance: true + inventory: Transfer + revertOnDeath: true # this is a test for transferring some visual appearance stuff - type: polymorph id: TestHumanMorph - entity: MobHuman - transferName: true - transferHumanoidAppearance: true - inventory: Transfer + configuration: + entity: MobHuman + transferName: true + transferHumanoidAppearance: true + inventory: Transfer - type: polymorph id: AMIVMorph - entity: MobMonkey - forced: true - inventory: Transfer - transferName: true - revertOnCrit: false - revertOnDeath: false + configuration: + entity: MobMonkey + forced: true + inventory: Transfer + transferName: true + revertOnCrit: false + revertOnDeath: false - type: polymorph id: BreadMorph - entity: FoodBreadPlain - forced: true - inventory: None - transferName: false - transferDamage: true - revertOnCrit: false - revertOnDeath: true - revertOnEat: true + configuration: + entity: FoodBreadPlain + forced: true + inventory: None + transferName: false + transferDamage: true + revertOnCrit: false + revertOnDeath: true + revertOnEat: true - type: polymorph id: TreeMorph - entity: FloraTree01 - forced: true - transferName: true - revertOnDeath: true - inventory: Drop - cooldown: 160 + configuration: + entity: FloraTree01 + forced: true + transferName: true + revertOnDeath: true + inventory: Drop + cooldown: 160 # this is the monkey polymorph for artifact. - type: polymorph id: ArtifactMonkey - entity: MobMonkey - forced: true - transferName: true - allowRepeatedMorphs: true - inventory: Transfer - revertOnCrit: true - revertOnDeath: true - duration: 20 + configuration: + entity: MobMonkey + forced: true + transferName: true + allowRepeatedMorphs: true + inventory: Transfer + revertOnCrit: true + revertOnDeath: true + duration: 20 - type: polymorph id: ArtifactCluwne - entity: MobCluwne - forced: true - transferName: true - transferHumanoidAppearance: true - inventory: None - revertOnDeath: true - revertOnCrit: true - duration: 30 + configuration: + entity: MobCluwne + forced: true + transferName: true + transferHumanoidAppearance: true + inventory: None + revertOnDeath: true + revertOnCrit: true + duration: 30 - type: polymorph id: ArtifactLizard - entity: MobLizard - forced: true - transferName: true - transferHumanoidAppearance: true - inventory: None - revertOnDeath: true - revertOnCrit: true - duration: 20 + configuration: + entity: MobLizard + forced: true + transferName: true + transferHumanoidAppearance: true + inventory: None + revertOnDeath: true + revertOnCrit: true + duration: 20 - type: polymorph id: ArtifactLuminous - entity: MobLuminousPerson - forced: true - transferName: true - transferHumanoidAppearance: true - inventory: None - revertOnDeath: true - revertOnCrit: true - duration: 20 + configuration: + entity: MobLuminousPerson + forced: true + transferName: true + transferHumanoidAppearance: true + inventory: None + revertOnDeath: true + revertOnCrit: true + duration: 20 diff --git a/Resources/Prototypes/XenoArch/Effects/normal_effects.yml b/Resources/Prototypes/XenoArch/Effects/normal_effects.yml index c0c3bf77f8..4810f0c546 100644 --- a/Resources/Prototypes/XenoArch/Effects/normal_effects.yml +++ b/Resources/Prototypes/XenoArch/Effects/normal_effects.yml @@ -515,14 +515,14 @@ targetDepth: 2 effectHint: artifact-effect-hint-polymorph components: - - type: PolyArtifact + - type: PolyOthersArtifact - type: artifactEffect id: EffectPolyLizard targetDepth: 2 effectHint: artifact-effect-hint-polymorph components: - - type: PolyArtifact + - type: PolyOthersArtifact polymorphPrototypeName: ArtifactLizard - type: artifactEffect @@ -530,7 +530,7 @@ targetDepth: 3 effectHint: artifact-effect-hint-polymorph components: - - type: PolyArtifact + - type: PolyOthersArtifact polymorphPrototypeName: ArtifactLuminous - type: artifactEffect