* - add: Flash protection for wiz hardsuit helmet. * - tweak: Cheaper wiz melee weapons. * - add: Rework alt lightning. * - fix: Timestop fixes. * - add: Don't end round on midround wizard death. * - tweak: Better shield. * - fix: Some fixes. * - fix: Fix wizard teleport pulling. * - add: Improve arc. * - add: Update knock. * - add: Update knock desc. * - add: Arcane Barrage.
192 lines
6.9 KiB
C#
192 lines
6.9 KiB
C#
using System.Linq;
|
|
using System.Numerics;
|
|
using Content.Shared.ActionBlocker;
|
|
using Content.Shared.Emoting;
|
|
using Content.Shared.Hands;
|
|
using Content.Shared.Interaction.Events;
|
|
using Content.Shared.Inventory.Events;
|
|
using Content.Shared.Item;
|
|
using Content.Shared.Movement.Events;
|
|
using Content.Shared.Speech;
|
|
using Content.Shared.Standing.Systems;
|
|
using Content.Shared.Throwing;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.Physics;
|
|
using Robust.Shared.Physics.Components;
|
|
using Robust.Shared.Physics.Events;
|
|
using Robust.Shared.Physics.Systems;
|
|
using Robust.Shared.Spawners;
|
|
|
|
namespace Content.Shared._White.Wizard.Timestop;
|
|
|
|
public sealed class FreezeContactsSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
|
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<FreezeContactsComponent, StartCollideEvent>(OnEntityEnter);
|
|
SubscribeLocalEvent<FreezeContactsComponent, EndCollideEvent>(OnEntityExit);
|
|
|
|
SubscribeLocalEvent<FrozenComponent, ComponentInit>(OnInit);
|
|
SubscribeLocalEvent<FrozenComponent, ComponentRemove>(OnRemove);
|
|
SubscribeLocalEvent<FrozenComponent, PreventCollideEvent>(OnPreventCollide);
|
|
SubscribeLocalEvent<FrozenComponent, EntGotInsertedIntoContainerMessage>(OnGetInserted);
|
|
|
|
SubscribeLocalEvent<FrozenComponent, StandAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, DownAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, SpeakAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, EmoteAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, ChangeDirectionAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, UpdateCanMoveEvent>(OnMoveAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, InteractionAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, UseAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, ThrowAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, DropAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, AttackAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, PickupAttemptEvent>(OnAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, IsEquippingAttemptEvent>(OnEquipAttempt);
|
|
SubscribeLocalEvent<FrozenComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
|
|
}
|
|
|
|
private void OnMoveAttempt(EntityUid uid, FrozenComponent component, UpdateCanMoveEvent args)
|
|
{
|
|
if (component.LifeStage > ComponentLifeStage.Running)
|
|
return;
|
|
|
|
args.Cancel();
|
|
}
|
|
|
|
private void OnAttempt(EntityUid uid, FrozenComponent component, CancellableEntityEventArgs args)
|
|
{
|
|
args.Cancel();
|
|
}
|
|
|
|
private void OnEquipAttempt(EntityUid uid, FrozenComponent component, IsEquippingAttemptEvent args)
|
|
{
|
|
// is this a self-equip, or are they being stripped?
|
|
if (args.Equipee == uid)
|
|
args.Cancel();
|
|
}
|
|
|
|
private void OnUnequipAttempt(EntityUid uid, FrozenComponent component, IsUnequippingAttemptEvent args)
|
|
{
|
|
// is this a self-equip, or are they being stripped?
|
|
if (args.Unequipee == uid)
|
|
args.Cancel();
|
|
}
|
|
|
|
private void OnGetInserted(Entity<FrozenComponent> ent, ref EntGotInsertedIntoContainerMessage args)
|
|
{
|
|
RemCompDeferred<FrozenComponent>(ent);
|
|
}
|
|
|
|
private void OnPreventCollide(Entity<FrozenComponent> ent, ref PreventCollideEvent args)
|
|
{
|
|
if (args.OurBody.BodyType == BodyType.Dynamic && !HasComp<FreezeContactsComponent>(args.OtherEntity))
|
|
args.Cancelled = true;
|
|
}
|
|
|
|
private void OnRemove(Entity<FrozenComponent> ent, ref ComponentRemove args)
|
|
{
|
|
var (uid, comp) = ent;
|
|
|
|
_blocker.UpdateCanMove(uid);
|
|
|
|
if (_container.IsEntityOrParentInContainer(uid))
|
|
return;
|
|
|
|
if (!TryComp(uid, out PhysicsComponent? physics))
|
|
return;
|
|
|
|
_physics.SetLinearVelocity(uid, comp.OldLinearVelocity, false, body: physics);
|
|
_physics.SetAngularVelocity(uid, comp.OldAngularVelocity, body: physics);
|
|
}
|
|
|
|
private void OnInit(Entity<FrozenComponent> ent, ref ComponentInit args)
|
|
{
|
|
var (uid, comp) = ent;
|
|
|
|
_blocker.UpdateCanMove(uid);
|
|
|
|
if (!TryComp(uid, out PhysicsComponent? physics))
|
|
return;
|
|
|
|
comp.OldLinearVelocity = physics.LinearVelocity;
|
|
comp.OldAngularVelocity = physics.AngularVelocity;
|
|
|
|
_physics.SetLinearVelocity(uid, Vector2.Zero, false, body: physics);
|
|
_physics.SetAngularVelocity(uid, 0f, body: physics);
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
|
|
var query = AllEntityQuery<FrozenComponent, FixturesComponent, PhysicsComponent>();
|
|
|
|
while (query.MoveNext(out var uid, out var frozen, out var fixtures, out var physics))
|
|
{
|
|
frozen.Lifetime -= frameTime;
|
|
|
|
if (physics.LinearVelocity != Vector2.Zero)
|
|
_physics.SetLinearVelocity(uid, Vector2.Zero, manager: fixtures, body: physics);
|
|
|
|
if (physics.AngularVelocity != 0f)
|
|
_physics.SetAngularVelocity(uid, 0f, manager: fixtures, body: physics);
|
|
|
|
if (frozen.Lifetime > 0)
|
|
continue;
|
|
|
|
RemCompDeferred<FrozenComponent>(uid);
|
|
}
|
|
}
|
|
|
|
private void OnEntityExit(Entity<FreezeContactsComponent> ent, ref EndCollideEvent args)
|
|
{
|
|
if (IsTouchingFrozenContacts(args.OtherEntity, args.OtherBody))
|
|
return;
|
|
|
|
RemCompDeferred<FrozenComponent>(args.OtherEntity);
|
|
}
|
|
|
|
private void OnEntityEnter(Entity<FreezeContactsComponent> ent, ref StartCollideEvent args)
|
|
{
|
|
FreezeEm(args.OtherEntity, ent);
|
|
}
|
|
|
|
private void FreezeEm(EntityUid uid, EntityUid freezeContact)
|
|
{
|
|
if (HasComp<FrozenComponent>(uid))
|
|
return;
|
|
|
|
var frozen = EnsureComp<FrozenComponent>(uid);
|
|
|
|
if (!TryComp(freezeContact, out TimedDespawnComponent? timedDespawn))
|
|
return;
|
|
|
|
frozen.Lifetime = timedDespawn.Lifetime;
|
|
|
|
if (TryComp(uid, out TimedDespawnComponent? otherTimedDespawn))
|
|
otherTimedDespawn.Lifetime += timedDespawn.Lifetime;
|
|
|
|
if (!TryComp(uid, out ThrownItemComponent? thrownItem))
|
|
return;
|
|
|
|
if (thrownItem.LandTime != null)
|
|
thrownItem.LandTime = thrownItem.LandTime.Value + TimeSpan.FromSeconds(timedDespawn.Lifetime);
|
|
|
|
if (thrownItem.ThrownTime != null)
|
|
thrownItem.ThrownTime = thrownItem.ThrownTime.Value + TimeSpan.FromSeconds(timedDespawn.Lifetime);
|
|
}
|
|
|
|
private bool IsTouchingFrozenContacts(EntityUid uid, PhysicsComponent body)
|
|
{
|
|
return _physics.GetContactingEntities(uid, body).Any(HasComp<FreezeContactsComponent>);
|
|
}
|
|
}
|