mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-12 03:41:14 +03:00
* Solving #43723 by making zombies clumsy (they are unable to hold anything in their hands, passing items to them will fail). Also made zombies uncuff themselves whenever they transform (seeing as they no longer lose their hands meaning that cuffs would otherwise remain on them) * Cleaning up the code * Renamed ClumsyHoldStatusEffectComponent.cs to ClumsyGrabStatusEffectComponent.cs (and renamed associated files). I think "ClumsyGrab" works better than "ClumsyHold" (as the effect happens when the item is first grabbed, not whilst the item is being held). everything still works Reordered appropriate functions in ClumsyStatusTest.cs and ClumsyStatusEffectSystem.cs to retain alphabetical order. * oopsies :p * Appeased the YAMLLinter (at the cost of a somewhat hackier implementation). ZombieSystem.Transform.cs now applies the zombie clumsiness via creating a new PermanentStatusEffectComponent with StatusEffectClumsyZombie as its status effect. * requested changes have been made (also re-added newline to end of clumsy-component.ftl because it has a newline at the end of it on the master branch, I guess it's probably supposed to be there) * reordering so private members (including new one) are before the internal member * hands are forcibly emptied - even if something's glued to them. * UnZombify should remove the lingering ZombieClumsy status effect (still needs to revert the rest of the zombification process, but at least the new bit I added can be undone) * Minor refactor of my own refactor. New order of operations: 1. Uncuffs zombie (if needed) 2. Attempts to `DropAll` items from hands 3. Iterates through hand containers to empty them (removes otherwise unremovable items from hands) Will refactor process to force drop all items if #45844 becomes implementable + is merged. * formatting * how the hell did the metabolizer code go missing!? * uncuffing now happens in a safer way less likely to accidentally infinitely loop * tweaking that one comment I was asked to tweak (this is unrelated to the hand malarkey) hopefully it won't lead to any merge conflicts later on * formatting * file style --------- Co-authored-by: Pok245 <113675512+Pok27@users.noreply.github.com>
199 lines
8.4 KiB
C#
199 lines
8.4 KiB
C#
using System.Numerics;
|
|
using Content.IntegrationTests.Fixtures.Attributes;
|
|
using Content.IntegrationTests.Tests.Helpers;
|
|
using Content.IntegrationTests.Tests.Interaction;
|
|
using Content.Shared.CCVar;
|
|
using Content.Shared.Chemistry.Events;
|
|
using Content.Shared.Climbing.Components;
|
|
using Content.Shared.Climbing.Events;
|
|
using Content.Shared.Climbing.Systems;
|
|
using Content.Shared.Clumsy;
|
|
using Content.Shared.Hands;
|
|
using Content.Shared.Medical;
|
|
using Content.Shared.Mobs.Components;
|
|
using Content.Shared.StatusEffectNew;
|
|
using Content.Shared.Stunnable;
|
|
using Content.Shared.Throwing;
|
|
using Content.Shared.Weapons.Ranged.Events;
|
|
using Robust.Shared.GameObjects;
|
|
using static Content.IntegrationTests.Tests.Clumsy.ClumsyTestPrototypes;
|
|
|
|
namespace Content.IntegrationTests.Tests.Clumsy;
|
|
|
|
[TestFixture]
|
|
[TestOf(typeof(ClumsyStatusEffectSystem))]
|
|
public sealed class ClumsyStatusTest : InteractionTest
|
|
{
|
|
private sealed class CatchListenerSystem : TestListenerSystem<CatchAttemptEvent>;
|
|
private sealed class ClimbListenerSystem : TestListenerSystem<SelfBeforeClimbEvent>;
|
|
private sealed class DefibListenerSystem : TestListenerSystem<SelfBeforeDefibrillatorZapsEvent>;
|
|
private sealed class GunListenerSystem : TestListenerSystem<SelfBeforeGunShotEvent>;
|
|
private sealed class InjectListenerSystem : TestListenerSystem<SelfBeforeInjectEvent>;
|
|
private sealed class BeforeEquipListenerSystem : TestListenerSystem<BeforeEquippingHandEvent>;
|
|
|
|
[SidedDependency(Side.Server)] private readonly ClimbSystem _sClimbSystem = default!;
|
|
[SidedDependency(Side.Server)] private readonly StatusEffectsSystem _sStatusSystem = default!;
|
|
[SidedDependency(Side.Server)] private readonly ThrowingSystem _sThrowSystem = default!;
|
|
|
|
[Test, Description("Test that a ball thrown at someone clumsy is not caught.")]
|
|
public async Task TestClumsyCatch()
|
|
{
|
|
await Server.WaitPost(() =>
|
|
{
|
|
SEntMan.EnsureComponent<TestListenerComponent>(SPlayer);
|
|
_sStatusSystem.TrySetStatusEffectDuration(SPlayer, ClumsyStatusAll100);
|
|
});
|
|
|
|
Assume.That(_sStatusSystem.HasStatusEffect(SPlayer, ClumsyStatusAll100), Is.True);
|
|
|
|
await Server.WaitPost(() =>
|
|
{
|
|
var location = SEntMan.EnsureComponent<TransformComponent>(SPlayer).Coordinates;
|
|
var ball = SSpawnAtPosition(BallProto, location);
|
|
|
|
_sThrowSystem.TryThrow(ball, Vector2.Zero); // Direction doesn't matter because it spawned on top of the player
|
|
});
|
|
|
|
Assert.That(HandSys.ActiveHandIsEmpty((SPlayer,Hands)), Is.True, "Clumsy mob caught the ball.");
|
|
foreach (var ev in GetEvents<CatchAttemptEvent>(SPlayer))
|
|
{
|
|
Assert.That(ev.Cancelled, Is.True, "Clumsy mob didn't cancel a catch event.");
|
|
}
|
|
}
|
|
|
|
[Test, Description("Test that a clumsy mob shocks themselves with a defibrillator.")]
|
|
public async Task TestClumsyDefib()
|
|
{
|
|
await Server.WaitPost(() =>
|
|
{
|
|
SEntMan.EnsureComponent<TestListenerComponent>(SPlayer);
|
|
_sStatusSystem.TrySetStatusEffectDuration(SPlayer, ClumsyStatusAll100);
|
|
});
|
|
|
|
Assume.That(_sStatusSystem.HasStatusEffect(SPlayer, ClumsyStatusAll100), Is.True);
|
|
|
|
await SpawnTarget(TargetProto);
|
|
|
|
await PlaceInHands(DefibProto);
|
|
await Interact();
|
|
await AwaitDoAfters();
|
|
|
|
foreach (var ev in GetEvents<SelfBeforeDefibrillatorZapsEvent>(SPlayer))
|
|
{
|
|
Assert.That(ev.DefibTarget, Is.EqualTo(ev.EntityUsingDefib), "Clumsy mob didn't target themself with a defibrillator.");
|
|
}
|
|
}
|
|
|
|
[Test, Description("Test that a gun explodes in a clumsy mob's face and stuns them.")]
|
|
public async Task TestClumsyGun()
|
|
{
|
|
await Server.WaitPost(() =>
|
|
{
|
|
SEntMan.EnsureComponent<MobStateComponent>(SPlayer); // So that we are a valid target for SharedStunSystem.StunId
|
|
SEntMan.EnsureComponent<TestListenerComponent>(SPlayer);
|
|
|
|
_sStatusSystem.TrySetStatusEffectDuration(SPlayer, ClumsyStatusAll100);
|
|
});
|
|
|
|
Assume.That(_sStatusSystem.HasStatusEffect(SPlayer, ClumsyStatusAll100), Is.True);
|
|
|
|
await SpawnTarget(TargetProto);
|
|
|
|
await PlaceInHands(GunProto);
|
|
await UseInHand(); // Chamber the gun
|
|
await RunSeconds(0.5f); // Guns have a cooldown when picking them up.
|
|
await AttemptShoot(Target);
|
|
|
|
Assert.That(_sStatusSystem.HasStatusEffect(SPlayer, SharedStunSystem.StunId), Is.True, "Clumsy mob wasn't stunned from shooting a gun.");
|
|
foreach (var ev in GetEvents<SelfBeforeGunShotEvent>(SPlayer))
|
|
{
|
|
Assert.That(ev.Cancelled, Is.True, "Clumsy mob didn't cancel gun shoot event.");
|
|
}
|
|
}
|
|
|
|
[Test, Description("Test that a clumsy mob injects themselves with a syringe.")]
|
|
public async Task TestClumsyInject()
|
|
{
|
|
await Server.WaitPost(() =>
|
|
{
|
|
SEntMan.EnsureComponent<TestListenerComponent>(SPlayer);
|
|
_sStatusSystem.TrySetStatusEffectDuration(SPlayer, ClumsyStatusAll100);
|
|
});
|
|
|
|
Assume.That(_sStatusSystem.HasStatusEffect(SPlayer, ClumsyStatusAll100), Is.True);
|
|
|
|
await PlaceInHands(SyringeProto);
|
|
await SpawnTarget(TargetProto);
|
|
|
|
await Interact();
|
|
await AwaitDoAfters();
|
|
|
|
foreach (var ev in GetEvents<SelfBeforeInjectEvent>(SPlayer))
|
|
{
|
|
Assert.That(ev.EntityUsingInjector, Is.EqualTo(ev.TargetGettingInjected), "Clumsy mob didn't target themself with an injector.");
|
|
}
|
|
}
|
|
|
|
[Test, Description("Test that a clumsy mob fails to climb and stuns themselves.")]
|
|
[EnsureCVar(Side.Server, typeof(CCVars), nameof(CCVars.GameTableBonk), true)]
|
|
public async Task TestClumsyClimb()
|
|
{
|
|
await Server.WaitPost(() =>
|
|
{
|
|
SEntMan.EnsureComponent<ClimbingComponent>(SPlayer); // So that we can climb tables
|
|
SEntMan.EnsureComponent<MobStateComponent>(SPlayer); // So that we are a valid target for SharedStunSystem.StunId
|
|
SEntMan.EnsureComponent<TestListenerComponent>(SPlayer);
|
|
|
|
_sStatusSystem.TrySetStatusEffectDuration(SPlayer, ClumsyStatusAll100);
|
|
});
|
|
|
|
Assume.That(_sStatusSystem.HasStatusEffect(SPlayer, ClumsyStatusAll100), Is.True);
|
|
|
|
await Server.WaitPost(() =>
|
|
{
|
|
var location = SEntMan.EnsureComponent<TransformComponent>(SPlayer).Coordinates;
|
|
var table = SSpawnAtPosition(TableProto, location);
|
|
|
|
SEntMan.EnsureComponent<ClimbingComponent>(SPlayer);
|
|
_sClimbSystem.TryClimb(SPlayer, SPlayer, table, out _);
|
|
});
|
|
|
|
await AwaitDoAfters();
|
|
|
|
Assert.That(_sStatusSystem.HasStatusEffect(SPlayer, SharedStunSystem.StunId), Is.True, "Clumsy mob wasn't stunned climbing a table.");
|
|
foreach (var ev in GetEvents<SelfBeforeClimbEvent>(SPlayer))
|
|
{
|
|
Assert.That(ev.Cancelled, Is.True, "Clumsy mob didn't cancel climb event.");
|
|
}
|
|
}
|
|
|
|
[Test, Description("Test that a mob with the ClumsyGrab status will be unable to hold items in hands.")]
|
|
public async Task TestClumsyGrab()
|
|
{
|
|
await Server.WaitPost(() =>
|
|
{
|
|
SEntMan.EnsureComponent<TestListenerComponent>(SPlayer);
|
|
_sStatusSystem.TrySetStatusEffectDuration(SPlayer, ClumsyGrabProto);
|
|
});
|
|
|
|
Assume.That(_sStatusSystem.HasStatusEffect(SPlayer, ClumsyGrabProto), Is.True);
|
|
Assume.That(HandSys.ActiveHandIsEmpty(SPlayer), Is.True, "Clumsy mob was already holding something!");
|
|
var freeHands = HandSys.CountFreeHands(SPlayer); //"before" free hands
|
|
|
|
// can't use PlaceInHands, that method will fail an assertion under this status effect.
|
|
await Server.WaitPost(() =>
|
|
{
|
|
var location = SEntMan.EnsureComponent<TransformComponent>(SPlayer).Coordinates;
|
|
var item = SSpawnAtPosition(ItemProto, location);
|
|
HandSys.TryPickup(SPlayer, item, handsComp: Hands);
|
|
});
|
|
|
|
Assert.That(HandSys.ActiveHandIsEmpty(SPlayer), Is.True, "The clumsy mob has something in their active hand (they picked up the item!?)");
|
|
Assert.That(HandSys.CountFreeHands(SPlayer), Is.EqualTo(freeHands), "A hand became occupied ('before' and 'after' free hand count has changed)");
|
|
|
|
foreach (var ev in GetEvents<BeforeEquippingHandEvent>(SPlayer))
|
|
{
|
|
Assert.That(ev.Cancelled, Is.True, "Clumsy mob didn't cancel BeforeEquippingHandEvent.");
|
|
}
|
|
}
|
|
}
|