Guardian bugfixes (#21467)

This commit is contained in:
Leon Friedrich
2023-11-07 14:16:32 +11:00
committed by GitHub
parent 2a9e08b906
commit fb60a56950
3 changed files with 61 additions and 32 deletions

View File

@@ -9,24 +9,26 @@ namespace Content.Server.Guardian
/// <summary> /// <summary>
/// The guardian host entity /// The guardian host entity
/// </summary> /// </summary>
public EntityUid Host; [DataField]
public EntityUid? Host;
/// <summary> /// <summary>
/// Percentage of damage reflected from the guardian to the host /// Percentage of damage reflected from the guardian to the host
/// </summary> /// </summary>
[DataField("damageShare")] [DataField]
public float DamageShare { get; set; } = 0.65f; public float DamageShare { get; set; } = 0.65f;
/// <summary> /// <summary>
/// Maximum distance the guardian can travel before it's forced to recall, use YAML to set /// Maximum distance the guardian can travel before it's forced to recall, use YAML to set
/// </summary> /// </summary>
[DataField("distanceAllowed")] [DataField]
public float DistanceAllowed { get; set; } = 5f; public float DistanceAllowed { get; set; } = 5f;
/// <summary> /// <summary>
/// If the guardian is currently manifested /// If the guardian is currently manifested
/// </summary> /// </summary>
public bool GuardianLoose = false; [DataField]
public bool GuardianLoose;
} }
} }

View File

@@ -1,6 +1,5 @@
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Guardian namespace Content.Server.Guardian
{ {
@@ -16,6 +15,7 @@ namespace Content.Server.Guardian
/// <remarks> /// <remarks>
/// Can be null if the component is added at any time. /// Can be null if the component is added at any time.
/// </remarks> /// </remarks>
[DataField]
public EntityUid? HostedGuardian; public EntityUid? HostedGuardian;
/// <summary> /// <summary>
@@ -23,9 +23,9 @@ namespace Content.Server.Guardian
/// </summary> /// </summary>
[ViewVariables] public ContainerSlot GuardianContainer = default!; [ViewVariables] public ContainerSlot GuardianContainer = default!;
[DataField("action", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] [DataField]
public string Action = "ActionToggleGuardian"; public EntProtoId Action = "ActionToggleGuardian";
[DataField("actionEntity")] public EntityUid? ActionEntity; [DataField] public EntityUid? ActionEntity;
} }
} }

View File

