Fix polymorphed null error (#11571)

This commit is contained in:
Leon Friedrich
2022-10-02 07:16:55 +13:00
committed by GitHub
parent 8389bde2c0
commit d43ed3210c
3 changed files with 43 additions and 23 deletions

View File

@@ -10,7 +10,8 @@ namespace Content.Server.Polymorph.Components
/// The polymorph prototype, used to track various information
/// about the polymorph
/// </summary>
public PolymorphPrototype Prototype = default!;
[DataField("prototype", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<PolymorphPrototype>))]
public string Prototype = string.Empty;
/// <summary>
/// The original entity that the player will revert back into

View File

@@ -24,6 +24,7 @@ namespace Content.Server.Polymorph.Systems
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IComponentFactory _compFact = default!;
[Dependency] private readonly ServerInventorySystem _inventory = default!;
[Dependency] private readonly SharedHandsSystem _sharedHands = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
@@ -98,10 +99,11 @@ namespace Content.Server.Polymorph.Systems
var child = Spawn(proto.Entity, targetTransformComp.Coordinates);
MakeSentientCommand.MakeSentient(child, EntityManager);
var comp = EnsureComp<PolymorphedEntityComponent>(child);
var comp = _compFact.GetComponent<PolymorphedEntityComponent>();
comp.Owner = child;
comp.Parent = target;
comp.Prototype = proto;
RaiseLocalEvent(child, new PolymorphComponentSetupEvent(), true);
comp.Prototype = proto.ID;
EntityManager.AddComponent(child, comp);
var childXform = Transform(child);
childXform.LocalRotation = targetTransformComp.LocalRotation;
@@ -212,11 +214,6 @@ namespace Content.Server.Polymorph.Systems
}
}
/// <summary>
/// Used after the polymorphedEntity component has it's data set up.
/// </summary>
public sealed class PolymorphComponentSetupEvent : InstantActionEvent { };
public sealed class PolymorphActionEvent : InstantActionEvent
{
/// <summary>

View File

@@ -13,11 +13,13 @@ using Content.Shared.Polymorph;
using Robust.Server.Containers;
using Robust.Shared.Containers;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
namespace Content.Server.Polymorph.Systems
{
public sealed class PolymorphedEntitySystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly PopupSystem _popup = default!;
@@ -29,7 +31,7 @@ namespace Content.Server.Polymorph.Systems
{
base.Initialize();
SubscribeLocalEvent<PolymorphedEntityComponent, PolymorphComponentSetupEvent>(OnInit);
SubscribeLocalEvent<PolymorphedEntityComponent, ComponentStartup>(OnInit);
SubscribeLocalEvent<PolymorphedEntityComponent, RevertPolymorphActionEvent>(OnRevertPolymorphActionEvent);
}
@@ -53,7 +55,11 @@ namespace Content.Server.Polymorph.Systems
if (Deleted(component.Parent))
return;
var proto = component.Prototype;
if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
{
Logger.Error($"{nameof(PolymorphedEntitySystem)} encountered an improperly initialized polymorph component while reverting. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
return;
}
var uidXform = Transform(uid);
var parentXform = Transform(component.Parent);
@@ -65,7 +71,7 @@ namespace Content.Server.Polymorph.Systems
if (_container.TryGetContainingContainer(uid, out var cont))
cont.Insert(component.Parent);
if (component.Prototype.TransferDamage &&
if (proto.TransferDamage &&
TryComp<DamageableComponent>(component.Parent, out var damageParent) &&
_damageable.GetScaledDamage(uid, component.Parent, out var damage) &&
damage != null)
@@ -89,6 +95,7 @@ namespace Content.Server.Polymorph.Systems
slot.EmptyContainer();
foreach (var hand in _sharedHands.EnumerateHeld(uid))
// This causes errors/bugs. Use hand related functions instead.
hand.TryRemoveFromContainer();
}
@@ -105,9 +112,17 @@ namespace Content.Server.Polymorph.Systems
QueueDel(uid);
}
private void OnInit(EntityUid uid, PolymorphedEntityComponent component, PolymorphComponentSetupEvent args)
public void OnInit(EntityUid uid, PolymorphedEntityComponent component, ComponentStartup args)
{
if (component.Prototype.Forced)
if (!_proto.TryIndex(component.Prototype, out PolymorphPrototype? proto))
{
// warning instead of error because of the all-comps one entity test.
Logger.Warning($"{nameof(PolymorphedEntitySystem)} encountered an improperly set up polymorph component while initializing. Entity {ToPrettyString(uid)}. Prototype: {component.Prototype}");
RemCompDeferred(uid, component);
return;
}
if (proto.Forced)
return;
var act = new InstantAction()
@@ -116,7 +131,7 @@ namespace Content.Server.Polymorph.Systems
EntityIcon = component.Parent,
DisplayName = Loc.GetString("polymorph-revert-action-name"),
Description = Loc.GetString("polymorph-revert-action-description"),
UseDelay = TimeSpan.FromSeconds(component.Prototype.Delay),
UseDelay = TimeSpan.FromSeconds(proto.Delay),
};
_actions.AddAction(uid, act, null);
@@ -126,19 +141,26 @@ namespace Content.Server.Polymorph.Systems
{
base.Update(frameTime);
foreach (var entity in EntityQuery<PolymorphedEntityComponent>())
foreach (var comp in EntityQuery<PolymorphedEntityComponent>())
{
entity.Time += frameTime;
comp.Time += frameTime;
if(entity.Prototype.Duration != null && entity.Time >= entity.Prototype.Duration)
Revert(entity.Owner);
if (!_proto.TryIndex(comp.Prototype, out PolymorphPrototype? proto))
{
Logger.Error($"{nameof(PolymorphedEntitySystem)} encountered an improperly initialized polymorph component while updating. Entity {ToPrettyString(comp.Owner)}. Prototype: {comp.Prototype}");
RemCompDeferred(comp.Owner, comp);
continue;
}
if (!TryComp<MobStateComponent>(entity.Owner, out var mob))
if(proto.Duration != null && comp.Time >= proto.Duration)
Revert(comp.Owner);
if (!TryComp<MobStateComponent>(comp.Owner, out var mob))
continue;
if ((entity.Prototype.RevertOnDeath && mob.IsDead()) ||
(entity.Prototype.RevertOnCrit && mob.IsCritical()))
Revert(entity.Owner);
if ((proto.RevertOnDeath && mob.IsDead()) ||
(proto.RevertOnCrit && mob.IsCritical()))
Revert(comp.Owner);
}
}
}