Cleanups PolymorphSystem/Components/Prototypes (#23721)

* Cleanups PolymorphSystem

* forgot this

* Nah

* Fix test

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
AJCM-git
2024-02-01 08:17:02 -04:00
committed by GitHub
parent c0227bcb3b
commit b8f0ed3975
17 changed files with 714 additions and 724 deletions

View File

@@ -32,7 +32,7 @@ public sealed class AddPolymorphActionCommand : IConsoleCommand
var polySystem = _entityManager.EntitySysManager.GetEntitySystem<PolymorphSystem>(); var polySystem = _entityManager.EntitySysManager.GetEntitySystem<PolymorphSystem>();
_entityManager.EnsureComponent<PolymorphableComponent>(entityUid.Value); var polymorphable = _entityManager.EnsureComponent<PolymorphableComponent>(entityUid.Value);
polySystem.CreatePolymorphAction(args[1], entityUid.Value); polySystem.CreatePolymorphAction(args[1], (entityUid.Value, polymorphable));
} }
} }

View File

@@ -18,7 +18,7 @@ public sealed partial class Polymorph : ReagentEffect
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
=> Loc.GetString("reagent-effect-guidebook-make-polymorph", => Loc.GetString("reagent-effect-guidebook-make-polymorph",
("chance", Probability), ("entityname", ("chance", Probability), ("entityname",
prototype.Index<EntityPrototype>(prototype.Index<PolymorphPrototype>(PolymorphPrototype).Entity).Name)); prototype.Index<EntityPrototype>(prototype.Index<PolymorphPrototype>(PolymorphPrototype).Configuration.Entity).Name));
public override void Effect(ReagentEffectArgs args) public override void Effect(ReagentEffectArgs args)
{ {

View File

@@ -1,21 +1,24 @@
using Content.Server.Polymorph.Systems;
using Content.Shared.Polymorph; using Content.Shared.Polymorph;
using Content.Shared.Whitelist; using Content.Shared.Whitelist;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Prototypes;
namespace Content.Server.Polymorph.Components; namespace Content.Server.Polymorph.Components;
[RegisterComponent] [RegisterComponent]
[Access(typeof(PolymorphSystem))]
public sealed partial class PolymorphOnCollideComponent : Component public sealed partial class PolymorphOnCollideComponent : Component
{ {
[DataField("polymorph", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<PolymorphPrototype>))] [DataField(required: true)]
public string Polymorph = default!; public ProtoId<PolymorphPrototype> Polymorph;
[DataField("whitelist", required: true)] [DataField(required: true)]
public EntityWhitelist Whitelist = default!; public EntityWhitelist Whitelist = default!;
[DataField("blacklist")] [DataField]
public EntityWhitelist? Blacklist; public EntityWhitelist? Blacklist;
[DataField]
public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg"); public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg");
} }

View File

@@ -1,16 +1,18 @@
using Content.Server.Polymorph.Systems;
using Content.Shared.Polymorph; 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] [RegisterComponent]
[Access(typeof(PolymorphSystem))]
public sealed partial class PolymorphableComponent : Component public sealed partial class PolymorphableComponent : Component
{ {
/// <summary> /// <summary>
/// A list of all the polymorphs that the entity has. /// A list of all the polymorphs that the entity has.
/// Used to manage them and remove them if needed. /// Used to manage them and remove them if needed.
/// </summary> /// </summary>
public Dictionary<string, EntityUid>? PolymorphActions = null; public Dictionary<ProtoId<PolymorphPrototype>, EntityUid>? PolymorphActions = null;
/// <summary> /// <summary>
/// Timestamp for when the most recent polymorph ended. /// Timestamp for when the most recent polymorph ended.
@@ -21,7 +23,6 @@ namespace Content.Server.Polymorph.Components
/// <summary> /// <summary>
/// The polymorphs that the entity starts out being able to do. /// The polymorphs that the entity starts out being able to do.
/// </summary> /// </summary>
[DataField("innatePolymorphs", customTypeSerializer : typeof(PrototypeIdListSerializer<PolymorphPrototype>))] [DataField]
public List<string>? InnatePolymorphs; public List<ProtoId<PolymorphPrototype>>? InnatePolymorphs;
}
} }

View File

@@ -1,31 +1,32 @@
using Content.Server.Polymorph.Systems;
using Content.Shared.Polymorph; using Content.Shared.Polymorph;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Polymorph.Components namespace Content.Server.Polymorph.Components;
{
[RegisterComponent] [RegisterComponent]
[Access(typeof(PolymorphSystem))]
public sealed partial class PolymorphedEntityComponent : Component public sealed partial class PolymorphedEntityComponent : Component
{ {
/// <summary> /// <summary>
/// The polymorph prototype, used to track various information /// The polymorph prototype, used to track various information
/// about the polymorph /// about the polymorph
/// </summary> /// </summary>
[DataField("prototype", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<PolymorphPrototype>))] [DataField(required: true)]
public string Prototype = string.Empty; public PolymorphConfiguration Configuration = new();
/// <summary> /// <summary>
/// The original entity that the player will revert back into /// The original entity that the player will revert back into
/// </summary> /// </summary>
[DataField("parent", required: true)] [DataField(required: true)]
public EntityUid Parent; public EntityUid Parent;
/// <summary> /// <summary>
/// The amount of time that has passed since the entity was created /// The amount of time that has passed since the entity was created
/// used for tracking the duration /// used for tracking the duration
/// </summary> /// </summary>
[DataField("time")] [DataField]
public float Time; public float Time;
[DataField] public EntityUid? Action; [DataField]
} public EntityUid? Action;
} }

View File

