public void CombatShouldWorkWithTwoOpponentsAndSequentialTurns() { Globals.Config.ConcurrentTurnsEnabled = false; SetupScenarioForTwoZombies(out var zombie1, out var zombie2); // The zombies should not perform simultaneously GameSystems.D20.Actions.isSimultPerformer(zombie1).Should().BeFalse(); GameSystems.D20.Actions.isSimultPerformer(zombie2).Should().BeFalse(); // It should be zombie1's turn, run the game until it's zombie2's turn and check what zombie1 did GameSystems.D20.Initiative.CurrentActor.Should().Be(zombie1); Game.RunUntil(() => GameSystems.D20.Initiative.CurrentActor == zombie2, 10000); CompletedActions.Should() .HaveCount(1) .And.Contain(action => action.d20APerformer == zombie1 && action.d20ATarget == _player && action.d20ActType == D20ActionType.MOVE); ActionLog.Clear(); // Now it's zombie2's turn, run until it's the player's turn and check what zombie2 did Game.RunUntil(() => GameSystems.D20.Initiative.CurrentActor == _player, 10000); CompletedActions.Should() .HaveCount(1) .And.Contain(action => action.d20APerformer == zombie2 && action.d20ATarget == _player && action.d20ActType == D20ActionType.MOVE); // Since both zombies just moved, there should be no combat entries CombatLog.Should().BeEmpty(); }
public void ActionsArePerformedAfterMovingIntoRange() { // Spawn a player and a chest (at a distance), and click on the chest var player = CreatePlayer(); var lockedChest = Create(TestProtos.LockedChest); ClickOn(lockedChest); // This should make the party leader perform the default action, // which is to open the container. Game.RunUntil(() => GameSystems.D20.Actions.IsCurrentlyPerforming(player)); var sequence = GameSystems.D20.Actions.CurrentSequence ?? throw new NullReferenceException(); sequence.performer.Should().Be(player); sequence.targetObj.Should().Be(lockedChest); // Run until the sequence has concluded Game.RunUntil(() => !GameSystems.D20.Actions.IsCurrentlyPerforming(player), 5000); // Since the player was not in reach, there should be a move action performed, // then the opening action CompletedActions.Should().SatisfyRespectively( first => { first.d20APerformer.Should().Be(player); first.d20ActType.Should().Be(D20ActionType.MOVE); // The target location should bring the player into reach of the container first.destLoc.DistanceTo(lockedChest.GetLocationFull()).Should().BeLessOrEqualTo( player.GetRadius() + lockedChest.GetRadius() // Reach returns feet + player.GetReach(D20ActionType.OPEN_CONTAINER) * locXY.INCH_PER_FEET ); }, second => { second.d20ActType.Should().Be(D20ActionType.OPEN_CONTAINER); second.d20APerformer.Should().Be(player); second.d20ATarget.Should().Be(lockedChest); } ); }