Delta-v/Content.Server/_Impstation/Revenant/EntitySystems/RevenantAnimatedSystem.cs

208 lines
8.0 KiB
C#

using Content.Shared.Popups;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Server.Revenant.Components;
using Content.Shared.DoAfter;
using Content.Shared.Revenant.Components;
using Content.Server.NPC.HTN;
using Content.Server.NPC;
using Content.Shared.Weapons.Melee;
using Content.Shared.CombatMode;
using Content.Shared.NPC.Components;
using Content.Shared.NPC.Systems;
using Robust.Shared.Prototypes;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Movement.Components;
using Content.Shared.Item.ItemToggle;
using Content.Shared.Item.ItemToggle.Components;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Systems;
using Content.Shared.Cuffs.Components;
using Content.Shared.Movement.Systems;
using Robust.Shared.Player;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Mobs;
using Robust.Shared.Timing;
using Content.Shared.Construction.Components;
using Content.Shared.Trigger.Components;
namespace Content.Server.Revenant.EntitySystems;
public sealed partial class RevenantAnimatedSystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly NpcFactionSystem _factionSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly ItemToggleSystem _itemToggleSystem = default!;
[Dependency] private readonly SharedGunSystem _gunSystem = default!;
[Dependency] private readonly MovementSpeedModifierSystem _moveSpeed = default!;
[Dependency] private readonly MobThresholdSystem _thresholds = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RevenantAnimatedComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<RevenantAnimatedComponent, ComponentShutdown>(OnComponentShutdown);
SubscribeLocalEvent<RevenantAnimatedComponent, MobStateChangedEvent>(OnMobStateChange);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var enumerator = EntityQueryEnumerator<RevenantAnimatedComponent>();
while (enumerator.MoveNext(out var uid, out var animate))
{
if (animate.EndTime == null)
continue;
if (animate.EndTime <= _gameTiming.CurTime)
InanimateTarget(uid, animate);
}
}
private void OnComponentStartup(Entity<RevenantAnimatedComponent> ent, ref ComponentStartup _)
{
if (ent.Comp.LifeStage != ComponentLifeStage.Starting)
return;
// Turn on welding rods and stun prods
if (HasComp<ItemToggleMeleeWeaponComponent>(ent.Owner) && TryComp<ItemToggleComponent>(ent.Owner, out var toggle))
_itemToggleSystem.TryActivate((ent.Owner, toggle));
_popup.PopupEntity(Loc.GetString("revenant-animate-item-animate", ("target", ent.Owner)), ent.Owner, Filter.Pvs(ent.Owner), true);
// Add melee damage if an item doesn't already have it
if (EnsureHelper<MeleeWeaponComponent>(ent, out var melee))
melee.Damage = new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Blunt"), 5);
EnsureHelper<InputMoverComponent>(ent);
EnsureHelper<MovementSpeedModifierComponent>(ent, out var moveSpeed);
if (ent.Comp.Revenant != null)
_moveSpeed.ChangeBaseSpeed(ent,
ent.Comp.Revenant.Value.Comp.AnimateWalkSpeed,
ent.Comp.Revenant.Value.Comp.AnimateSprintSpeed,
MovementSpeedModifierComponent.DefaultAcceleration,
moveSpeed
);
else
_moveSpeed.ChangeBaseSpeed(ent,
RevenantComponent.DefaultAnimateWalkSpeed,
RevenantComponent.DefaultAnimateSprintSpeed,
MovementSpeedModifierComponent.DefaultAcceleration,
moveSpeed
);
EnsureHelper<NpcFactionMemberComponent>(ent, out var factions);
_factionSystem.ClearFactions((ent, factions));
_factionSystem.AddFaction((ent, factions), "SimpleHostile");
// For things like handcuffs
EnsureHelper<DoAfterComponent>(ent);
EnsureHelper<HTNComponent>(ent, out var htn);
if (HasComp<GunComponent>(ent))
{
// Goals: Magdump into any nearby creatures, and melee hit them if empty
if (ent.Comp.Revenant != null && ent.Comp.Revenant.Value.Comp.AnimateCanBoltGuns && TryComp<ChamberMagazineAmmoProviderComponent>(ent, out var bolt))
_gunSystem.SetBoltClosed(ent, bolt, true);
htn.RootTask = new HTNCompoundTask() { Task = "SimpleRangedHostileCompound" };
}
else if (HasComp<HandcuffComponent>(ent))
// Goals: Jump into any creature's pockets/hands and cuff them
htn.RootTask = new HTNCompoundTask() { Task = "AnimatedHandcuffsCompound" };
else if (HasComp<TimerTriggerComponent>(ent))
// Goals: Jump into any creature's pockets/hands and activate self
htn.RootTask = new HTNCompoundTask() { Task = "AnimatedGrenadeCompound" };
else
// Goals: Fist fight anyone near you
htn.RootTask = new HTNCompoundTask() { Task = "SimpleHostileCompound" };
htn.Blackboard.SetValue(NPCBlackboard.Owner, ent.Owner);
EnsureHelper<DamageableComponent>(ent);
EnsureHelper<MobStateComponent>(ent);
EnsureHelper<MobThresholdsComponent>(ent, out var thresholds);
_thresholds.SetMobStateThreshold(ent, 30, MobState.Dead, thresholds);
EnsureHelper<CombatModeComponent>(ent);
}
private void OnComponentShutdown(Entity<RevenantAnimatedComponent> ent, ref ComponentShutdown _)
{
if (ent.Comp.LifeStage != ComponentLifeStage.Stopping)
return;
foreach (var comp in ent.Comp.AddedComponents)
{
if (comp.Deleted)
continue;
RemCompDeferred(ent, comp);
}
_popup.PopupEntity(Loc.GetString("revenant-animate-item-inanimate", ("target", ent)), ent, Filter.Pvs(ent), true);
}
private void OnMobStateChange(Entity<RevenantAnimatedComponent> ent, ref MobStateChangedEvent args)
{
if (args.NewMobState == MobState.Dead)
{
InanimateTarget(ent);
}
}
// Returns true if a new component was added to the target.
private bool EnsureHelper<T>(Entity<RevenantAnimatedComponent> target, out T comp) where T : Component, new()
{
if (TryComp<T>(target, out var existing))
{
comp = existing;
return false;
}
comp = AddComp<T>(target);
target.Comp.AddedComponents.Add(comp);
return true;
}
private bool EnsureHelper<T>(Entity<RevenantAnimatedComponent> target) where T : Component, new()
{
return EnsureHelper<T>(target, out _);
}
public bool CanAnimateObject(EntityUid target)
{
return !(HasComp<AnchorableComponent>(target) || HasComp<MindContainerComponent>(target)
|| HasComp<HTNComponent>(target) || HasComp<RevenantAnimatedComponent>(target));
}
public bool TryAnimateObject(EntityUid target, TimeSpan? duration = null, Entity<RevenantComponent>? revenant = null)
{
if (!CanAnimateObject(target))
return false;
var animate = EnsureComp<RevenantAnimatedComponent>(target);
animate.Revenant = revenant;
if (duration != null)
animate.EndTime = _gameTiming.CurTime + duration.Value;
else if (revenant != null)
animate.EndTime = _gameTiming.CurTime + revenant.Value.Comp.AnimateTime;
return true;
}
public void InanimateTarget(EntityUid target, RevenantAnimatedComponent? comp = null)
{
if (!target.Valid || !Resolve(target, ref comp))
return;
RemComp<RevenantAnimatedComponent>(target);
}
}