@@ -1,16 +1,25 @@
using Content.Server.Polymorph.Components; using Content.Server.Polymorph.Components;
using Content.Shared.Polymorph;
using Content.Shared.Projectiles; using Content.Shared.Projectiles;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Events;
using Robust.Shared.Prototypes;
namespace Content.Server.Polymorph.Systems; namespace Content.Server.Polymorph.Systems;
public partial class PolymorphSystem public partial class PolymorphSystem
{ {
// Need to do this so we don't get a collection enumeration error in physics by polymorphing /// <summary>
// 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
/// </summary>
private Queue<PolymorphQueuedData> _queuedPolymorphUpdates = new(); private Queue<PolymorphQueuedData> _queuedPolymorphUpdates = new();
private void InitializeCollide()
{
SubscribeLocalEvent<PolymorphOnCollideComponent, StartCollideEvent>(OnPolymorphCollide);
}
public void UpdateCollide() public void UpdateCollide()
{ {
while (_queuedPolymorphUpdates.TryDequeue(out var data)) while (_queuedPolymorphUpdates.TryDequeue(out var data))
@@ -20,16 +29,9 @@ public partial class PolymorphSystem
var ent = PolymorphEntity(data.Ent, data.Polymorph); var ent = PolymorphEntity(data.Ent, data.Polymorph);
if (ent != null) if (ent != null)
{
_audio.PlayPvs(data.Sound, ent.Value); _audio.PlayPvs(data.Sound, ent.Value);
} }
} }
}
private void InitializeCollide()
{
SubscribeLocalEvent<PolymorphOnCollideComponent, StartCollideEvent>(OnPolymorphCollide);
}
private void OnPolymorphCollide(EntityUid uid, PolymorphOnCollideComponent component, ref StartCollideEvent args) private void OnPolymorphCollide(EntityUid uid, PolymorphOnCollideComponent component, ref StartCollideEvent args)
{ {
@@ -37,8 +39,8 @@ public partial class PolymorphSystem
return; return;
var other = args.OtherEntity; var other = args.OtherEntity;
if (!component.Whitelist.IsValid(other) if (!component.Whitelist.IsValid(other, EntityManager)
|| component.Blacklist != null && component.Blacklist.IsValid(other)) || component.Blacklist != null && component.Blacklist.IsValid(other, EntityManager))
return; return;
_queuedPolymorphUpdates.Enqueue(new (other, component.Sound, component.Polymorph)); _queuedPolymorphUpdates.Enqueue(new (other, component.Sound, component.Polymorph));
@@ -49,9 +51,9 @@ public struct PolymorphQueuedData
{ {
public EntityUid Ent; public EntityUid Ent;
public SoundSpecifier Sound; public SoundSpecifier Sound;
public string Polymorph; public ProtoId<PolymorphPrototype> Polymorph;
public PolymorphQueuedData(EntityUid ent, SoundSpecifier sound, string polymorph) public PolymorphQueuedData(EntityUid ent, SoundSpecifier sound, ProtoId<PolymorphPrototype> polymorph)
{ {
Ent = ent; Ent = ent;
Sound = sound; Sound = sound;

View File

@@ -1,7 +1,7 @@
using Content.Shared.GameTicking; 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; }
@@ -19,14 +19,14 @@ namespace Content.Server.Polymorph.Systems
if (PausedMap == null || !Exists(PausedMap)) if (PausedMap == null || !Exists(PausedMap))
return; return;
EntityManager.DeleteEntity(PausedMap.Value); Del(PausedMap.Value);
} }
/// <summary> /// <summary>
/// Used internally to ensure a paused map that is /// Used internally to ensure a paused map that is
/// stores polymorphed entities. /// stores polymorphed entities.
/// </summary> /// </summary>
private void EnsurePausesdMap() private void EnsurePausedMap()
{ {
if (PausedMap != null && Exists(PausedMap)) if (PausedMap != null && Exists(PausedMap))
return; return;
@@ -36,4 +36,3 @@ namespace Content.Server.Polymorph.Systems
PausedMap = _mapManager.GetMapEntityId(newmap); PausedMap = _mapManager.GetMapEntityId(newmap);
} }
} }
}

View File