@@ -41,10 +41,11 @@ namespace Content.Server.Guardian
SubscribeLocalEvent<GuardianCreatorComponent, ExaminedEvent>(OnCreatorExamine); SubscribeLocalEvent<GuardianCreatorComponent, ExaminedEvent>(OnCreatorExamine);
SubscribeLocalEvent<GuardianCreatorComponent, GuardianCreatorDoAfterEvent>(OnDoAfter); SubscribeLocalEvent<GuardianCreatorComponent, GuardianCreatorDoAfterEvent>(OnDoAfter);
SubscribeLocalEvent<GuardianComponent, ComponentShutdown>(OnGuardianShutdown);
SubscribeLocalEvent<GuardianComponent, MoveEvent>(OnGuardianMove); SubscribeLocalEvent<GuardianComponent, MoveEvent>(OnGuardianMove);
SubscribeLocalEvent<GuardianComponent, DamageChangedEvent>(OnGuardianDamaged); SubscribeLocalEvent<GuardianComponent, DamageChangedEvent>(OnGuardianDamaged);
SubscribeLocalEvent<GuardianComponent, PlayerAttachedEvent>(OnGuardianPlayer); SubscribeLocalEvent<GuardianComponent, PlayerAttachedEvent>(OnGuardianPlayerAttached);
SubscribeLocalEvent<GuardianComponent, PlayerDetachedEvent>(OnGuardianUnplayer); SubscribeLocalEvent<GuardianComponent, PlayerDetachedEvent>(OnGuardianPlayerDetached);
SubscribeLocalEvent<GuardianHostComponent, ComponentInit>(OnHostInit); SubscribeLocalEvent<GuardianHostComponent, ComponentInit>(OnHostInit);
SubscribeLocalEvent<GuardianHostComponent, MoveEvent>(OnHostMove); SubscribeLocalEvent<GuardianHostComponent, MoveEvent>(OnHostMove);
@@ -56,6 +57,21 @@ namespace Content.Server.Guardian
SubscribeLocalEvent<GuardianComponent, AttackAttemptEvent>(OnGuardianAttackAttempt); SubscribeLocalEvent<GuardianComponent, AttackAttemptEvent>(OnGuardianAttackAttempt);
} }
private void OnGuardianShutdown(EntityUid uid, GuardianComponent component, ComponentShutdown args)
{
var host = component.Host;
component.Host = null;
if (!TryComp(host, out GuardianHostComponent? hostComponent))
return;
hostComponent.GuardianContainer.Remove(uid);
hostComponent.HostedGuardian = null;
Dirty(host.Value, hostComponent);
QueueDel(hostComponent.ActionEntity);
hostComponent.ActionEntity = null;
}
private void OnPerformAction(EntityUid uid, GuardianHostComponent component, GuardianToggleActionEvent args) private void OnPerformAction(EntityUid uid, GuardianHostComponent component, GuardianToggleActionEvent args)
{ {
if (args.Handled) if (args.Handled)
@@ -67,24 +83,29 @@ namespace Content.Server.Guardian
args.Handled = true; args.Handled = true;
} }
private void OnGuardianUnplayer(EntityUid uid, GuardianComponent component, PlayerDetachedEvent args) private void OnGuardianPlayerDetached(EntityUid uid, GuardianComponent component, PlayerDetachedEvent args)
{ {
var host = component.Host; var host = component.Host;
if (!TryComp<GuardianHostComponent>(host, out var hostComponent) || TerminatingOrDeleted(host.Value))
if (!TryComp<GuardianHostComponent>(host, out var hostComponent) || LifeStage(host) >= EntityLifeStage.MapInitialized) {
QueueDel(uid);
return; return;
}
RetractGuardian(host, hostComponent, uid, component); RetractGuardian(host.Value, hostComponent, uid, component);
} }
private void OnGuardianPlayer(EntityUid uid, GuardianComponent component, PlayerAttachedEvent args) private void OnGuardianPlayerAttached(EntityUid uid, GuardianComponent component, PlayerAttachedEvent args)
{ {
var host = component.Host; var host = component.Host;
if (!HasComp<GuardianHostComponent>(host)) if (!HasComp<GuardianHostComponent>(host))
{
QueueDel(uid);
return; return;
}
_popupSystem.PopupEntity(Loc.GetString("guardian-available"), host, host); _popupSystem.PopupEntity(Loc.GetString("guardian-available"), host.Value, host.Value);
} }
private void OnHostInit(EntityUid uid, GuardianHostComponent component, ComponentInit args) private void OnHostInit(EntityUid uid, GuardianHostComponent component, ComponentInit args)
@@ -95,14 +116,16 @@ namespace Content.Server.Guardian
private void OnHostShutdown(EntityUid uid, GuardianHostComponent component, ComponentShutdown args) private void OnHostShutdown(EntityUid uid, GuardianHostComponent component, ComponentShutdown args)
{ {
if (component.HostedGuardian == null) if (component.HostedGuardian is not {} guardian)
return; return;
if (HasComp<HandsComponent>(component.HostedGuardian.Value)) // Ensure held items are dropped before deleting guardian.
if (HasComp<HandsComponent>(guardian))
_bodySystem.GibBody(component.HostedGuardian.Value); _bodySystem.GibBody(component.HostedGuardian.Value);
EntityManager.QueueDeleteEntity(component.HostedGuardian.Value); QueueDel(guardian);
_actionSystem.RemoveAction(uid, component.ActionEntity); QueueDel(component.ActionEntity);
component.ActionEntity = null;
} }
private void OnGuardianAttackAttempt(EntityUid uid, GuardianComponent component, AttackAttemptEvent args) private void OnGuardianAttackAttempt(EntityUid uid, GuardianComponent component, AttackAttemptEvent args)
@@ -117,7 +140,7 @@ namespace Content.Server.Guardian
public void ToggleGuardian(EntityUid user, GuardianHostComponent hostComponent) public void ToggleGuardian(EntityUid user, GuardianHostComponent hostComponent)
{ {
if (hostComponent.HostedGuardian == null || !TryComp<GuardianComponent>(hostComponent.HostedGuardian, out var guardianComponent)) if (!TryComp<GuardianComponent>(hostComponent.HostedGuardian, out var guardianComponent))
return; return;
if (guardianComponent.GuardianLoose) if (guardianComponent.GuardianLoose)
@@ -134,7 +157,7 @@ namespace Content.Server.Guardian
if (args.Handled) if (args.Handled)
return; return;
//args.Handled = true; args.Handled = true;
UseCreator(args.User, args.User, uid, component); UseCreator(args.User, args.User, uid, component);
} }
@@ -143,7 +166,7 @@ namespace Content.Server.Guardian
if (args.Handled || args.Target == null || !args.CanReach) if (args.Handled || args.Target == null || !args.CanReach)
return; return;
//args.Handled = true; args.Handled = true;
UseCreator(args.User, args.Target.Value, uid, component); UseCreator(args.User, args.Target.Value, uid, component);
} }
private void UseCreator(EntityUid user, EntityUid target, EntityUid injector, GuardianCreatorComponent component) private void UseCreator(EntityUid user, EntityUid target, EntityUid injector, GuardianCreatorComponent component)
@@ -194,6 +217,7 @@ namespace Content.Server.Guardian
if (TryComp<GuardianComponent>(guardian, out var guardianComp)) if (TryComp<GuardianComponent>(guardian, out var guardianComp))
{ {
guardianComp.Host = args.Args.Target.Value; guardianComp.Host = args.Args.Target.Value;
// TODO this should be a data field, not a hardcoded path
_audio.Play("/Audio/Effects/guardian_inject.ogg", Filter.Pvs(args.Args.Target.Value), args.Args.Target.Value, true); _audio.Play("/Audio/Effects/guardian_inject.ogg", Filter.Pvs(args.Args.Target.Value), args.Args.Target.Value, true);
_popupSystem.PopupEntity(Loc.GetString("guardian-created"), args.Args.Target.Value, args.Args.Target.Value); _popupSystem.PopupEntity(Loc.GetString("guardian-created"), args.Args.Target.Value, args.Args.Target.Value);
// Exhaust the activator // Exhaust the activator
@@ -201,8 +225,8 @@ namespace Content.Server.Guardian
} }
else else
{ {
Logger.ErrorS("guardian", $"Tried to spawn a guardian that doesn't have {nameof(GuardianComponent)}"); Log.Error($"Tried to spawn a guardian that doesn't have {nameof(GuardianComponent)}");
EntityManager.QueueDeleteEntity(guardian); QueueDel(guardian);
} }
args.Handled = true; args.Handled = true;
@@ -219,13 +243,14 @@ namespace Content.Server.Guardian
if (args.NewMobState == MobState.Critical) if (args.NewMobState == MobState.Critical)
{ {
_popupSystem.PopupEntity(Loc.GetString("guardian-host-critical-warn"), component.HostedGuardian.Value, component.HostedGuardian.Value); _popupSystem.PopupEntity(Loc.GetString("guardian-host-critical-warn"), component.HostedGuardian.Value, component.HostedGuardian.Value);
// TODO this should be a data field, not a hardcoded path
_audio.Play("/Audio/Effects/guardian_warn.ogg", Filter.Pvs(component.HostedGuardian.Value), component.HostedGuardian.Value, true); _audio.Play("/Audio/Effects/guardian_warn.ogg", Filter.Pvs(component.HostedGuardian.Value), component.HostedGuardian.Value, true);
} }
else if (args.NewMobState == MobState.Dead) else if (args.NewMobState == MobState.Dead)
{ {
//TODO: Replace WithVariation with datafield //TODO: Replace WithVariation with datafield
_audio.Play("/Audio/Voice/Human/malescream_guardian.ogg", Filter.Pvs(uid), uid, true, AudioHelpers.WithVariation(0.20f)); _audio.Play("/Audio/Voice/Human/malescream_guardian.ogg", Filter.Pvs(uid), uid, true, AudioHelpers.WithVariation(0.20f));
EntityManager.RemoveComponent<GuardianHostComponent>(uid); RemComp<GuardianHostComponent>(uid);
} }
} }
@@ -234,11 +259,11 @@ namespace Content.Server.Guardian
/// </summary> /// </summary>
private void OnGuardianDamaged(EntityUid uid, GuardianComponent component, DamageChangedEvent args) private void OnGuardianDamaged(EntityUid uid, GuardianComponent component, DamageChangedEvent args)
{ {
if (args.DamageDelta == null) if (args.DamageDelta == null || component.Host == null || component.DamageShare > 0)
return; return;
_damageSystem.TryChangeDamage(component.Host, args.DamageDelta * component.DamageShare, origin: args.Origin); _damageSystem.TryChangeDamage(component.Host, args.DamageDelta * component.DamageShare, origin: args.Origin);
_popupSystem.PopupEntity(Loc.GetString("guardian-entity-taking-damage"), component.Host, component.Host); _popupSystem.PopupEntity(Loc.GetString("guardian-entity-taking-damage"), component.Host.Value, component.Host.Value);
} }
@@ -256,8 +281,7 @@ namespace Content.Server.Guardian
/// </summary> /// </summary>
private void OnHostMove(EntityUid uid, GuardianHostComponent component, ref MoveEvent args) private void OnHostMove(EntityUid uid, GuardianHostComponent component, ref MoveEvent args)
{ {
if (component.HostedGuardian == null || if (!TryComp(component.HostedGuardian, out GuardianComponent? guardianComponent) ||
!TryComp(component.HostedGuardian, out GuardianComponent? guardianComponent) ||
!guardianComponent.GuardianLoose) !guardianComponent.GuardianLoose)
{ {
return; return;
@@ -271,10 +295,10 @@ namespace Content.Server.Guardian
/// </summary> /// </summary>
private void OnGuardianMove(EntityUid uid, GuardianComponent component, ref MoveEvent args) private void OnGuardianMove(EntityUid uid, GuardianComponent component, ref MoveEvent args)
{ {
if (!component.GuardianLoose) if (!component.GuardianLoose || component.Host == null)
return; return;
CheckGuardianMove(component.Host, uid, guardianComponent: component); CheckGuardianMove(component.Host.Value, uid, guardianComponent: component);
} }
/// <summary> /// <summary>
@@ -288,6 +312,9 @@ namespace Content.Server.Guardian
TransformComponent? hostXform = null, TransformComponent? hostXform = null,
TransformComponent? guardianXform = null) TransformComponent? guardianXform = null)
{ {
if (TerminatingOrDeleted(guardianUid) || TerminatingOrDeleted(hostUid))
return;
if (!Resolve(hostUid, ref hostComponent, ref hostXform) || if (!Resolve(hostUid, ref hostComponent, ref hostXform) ||
!Resolve(guardianUid, ref guardianComponent, ref guardianXform)) !Resolve(guardianUid, ref guardianComponent, ref guardianXform))
{ {