@@ -15,7 +15,6 @@ using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems; using Content.Shared.Mobs.Systems;
using Content.Shared.Polymorph; using Content.Shared.Polymorph;
using Content.Shared.Popups; using Content.Shared.Popups;
using JetBrains.Annotations;
using Robust.Server.Audio; using Robust.Server.Audio;
using Robust.Server.Containers; using Robust.Server.Containers;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
@@ -24,13 +23,14 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; 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 IComponentFactory _compFact = default!;
[Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly ActionContainerSystem _actionContainer = default!; [Dependency] private readonly ActionContainerSystem _actionContainer = default!;
[Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly AudioSystem _audio = default!;
@@ -46,83 +46,105 @@ namespace Content.Server.Polymorph.Systems
[Dependency] private readonly TransformSystem _transform = default!; [Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly SharedMindSystem _mindSystem = default!; [Dependency] private readonly SharedMindSystem _mindSystem = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
private ISawmill _sawmill = default!;
private const string RevertPolymorphId = "ActionRevertPolymorph"; private const string RevertPolymorphId = "ActionRevertPolymorph";
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); SubscribeLocalEvent<PolymorphableComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<PolymorphableComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<PolymorphableComponent, PolymorphActionEvent>(OnPolymorphActionEvent);
SubscribeLocalEvent<PolymorphedEntityComponent, MapInitEvent>(OnMapInit); SubscribeLocalEvent<PolymorphedEntityComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<PolymorphableComponent, PolymorphActionEvent>(OnPolymorphActionEvent);
SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent);
SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullyEatenEvent>(OnBeforeFullyEaten); SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullyEatenEvent>(OnBeforeFullyEaten);
SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullySlicedEvent>(OnBeforeFullySliced); SubscribeLocalEvent<PolymorphedEntityComponent, BeforeFullySlicedEvent>(OnBeforeFullySliced);
SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent);
SubscribeLocalEvent<PolymorphedEntityComponent, DestructionEventArgs>(OnDestruction); SubscribeLocalEvent<PolymorphedEntityComponent, DestructionEventArgs>(OnDestruction);
InitializeCollide(); InitializeCollide();
InitializeMap(); InitializeMap();
_sawmill = Logger.GetSawmill("polymorph");
} }
private void OnStartup(EntityUid uid, PolymorphableComponent component, ComponentStartup args) public override void Update(float frameTime)
{ {
if (component.InnatePolymorphs != null) base.Update(frameTime);
var query = EntityQueryEnumerator<PolymorphedEntityComponent>();
while (query.MoveNext(out var uid, out var comp))
{ {
foreach (var morph in component.InnatePolymorphs) comp.Time += frameTime;
if (comp.Configuration.Duration != null && comp.Time >= comp.Configuration.Duration)
{ {
CreatePolymorphAction(morph, uid); Revert((uid, comp));
continue;
}
if (!TryComp<MobStateComponent>(uid, out var mob))
continue;
if (comp.Configuration.RevertOnDeath && _mobState.IsDead(uid, mob) ||
comp.Configuration.RevertOnCrit && _mobState.IsIncapacitated(uid, mob))
{
Revert((uid, comp));
}
}
UpdateCollide();
}
private void OnComponentStartup(Entity<PolymorphableComponent> ent, ref ComponentStartup args)
{
if (ent.Comp.InnatePolymorphs != null)
{
foreach (var morph in ent.Comp.InnatePolymorphs)
{
CreatePolymorphAction(morph, ent);
} }
} }
} }
private void OnPolymorphActionEvent(EntityUid uid, PolymorphableComponent component, PolymorphActionEvent args) private void OnMapInit(Entity<PolymorphedEntityComponent> ent, ref MapInitEvent args)
{ {
PolymorphEntity(uid, args.Prototype); var (uid, component) = ent;
} if (component.Configuration.Forced)
private void OnRevertPolymorphActionEvent(EntityUid uid, PolymorphedEntityComponent component, RevertPolymorphActionEvent args)
{
Revert(uid, component);
}
private void OnMapInit(EntityUid uid, PolymorphedEntityComponent component, MapInitEvent args)
{
if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
{
// 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;
}
if (proto.Forced)
return; return;
if (_actions.AddAction(uid, ref component.Action, out var action, RevertPolymorphId)) if (_actions.AddAction(uid, ref component.Action, out var action, RevertPolymorphId))
{ {
action.EntityIcon = component.Parent; action.EntityIcon = component.Parent;
action.UseDelay = TimeSpan.FromSeconds(proto.Delay); action.UseDelay = TimeSpan.FromSeconds(component.Configuration.Delay);
} }
} }
private void OnBeforeFullyEaten(EntityUid uid, PolymorphedEntityComponent comp, BeforeFullyEatenEvent args) private void OnPolymorphActionEvent(Entity<PolymorphableComponent> ent, ref PolymorphActionEvent args)
{ {
if (!_proto.TryIndex<PolymorphPrototype>(comp.Prototype, out var proto)) PolymorphEntity(ent, args.Prototype.Configuration);
{
_sawmill.Error($"Invalid polymorph prototype {comp.Prototype}");
return;
} }
if (proto.RevertOnEat) private void OnRevertPolymorphActionEvent(Entity<PolymorphedEntityComponent> ent,
ref RevertPolymorphActionEvent args)
{
Revert((ent, ent));
}
private void OnBeforeFullyEaten(Entity<PolymorphedEntityComponent> ent, ref BeforeFullyEatenEvent args)
{
var (_, comp) = ent;
if (comp.Configuration.RevertOnEat)
{ {
args.Cancel(); args.Cancel();
Revert(uid, comp); Revert((ent, ent));
}
}
private void OnBeforeFullySliced(Entity<PolymorphedEntityComponent> ent, ref BeforeFullySlicedEvent args)
{
var (_, comp) = ent;
if (comp.Configuration.RevertOnEat)
{
args.Cancel();
Revert((ent, ent));
} }
} }
@@ -130,67 +152,42 @@ namespace Content.Server.Polymorph.Systems
/// It is possible to be polymorphed into an entity that can't "die", but is instead /// 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. /// destroyed. This handler ensures that destruction is treated like death.
/// </summary> /// </summary>
private void OnDestruction(EntityUid uid, PolymorphedEntityComponent comp, DestructionEventArgs args) private void OnDestruction(Entity<PolymorphedEntityComponent> ent, ref DestructionEventArgs args)
{ {
if (!_proto.TryIndex<PolymorphPrototype>(comp.Prototype, out var proto)) if (ent.Comp.Configuration.RevertOnDeath)
{ {
_sawmill.Error($"Invalid polymorph prototype {comp.Prototype}"); Revert((ent, ent));
return;
} }
if (proto.RevertOnDeath)
{
Revert(uid, comp);
}
}
private void OnBeforeFullySliced(EntityUid uid, PolymorphedEntityComponent comp, BeforeFullySlicedEvent args)
{
if (!_proto.TryIndex<PolymorphPrototype>(comp.Prototype, out var proto))
{
_sawmill.Error("Invalid polymorph prototype {comp.Prototype}");
return;
}
if (proto.RevertOnEat)
{
args.Cancel();
Revert(uid, comp);
}
}
/// <summary>
/// Polymorphs the target entity into the specific polymorph prototype
/// </summary>
/// <param name="target">The entity that will be transformed</param>
/// <param name="id">The id of the polymorph prototype</param>
public EntityUid? PolymorphEntity(EntityUid target, string id)
{
if (!_proto.TryIndex<PolymorphPrototype>(id, out var proto))
{
_sawmill.Error("Invalid polymorph prototype {id}");
return null;
}
return PolymorphEntity(target, proto);
} }
/// <summary> /// <summary>
/// Polymorphs the target entity into the specific polymorph prototype /// Polymorphs the target entity into the specific polymorph prototype
/// </summary> /// </summary>
/// <param name="uid">The entity that will be transformed</param> /// <param name="uid">The entity that will be transformed</param>
/// <param name="proto">The polymorph prototype</param> /// <param name="protoId">The id of the polymorph prototype</param>
public EntityUid? PolymorphEntity(EntityUid uid, PolymorphPrototype proto) public EntityUid? PolymorphEntity(EntityUid uid, ProtoId<PolymorphPrototype> protoId)
{
var config = _proto.Index(protoId).Configuration;
return PolymorphEntity(uid, config);
}
/// <summary>
/// Polymorphs the target entity into another
/// </summary>
/// <param name="uid">The entity that will be transformed</param>
/// <param name="configuration">Polymorph data</param>
/// <returns></returns>
public EntityUid? PolymorphEntity(EntityUid uid, PolymorphConfiguration configuration)
{ {
// if it's already morphed, don't allow it again with this condition active. // if it's already morphed, don't allow it again with this condition active.
if (!proto.AllowRepeatedMorphs && HasComp<PolymorphedEntityComponent>(uid)) if (!configuration.AllowRepeatedMorphs && HasComp<PolymorphedEntityComponent>(uid))
return null; return null;
// If this polymorph has a cooldown, check if that amount of time has passed since the // If this polymorph has a cooldown, check if that amount of time has passed since the
// last polymorph ended. // last polymorph ended.
if (TryComp<PolymorphableComponent>(uid, out var polymorphableComponent) && if (TryComp<PolymorphableComponent>(uid, out var polymorphableComponent) &&
polymorphableComponent.LastPolymorphEnd != null && polymorphableComponent.LastPolymorphEnd != null &&
_gameTiming.CurTime < polymorphableComponent.LastPolymorphEnd + proto.Cooldown) _gameTiming.CurTime < polymorphableComponent.LastPolymorphEnd + configuration.Cooldown)
return null; return null;
// mostly just for vehicles // mostly just for vehicles
@@ -198,22 +195,23 @@ namespace Content.Server.Polymorph.Systems
var targetTransformComp = Transform(uid); var targetTransformComp = Transform(uid);
var child = Spawn(proto.Entity, targetTransformComp.Coordinates); var child = Spawn(configuration.Entity, targetTransformComp.Coordinates);
MakeSentientCommand.MakeSentient(child, EntityManager); MakeSentientCommand.MakeSentient(child, EntityManager);
var comp = _compFact.GetComponent<PolymorphedEntityComponent>(); var polymorphedComp = _compFact.GetComponent<PolymorphedEntityComponent>();
comp.Parent = uid; polymorphedComp.Parent = uid;
comp.Prototype = proto.ID; polymorphedComp.Configuration = configuration;
AddComp(child, comp); AddComp(child, polymorphedComp);
var childXform = Transform(child); var childXform = Transform(child);
childXform.LocalRotation = targetTransformComp.LocalRotation; _transform.SetLocalRotation(child, targetTransformComp.LocalRotation, childXform);
if (_container.TryGetContainingContainer(uid, out var cont)) if (_container.TryGetContainingContainer(uid, out var cont))
_container.Insert(child, cont); _container.Insert(child, cont);
//Transfers all damage from the original to the new one //Transfers all damage from the original to the new one
if (proto.TransferDamage && if (configuration.TransferDamage &&
TryComp<DamageableComponent>(child, out var damageParent) && TryComp<DamageableComponent>(child, out var damageParent) &&
_mobThreshold.GetScaledDamage(uid, child, out var damage) && _mobThreshold.GetScaledDamage(uid, child, out var damage) &&
damage != null) damage != null)
@@ -221,7 +219,7 @@ namespace Content.Server.Polymorph.Systems
_damageable.SetDamage(child, damageParent, damage); _damageable.SetDamage(child, damageParent, damage);
} }
if (proto.Inventory == PolymorphInventoryChange.Transfer) if (configuration.Inventory == PolymorphInventoryChange.Transfer)
{ {
_inventory.TransferEntityInventories(uid, child); _inventory.TransferEntityInventories(uid, child);
foreach (var hand in _hands.EnumerateHeld(uid)) foreach (var hand in _hands.EnumerateHeld(uid))
@@ -230,7 +228,7 @@ namespace Content.Server.Polymorph.Systems
_hands.TryPickupAnyHand(child, hand); _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))
{ {
@@ -246,10 +244,10 @@ namespace Content.Server.Polymorph.Systems
} }
} }
if (proto.TransferName && TryComp<MetaDataComponent>(uid, out var targetMeta)) if (configuration.TransferName && TryComp<MetaDataComponent>(uid, out var targetMeta))
_metaData.SetEntityName(child, targetMeta.EntityName); _metaData.SetEntityName(child, targetMeta.EntityName);
if (proto.TransferHumanoidAppearance) if (configuration.TransferHumanoidAppearance)
{ {
_humanoid.CloneAppearance(uid, child); _humanoid.CloneAppearance(uid, child);
} }
@@ -258,7 +256,7 @@ namespace Content.Server.Polymorph.Systems
_mindSystem.TransferTo(mindId, child, mind: mind); _mindSystem.TransferTo(mindId, child, mind: mind);
//Ensures a map to banish the entity to //Ensures a map to banish the entity to
EnsurePausesdMap(); EnsurePausedMap();
if (PausedMap != null) if (PausedMap != null)
_transform.SetParent(uid, targetTransformComp, PausedMap.Value); _transform.SetParent(uid, targetTransformComp, PausedMap.Value);
@@ -270,32 +268,26 @@ namespace Content.Server.Polymorph.Systems
/// </summary> /// </summary>
/// <param name="uid">The entityuid of the entity being reverted</param> /// <param name="uid">The entityuid of the entity being reverted</param>
/// <param name="component"></param> /// <param name="component"></param>
public EntityUid? Revert(EntityUid uid, PolymorphedEntityComponent? component = null) public EntityUid? Revert(Entity<PolymorphedEntityComponent?> ent)
{ {
if (Deleted(uid)) var (uid, component) = ent;
if (!Resolve(ent, ref component))
return null; return null;
if (!Resolve(uid, ref component)) if (Deleted(uid))
return null; return null;
var parent = component.Parent; var parent = component.Parent;
if (Deleted(parent)) if (Deleted(parent))
return null; return null;
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;
}
var uidXform = Transform(uid); var uidXform = Transform(uid);
var parentXform = Transform(parent); var parentXform = Transform(parent);
_transform.SetParent(parent, parentXform, uidXform.ParentUid); _transform.SetParent(parent, parentXform, uidXform.ParentUid);
parentXform.Coordinates = uidXform.Coordinates; _transform.SetCoordinates(parent, parentXform, uidXform.Coordinates, uidXform.LocalRotation);
parentXform.LocalRotation = uidXform.LocalRotation;
if (proto.TransferDamage && if (component.Configuration.TransferDamage &&
TryComp<DamageableComponent>(parent, out var damageParent) && TryComp<DamageableComponent>(parent, out var damageParent) &&
_mobThreshold.GetScaledDamage(uid, parent, out var damage) && _mobThreshold.GetScaledDamage(uid, parent, out var damage) &&
damage != null) damage != null)
@@ -303,7 +295,7 @@ namespace Content.Server.Polymorph.Systems
_damageable.SetDamage(parent, damageParent, damage); _damageable.SetDamage(parent, damageParent, damage);
} }
if (proto.Inventory == PolymorphInventoryChange.Transfer) if (component.Configuration.Inventory == PolymorphInventoryChange.Transfer)
{ {
_inventory.TransferEntityInventories(uid, parent); _inventory.TransferEntityInventories(uid, parent);
foreach (var held in _hands.EnumerateHeld(uid)) foreach (var held in _hands.EnumerateHeld(uid))
@@ -312,7 +304,7 @@ namespace Content.Server.Polymorph.Systems
_hands.TryPickupAnyHand(parent, held, checkActionBlocker: false); _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))
{ {
@@ -335,7 +327,7 @@ namespace Content.Server.Polymorph.Systems
polymorphableComponent.LastPolymorphEnd = _gameTiming.CurTime; polymorphableComponent.LastPolymorphEnd = _gameTiming.CurTime;
// if an item polymorph was picked up, put it back down after reverting // if an item polymorph was picked up, put it back down after reverting
Transform(parent).AttachToGridOrMap(); _transform.AttachToGridOrMap(parent, parentXform);
_popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic", _popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic",
("parent", Identity.Entity(uid, EntityManager)), ("parent", Identity.Entity(uid, EntityManager)),
@@ -351,83 +343,39 @@ namespace Content.Server.Polymorph.Systems
/// </summary> /// </summary>
/// <param name="id">The string of the id of the polymorph action</param> /// <param name="id">The string of the id of the polymorph action</param>
/// <param name="target">The entity that will be gaining the action</param> /// <param name="target">The entity that will be gaining the action</param>
public void CreatePolymorphAction(string id, EntityUid target) public void CreatePolymorphAction(ProtoId<PolymorphPrototype> id, Entity<PolymorphableComponent> target)
{ {
if (!_proto.TryIndex<PolymorphPrototype>(id, out var polyproto)) target.Comp.PolymorphActions ??= new();
{ if (target.Comp.PolymorphActions.ContainsKey(id))
_sawmill.Error("Invalid polymorph prototype");
return;
}
if (!TryComp<PolymorphableComponent>(target, out var polycomp))
return; return;
polycomp.PolymorphActions ??= new Dictionary<string, EntityUid>(); var polyProto = _proto.Index(id);
if (polycomp.PolymorphActions.ContainsKey(id)) var entProto = _proto.Index(polyProto.Configuration.Entity);
return;
var entproto = _proto.Index<EntityPrototype>(polyproto.Entity);
EntityUid? actionId = default!; EntityUid? actionId = default!;
if (!_actions.AddAction(target, ref actionId, RevertPolymorphId, target)) if (!_actions.AddAction(target, ref actionId, RevertPolymorphId, target))
return; return;
polycomp.PolymorphActions.Add(id, actionId.Value); target.Comp.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))); 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 (!_actions.TryGetActionData(actionId, out var baseAction)) if (!_actions.TryGetActionData(actionId, out var baseAction))
return; return;
baseAction.Icon = new SpriteSpecifier.EntityPrototype(polyproto.Entity); baseAction.Icon = new SpriteSpecifier.EntityPrototype(polyProto.Configuration.Entity);
if (baseAction is InstantActionComponent action) if (baseAction is InstantActionComponent action)
action.Event = new PolymorphActionEvent { Prototype = polyproto }; action.Event = new PolymorphActionEvent(prototype: polyProto);
} }
[PublicAPI] public void RemovePolymorphAction(ProtoId<PolymorphPrototype> id, Entity<PolymorphableComponent> target)
public void RemovePolymorphAction(string id, EntityUid target, PolymorphableComponent? component = null)
{ {
if (!Resolve(target, ref component, false)) if (target.Comp.PolymorphActions == null)
return; return;
if (component.PolymorphActions == null)
return; if (target.Comp.PolymorphActions.TryGetValue(id, out var val))
if (component.PolymorphActions.TryGetValue(id, out var val))
_actions.RemoveAction(target, val); _actions.RemoveAction(target, val);
} }
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<PolymorphedEntityComponent>();
while (query.MoveNext(out var uid, out var comp))
{
comp.Time += frameTime;
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;
}
if (proto.Duration != null && comp.Time >= proto.Duration)
{
Revert(uid, comp);
continue;
}
if (!TryComp<MobStateComponent>(uid, out var mob))
continue;
if (proto.RevertOnDeath && _mobState.IsDead(uid, mob) ||
proto.RevertOnCrit && _mobState.IsIncapacitated(uid, mob))
{
Revert(uid, comp);
}
}
UpdateCollide();
}
}
} }

View File

@@ -24,7 +24,7 @@ public sealed class PolymorphCommand : ToolshedCommand
{ {
_system ??= GetSys<PolymorphSystem>(); _system ??= GetSys<PolymorphSystem>();
return _system.PolymorphEntity(input, prototype.Value); return _system.PolymorphEntity(input, prototype.Value.Configuration);
} }
[CommandImplementation] [CommandImplementation]

View File

@@ -2,9 +2,7 @@
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.Polymorph.Systems; using Content.Server.Polymorph.Systems;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Polymorph;
using Robust.Shared.Toolshed; using Robust.Shared.Toolshed;
using Robust.Shared.Toolshed.TypeParsers;
namespace Content.Server.Polymorph.Toolshed; namespace Content.Server.Polymorph.Toolshed;

View File

@@ -1,3 +1,4 @@
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Content.Shared.Polymorph; using Content.Shared.Polymorph;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -8,7 +9,8 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
/// Artifact polymorphs surrounding entities when triggered. /// Artifact polymorphs surrounding entities when triggered.
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent]
public sealed partial class PolyArtifactComponent : Component [Access(typeof(PolyOthersArtifactSystem))]
public sealed partial class PolyOthersArtifactComponent : Component
{ {
/// <summary> /// <summary>
/// The polymorph effect to trigger. /// The polymorph effect to trigger.

View File

@@ -7,7 +7,7 @@ using Robust.Shared.Audio.Systems;
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.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 EntityLookupSystem _lookup = default!;
[Dependency] private readonly MobStateSystem _mob = default!; [Dependency] private readonly MobStateSystem _mob = default!;
@@ -19,25 +19,25 @@ public sealed class PolyArtifactSystem : EntitySystem
/// </summary> /// </summary>
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<PolyArtifactComponent, ArtifactActivatedEvent>(OnActivate); SubscribeLocalEvent<PolyOthersArtifactComponent, ArtifactActivatedEvent>(OnActivate);
} }
/// <summary> /// <summary>
/// Provided target is alive and is not a zombie, polymorphs the target. /// Provided target is alive and is not a zombie, polymorphs the target.
/// </summary> /// </summary>
private void OnActivate(EntityUid uid, PolyArtifactComponent component, ArtifactActivatedEvent args) private void OnActivate(Entity<PolyOthersArtifactComponent> ent, ref ArtifactActivatedEvent args)
{ {
var xform = Transform(uid); var xform = Transform(ent);
var humanoids = new HashSet<Entity<HumanoidAppearanceComponent>>(); var humanoids = new HashSet<Entity<HumanoidAppearanceComponent>>();
_lookup.GetEntitiesInRange(xform.Coordinates, component.Range, humanoids); _lookup.GetEntitiesInRange(xform.Coordinates, ent.Comp.Range, humanoids);
foreach (var comp in humanoids) foreach (var comp in humanoids)
{ {
var target = comp.Owner; var target = comp.Owner;
if (_mob.IsAlive(target)) if (_mob.IsAlive(target))
{ {
_poly.PolymorphEntity(target, component.PolymorphPrototypeName); _poly.PolymorphEntity(target, ent.Comp.PolymorphPrototypeName);
_audio.PlayPvs(component.PolySound, uid); _audio.PlayPvs(ent.Comp.PolySound, ent);
} }
} }
} }

View File

@@ -9,6 +9,11 @@ public sealed partial class PolymorphActionEvent : InstantActionEvent
/// the specific polymorph. /// the specific polymorph.
/// </summary> /// </summary>
public PolymorphPrototype Prototype = default!; public PolymorphPrototype Prototype = default!;
public PolymorphActionEvent(PolymorphPrototype prototype) : this()
{
Prototype = prototype;
}
} }
public sealed partial class RevertPolymorphActionEvent : InstantActionEvent public sealed partial class RevertPolymorphActionEvent : InstantActionEvent

View File

@@ -1,13 +1,12 @@
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
namespace Content.Shared.Polymorph namespace Content.Shared.Polymorph;
{
/// <summary> /// <summary>
/// Polymorphs generally describe any type of transformation that can be applied to an entity. /// Polymorphs generally describe any type of transformation that can be applied to an entity.
/// </summary> /// </summary>
[Prototype("polymorph")] [Prototype]
[DataDefinition] [DataDefinition]
public sealed partial class PolymorphPrototype : IPrototype, IInheritingPrototype public sealed partial class PolymorphPrototype : IPrototype, IInheritingPrototype
{ {
@@ -15,94 +14,105 @@ namespace Content.Shared.Polymorph
[IdDataField] [IdDataField]
public string ID { get; private set; } = default!; public string ID { get; private set; } = default!;
[DataField("name")]
public string Name { get; private set; } = string.Empty;
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<PolymorphPrototype>))] [ParentDataField(typeof(AbstractPrototypeIdArraySerializer<PolymorphPrototype>))]
public string[]? Parents { get; private set; } public string[]? Parents { get; private set; }
[NeverPushInheritance] [NeverPushInheritance]
[AbstractDataFieldAttribute] [AbstractDataField]
public bool Abstract { get; private set; } public bool Abstract { get; private set; }
[DataField(required: true, serverOnly: true)]
public PolymorphConfiguration Configuration = new();
}
/// <summary>
/// Defines information about the polymorph
/// </summary>
[DataDefinition]
public sealed partial record PolymorphConfiguration
{
/// <summary> /// <summary>
/// What entity the polymorph will turn the target into /// What entity the polymorph will turn the target into
/// must be in here because it makes no sense if it isn't /// must be in here because it makes no sense if it isn't
/// </summary> /// </summary>
[DataField("entity", required: true, serverOnly: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] [DataField(required: true, serverOnly: true)]
public string Entity = string.Empty; public EntProtoId Entity;
/// <summary> /// <summary>
/// The delay between the polymorph's uses in seconds /// The delay between the polymorph's uses in seconds
/// Slightly weird as of right now. /// Slightly weird as of right now.
/// </summary> /// </summary>
[DataField("delay", serverOnly: true)] [DataField(serverOnly: true)]
public int Delay = 60; public int Delay = 60;
/// <summary> /// <summary>
/// The duration of the transformation in seconds /// The duration of the transformation in seconds
/// can be null if there is not one /// can be null if there is not one
/// </summary> /// </summary>
[DataField("duration", serverOnly: true)] [DataField(serverOnly: true)]
public int? Duration = null; public int? Duration;
/// <summary> /// <summary>
/// whether or not the target can transform as will /// whether or not the target can transform as will
/// set to true for things like polymorph spells and curses /// set to true for things like polymorph spells and curses
/// </summary> /// </summary>
[DataField("forced", serverOnly: true)] [DataField(serverOnly: true)]
public bool Forced = false; public bool Forced;
/// <summary> /// <summary>
/// Whether or not the entity transfers its damage between forms. /// Whether or not the entity transfers its damage between forms.
/// </summary> /// </summary>
[DataField("transferDamage", serverOnly: true)] [DataField(serverOnly: true)]
public bool TransferDamage = true; public bool TransferDamage = true;
/// <summary> /// <summary>
/// Whether or not the entity transfers its name between forms. /// Whether or not the entity transfers its name between forms.
/// </summary> /// </summary>
[DataField("transferName", serverOnly: true)] [DataField(serverOnly: true)]
public bool TransferName = false; public bool TransferName;
/// <summary> /// <summary>
/// Whether or not the entity transfers its hair, skin color, hair color, etc. /// Whether or not the entity transfers its hair, skin color, hair color, etc.
/// </summary> /// </summary>
[DataField("transferHumanoidAppearance", serverOnly: true)] [DataField(serverOnly: true)]
public bool TransferHumanoidAppearance = false; public bool TransferHumanoidAppearance;
/// <summary> /// <summary>
/// Whether or not the entity transfers its inventory and equipment between forms. /// Whether or not the entity transfers its inventory and equipment between forms.
/// </summary> /// </summary>
[DataField("inventory", serverOnly: true)] [DataField(serverOnly: true)]
public PolymorphInventoryChange Inventory = PolymorphInventoryChange.None; public PolymorphInventoryChange Inventory = PolymorphInventoryChange.None;
/// <summary> /// <summary>
/// Whether or not the polymorph reverts when the entity goes into crit. /// Whether or not the polymorph reverts when the entity goes into crit.
/// </summary> /// </summary>
[DataField("revertOnCrit", serverOnly: true)] [DataField(serverOnly: true)]
public bool RevertOnCrit = true; public bool RevertOnCrit = true;
/// <summary> /// <summary>
/// Whether or not the polymorph reverts when the entity dies. /// Whether or not the polymorph reverts when the entity dies.
/// </summary> /// </summary>
[DataField("revertOnDeath", serverOnly: true)] [DataField(serverOnly: true)]
public bool RevertOnDeath = true; public bool RevertOnDeath = true;
/// <summary> /// <summary>
/// Whether or not the polymorph reverts when the entity is eaten or fully sliced. /// Whether or not the polymorph reverts when the entity is eaten or fully sliced.
/// </summary> /// </summary>
[DataField("revertOnEat", serverOnly: true)] [DataField(serverOnly: true)]
public bool RevertOnEat = false; public bool RevertOnEat;
[DataField("allowRepeatedMorphs", serverOnly: true)] /// <summary>
public bool AllowRepeatedMorphs = false; /// Whether or not an already polymorphed entity is able to be polymorphed again
/// </summary>
[DataField(serverOnly: true)]
public bool AllowRepeatedMorphs;
/// <summary> /// <summary>
/// The amount of time that should pass after this polymorph has ended, before a new one /// The amount of time that should pass after this polymorph has ended, before a new one
/// can occur. /// can occur.
/// </summary> /// </summary>
[DataField("cooldown", serverOnly: true)] [DataField(serverOnly: true)]
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public TimeSpan Cooldown = TimeSpan.Zero; public TimeSpan Cooldown = TimeSpan.Zero;
} }
@@ -113,4 +123,3 @@ namespace Content.Shared.Polymorph
Drop, Drop,
Transfer, Transfer,
} }
}

View File

@@ -1,5 +1,6 @@
- type: polymorph - type: polymorph
id: AdminLizardSmite id: AdminLizardSmite
configuration:
entity: MobReptilian entity: MobReptilian
forced: true forced: true
transferName: true transferName: true
@@ -9,6 +10,7 @@
- type: polymorph - type: polymorph
id: AdminMonkeySmite id: AdminMonkeySmite
configuration:
entity: MobMonkey entity: MobMonkey
forced: true forced: true
inventory: Drop inventory: Drop
@@ -16,6 +18,7 @@
- type: polymorph - type: polymorph
id: AdminBreadSmite id: AdminBreadSmite
configuration:
entity: FoodBreadPlain entity: FoodBreadPlain
forced: true forced: true
inventory: Drop inventory: Drop
@@ -23,6 +26,7 @@
- type: polymorph - type: polymorph
id: AdminInstrumentSmite id: AdminInstrumentSmite
configuration:
entity: SuperSynthesizerInstrument entity: SuperSynthesizerInstrument
forced: true forced: true
inventory: Drop inventory: Drop
@@ -30,6 +34,7 @@
- type: polymorph - type: polymorph
id: AdminMouseSmite id: AdminMouseSmite
configuration:
entity: MobMouse entity: MobMouse
forced: true forced: true
inventory: Drop inventory: Drop
@@ -37,6 +42,7 @@
- type: polymorph - type: polymorph
id: AdminDisposalsSmite id: AdminDisposalsSmite
configuration:
entity: DisposalUnit entity: DisposalUnit
forced: true forced: true
inventory: Drop inventory: Drop

View File

@@ -1,17 +1,20 @@
- type: polymorph - type: polymorph
id: Mouse id: Mouse
configuration:
entity: MobMouse entity: MobMouse
forced: true forced: true
duration: 30 duration: 30
- type: polymorph - type: polymorph
id: Chicken id: Chicken
configuration:
entity: MobChicken entity: MobChicken
forced: true forced: true
inventory: Drop inventory: Drop
- type: polymorph - type: polymorph
id: Monkey id: Monkey
configuration:
entity: MobMonkey entity: MobMonkey
forced: true forced: true
inventory: Drop inventory: Drop
@@ -20,6 +23,7 @@
- type: polymorph - type: polymorph
id: WizardForcedCarp id: WizardForcedCarp
configuration:
entity: MobCarpMagic entity: MobCarpMagic
forced: true forced: true
inventory: None inventory: None
@@ -30,6 +34,7 @@
- type: polymorph - type: polymorph
id: WizardForcedSkeleton id: WizardForcedSkeleton
configuration:
entity: MobSkeletonPerson entity: MobSkeletonPerson
forced: true forced: true
inventory: Drop inventory: Drop
@@ -40,6 +45,7 @@
- type: polymorph - type: polymorph
id: WizardForcedMonkey id: WizardForcedMonkey
configuration:
entity: MobMonkey entity: MobMonkey
forced: true forced: true
inventory: None inventory: None
@@ -50,6 +56,7 @@
- type: polymorph - type: polymorph
id: WizardWallDoor id: WizardWallDoor
configuration:
entity: WoodDoor entity: WoodDoor
forced: true forced: true
inventory: None inventory: None
@@ -60,6 +67,7 @@
- type: polymorph - type: polymorph
id: WizardForcedCluwne id: WizardForcedCluwne
configuration:
entity: MobCluwne entity: MobCluwne
forced: true forced: true
transferName: true transferName: true
@@ -70,6 +78,7 @@
# this is a test for transferring some visual appearance stuff # this is a test for transferring some visual appearance stuff
- type: polymorph - type: polymorph
id: TestHumanMorph id: TestHumanMorph
configuration:
entity: MobHuman entity: MobHuman
transferName: true transferName: true
transferHumanoidAppearance: true transferHumanoidAppearance: true
@@ -77,6 +86,7 @@
- type: polymorph - type: polymorph
id: AMIVMorph id: AMIVMorph
configuration:
entity: MobMonkey entity: MobMonkey
forced: true forced: true
inventory: Transfer inventory: Transfer
@@ -86,6 +96,7 @@
- type: polymorph - type: polymorph
id: BreadMorph id: BreadMorph
configuration:
entity: FoodBreadPlain entity: FoodBreadPlain
forced: true forced: true
inventory: None inventory: None
@@ -97,6 +108,7 @@
- type: polymorph - type: polymorph
id: TreeMorph id: TreeMorph
configuration:
entity: FloraTree01 entity: FloraTree01
forced: true forced: true
transferName: true transferName: true
@@ -107,6 +119,7 @@
# this is the monkey polymorph for artifact. # this is the monkey polymorph for artifact.
- type: polymorph - type: polymorph
id: ArtifactMonkey id: ArtifactMonkey
configuration:
entity: MobMonkey entity: MobMonkey
forced: true forced: true
transferName: true transferName: true
@@ -118,6 +131,7 @@
- type: polymorph - type: polymorph
id: ArtifactCluwne id: ArtifactCluwne
configuration:
entity: MobCluwne entity: MobCluwne
forced: true forced: true
transferName: true transferName: true
@@ -129,6 +143,7 @@
- type: polymorph - type: polymorph
id: ArtifactLizard id: ArtifactLizard
configuration:
entity: MobLizard entity: MobLizard
forced: true forced: true
transferName: true transferName: true
@@ -140,6 +155,7 @@
- type: polymorph - type: polymorph
id: ArtifactLuminous id: ArtifactLuminous
configuration:
entity: MobLuminousPerson entity: MobLuminousPerson
forced: true forced: true
transferName: true transferName: true

View File

@@ -515,14 +515,14 @@
targetDepth: 2 targetDepth: 2
effectHint: artifact-effect-hint-polymorph effectHint: artifact-effect-hint-polymorph
components: components:
- type: PolyArtifact - type: PolyOthersArtifact
- type: artifactEffect - type: artifactEffect
id: EffectPolyLizard id: EffectPolyLizard
targetDepth: 2 targetDepth: 2
effectHint: artifact-effect-hint-polymorph effectHint: artifact-effect-hint-polymorph
components: components:
- type: PolyArtifact - type: PolyOthersArtifact
polymorphPrototypeName: ArtifactLizard polymorphPrototypeName: ArtifactLizard
- type: artifactEffect - type: artifactEffect
@@ -530,7 +530,7 @@
targetDepth: 3 targetDepth: 3
effectHint: artifact-effect-hint-polymorph effectHint: artifact-effect-hint-polymorph
components: components:
- type: PolyArtifact - type: PolyOthersArtifact
polymorphPrototypeName: ArtifactLuminous polymorphPrototypeName: ArtifactLuminous
- type: artifactEffect - type: artifactEffect