コード例 #1
0
        protected void PrintStatusAddedMessage(IFighter fighter, AutoEvadeStatus status)
        {
            string andCounterString = status.ShouldCounterAttack ? " and counter" : "";
            string output           = $"{fighter.DisplayName} will evade{andCounterString} all attacks for {GetDurationString(status)}!";

            _output.WriteLine(output);
        }
コード例 #2
0
        public void AutoEvadeStatus_CorrectlyPrintsMessage_WhenAdded([Values(1, 4)] int statusDuration, [Values(true, false)] bool shouldCounter)
        {
            AutoEvadeStatus evadeStatus = new AutoEvadeStatus(statusDuration, shouldCounter);
            StatusMove      statusMove  = new StatusMove("foo", TargetType.Self, evadeStatus);

            _humanFighter.SetMove(statusMove, 1);
            //status move hits
            _chanceService.PushEventOccurs(true);
            _humanFighter.SetMove(_runawayMove);

            _enemy.SetMove(_doNothing);

            BattleManagerBattleConfiguration config = new BattleManagerBattleConfiguration
            {
                ShowIntroAndOutroMessages = false
            };

            _battleManager.Battle(_humanTeam, _enemyTeam, config: config);

            MockOutputMessage[] outputs = _output.GetOutputs();

            Assert.AreEqual(1, outputs.Length);

            string turnOrTurns      = statusDuration == 1 ? "turn" : "turns";
            string andCounterString = shouldCounter ? " and counter" : "";
            string expectedOutput   = $"{_humanFighter.DisplayName} will evade{andCounterString} all attacks for {statusDuration} {turnOrTurns}!\n";

            Assert.AreEqual(expectedOutput, outputs[0].Message);
        }
コード例 #3
0
        public override bool AreEqual(Status status)
        {
            AutoEvadeStatus evadeStatus = status as AutoEvadeStatus;

            bool areEqual = evadeStatus != null && evadeStatus.ShouldCounterAttack == ShouldCounterAttack;

            return(areEqual);
        }
コード例 #4
0
        protected void PrintStatusAddedMessage(object sender, StatusAddedEventArgs e)
        {
            Status status = e.Status;

            IFighter senderAsFighter = sender as IFighter;

            if (senderAsFighter == null)
            {
                throw new InvalidOperationException("BattleManager.PrintStatusAddedMessage() should only subscribe to instances of IFighter");
            }

            CriticalChanceMultiplierStatus  criticalChanceStatus       = status as CriticalChanceMultiplierStatus;
            StatMultiplierStatus            statMultiplierStatus       = status as StatMultiplierStatus;
            MagicMultiplierStatus           magicMultiplierStatus      = status as MagicMultiplierStatus;
            MagicResistanceMultiplierStatus resistanceMultiplierStatus = status as MagicResistanceMultiplierStatus;
            ReflectStatus             reflectStatus             = status as ReflectStatus;
            SpellCostMultiplierStatus spellCostMultiplierStatus = status as SpellCostMultiplierStatus;
            AutoEvadeStatus           autoEvadeStatus           = status as AutoEvadeStatus;
            CounterAttackStatus       counterAttackStatus       = status as CounterAttackStatus;
            BlindStatus blindStatus = status as BlindStatus;

            if (criticalChanceStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, criticalChanceStatus);
            }
            if (statMultiplierStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, statMultiplierStatus);
            }
            if (magicMultiplierStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, magicMultiplierStatus);
            }
            if (resistanceMultiplierStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, resistanceMultiplierStatus);
            }
            if (reflectStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, reflectStatus);
            }
            if (spellCostMultiplierStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, spellCostMultiplierStatus);
            }
            if (autoEvadeStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, autoEvadeStatus);
            }
            if (counterAttackStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, counterAttackStatus);
            }
            if (blindStatus != null)
            {
                PrintStatusAddedMessage(senderAsFighter, blindStatus);
            }
        }
コード例 #5
0
        public void MoveWithNeverMissEffect_CanStillBeEvaded()
        {
            _human.SetMove(_attackWithNeverMissEffect, 1);
            _human.SetMoveTarget(_enemy);
            _chanceService.PushEventsOccur(false); //just check the crit
            _human.SetMove(_runawayMove);

            AutoEvadeStatus autoEvadeStatus = new AutoEvadeStatus(1, false);

            _enemy.AddStatus(autoEvadeStatus);
            _enemy.SetMove(_doNothingMove);

            _battleManager.Battle(_humanTeam, _enemyTeam);

            Assert.AreEqual(_enemy.MaxHealth, _enemy.CurrentHealth, "Enemy should have evaded the never-miss attack and escaped at full health!");
        }
コード例 #6
0
        public void MoveWithCannotBeEvadedEffect_HitsOpponentThatEvaded()
        {
            CannotBeEvadedBattleMoveEffect cannotBeEvadedEffect = new CannotBeEvadedBattleMoveEffect();
            AttackBattleMove noEvadeAttack = new AttackBattleMove("foo", TargetType.SingleEnemy, 100, 10, effects: cannotBeEvadedEffect);

            _human.SetMove(noEvadeAttack, 1);
            _human.SetMove(_runawayMove);
            _human.SetMoveTarget(_enemy);
            _chanceService.PushAttackHitsNotCrit(); //attack hits, not a crit

            AutoEvadeStatus autoEvadeStatus = new AutoEvadeStatus(1, false);

            _enemy.AddStatus(autoEvadeStatus);
            _enemy.SetMove(_doNothingMove);
            _enemy.SetHealth(_human.Strength + 1);

            _battleManager.Battle(_humanTeam, _enemyTeam);

            Assert.AreEqual(1, _enemy.CurrentHealth, "attack should have hit even though enemy had an AutoEvade status!");
        }
コード例 #7
0
        public void Setup()
        {
            _logger        = new EventLogger();
            _input         = new MockInput();
            _output        = new MockOutput();
            _menuManager   = new TestMenuManager(_input, _output);
            _chanceService = new MockChanceService();
            _battleManager = new TestBattleManager(_chanceService, _input, _output);

            _evadeButDoNotCounterStatus = new AutoEvadeStatus(1, false);
            _evadeAndCounterStatus      = new AutoEvadeStatus(1, true);

            _humanFighter = new TestHumanFighter("foo", 1);
            _humanTeam    = new TestTeam(_humanFighter);

            _enemy     = (TestEnemyFighter)TestFighterFactory.GetFighter(TestFighterType.TestEnemy, 1);
            _enemyTeam = new Team(_menuManager, _enemy);

            _doNothing = new DoNothingMove();
        }
コード例 #8
0
        private void GetLevel3MoveIndices(out int attackIndex, out int evadeIndex, out int evadeAndCounterIndex, out int attackBoostIndex)
        {
            List <BattleMove> availableMoves = _level3Warrior.AvailableMoves;

            attackIndex = availableMoves.FindIndex(bm => bm.MoveType == BattleMoveType.Attack);
            evadeIndex  = availableMoves.FindIndex(bm =>
            {
                if (bm.MoveType != BattleMoveType.Status)
                {
                    return(false);
                }

                StatusMove statusMove = bm as StatusMove;

                AutoEvadeStatus status = statusMove?.Status as AutoEvadeStatus;

                if (status == null || status.ShouldCounterAttack)
                {
                    return(false);
                }
                return(true);
            });
            evadeAndCounterIndex = availableMoves.FindIndex(bm =>
            {
                if (bm.MoveType != BattleMoveType.Status)
                {
                    return(false);
                }

                StatusMove statusMove = bm as StatusMove;

                AutoEvadeStatus status = statusMove?.Status as AutoEvadeStatus;

                if (status == null || !status.ShouldCounterAttack)
                {
                    return(false);
                }
                return(true);
            });
            attackBoostIndex = availableMoves.FindIndex(bm => bm.MoveType == BattleMoveType.Status && (bm as StatusMove)?.Status is StatMultiplierStatus);
        }
コード例 #9
0
        public void ConditionalEffect_AppropriatelySuppressed_WhenNotEvadedConditionNotMet([Values(10, 20)] int percentage)
        {
            AttackBattleMove conditionalHealMove = GetNotEvadeRestoreHealthAttack(percentage);

            _team1Fighter.SetHealth(100, 10);
            _team1Fighter.SetMove(conditionalHealMove, 1);
            _team1Fighter.SetMoveTarget(_team2Fighter);
            _team1Fighter.SetMove(_runawayMove);

            _chanceService.PushAttackHitsNotCrit();

            AutoEvadeStatus autoEvadeStatus = new AutoEvadeStatus(1, false);

            _team2Fighter.AddStatus(autoEvadeStatus);
            _team2Fighter.SetHealth(100);
            _team2Fighter.SetMove(_doNothingMove);

            _battleManager.Battle(_team1, _team2);

            int expectedRemainingHealth = 10;

            Assert.AreEqual(expectedRemainingHealth, _team1Fighter.CurrentHealth, "The enemy had evade status, so the user should not have regained any HP");
        }
コード例 #10
0
ファイル: MoveFactory.cs プロジェクト: Jsweeney1000/SimpleRPG
        public static BattleMove Get(BattleMoveType type, string description = null)
        {
            BattleMove ret;
            var        notFoundException = new ArgumentException($"No move exists with type {type} and description '{description}'!");

            switch (type)
            {
            case BattleMoveType.Attack:
                switch (description)
                {
                case null:
                case "attack":
                    ret = Attack;
                    break;

                case "goblin punch":
                    ret = new AttackBattleMove(description, TargetType.SingleEnemy, 100, 75, executionText: $"throws a goblin punch at {Globals.TargetReplaceText}");
                    break;

                case "feint":
                    NotEvadedBattleCondition       notEvadedCondition   = new NotEvadedBattleCondition();
                    AttackBoostBattleMoveEffect    attackBoostEffect    = new AttackBoostBattleMoveEffect(0.25, notEvadedCondition);
                    CannotBeEvadedBattleMoveEffect cannotBeEvadedEffect = new CannotBeEvadedBattleMoveEffect();
                    BattleMoveEffect[]             effects = { attackBoostEffect, cannotBeEvadedEffect, UnconditionalNeverMissEffect };
                    ret = new AttackBattleMove(description, TargetType.SingleEnemy, 100, 0, executionText: "attacks [target] with a feint", effects: effects);
                    break;

                default:
                    throw notFoundException;
                }
                break;

            case BattleMoveType.ConditionalPowerAttack:
                ret = new ConditionalPowerAttackBattleMove("malevolence attack", TargetType.SingleEnemy, 100, 10, executionText: "unleashes their dark power!");
                break;

            case BattleMoveType.Runaway:
                ret = Runaway;
                break;

            case BattleMoveType.DoNothing:
                switch (description)
                {
                case null:
                    ret = DoNothing;
                    break;

                case "goblin punch charge":
                    ret = new DoNothingMove("prepares to unleash its fury");
                    break;

                default:
                    throw notFoundException;
                }
                break;

            case BattleMoveType.Special:
                switch (description)
                {
                case "dark energy gather":
                    ret = new SpecialMove(description, BattleMoveType.Special, TargetType.Self, "gathers dark energy");
                    break;

                default:
                    throw notFoundException;
                }
                break;

            case BattleMoveType.MultiTurn:
                if (description == "goblin punch")
                {
                    ret = new MultiTurnBattleMove(description, TargetType.SingleEnemy,
                                                  Get(BattleMoveType.DoNothing, "goblin punch charge"),
                                                  Get(BattleMoveType.Attack, description));
                }
                else
                {
                    throw notFoundException;
                }
                break;

            case BattleMoveType.Dance:
                switch (description)
                {
                default:
                    throw notFoundException;

                case "fire dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Fire,
                                        new List <FieldEffect>
                    {
                        new MagicMultiplierFieldEffect(TargetType.OwnTeam, "fire dance", MagicType.Fire, (4.0 / 3.0))
                    },
                                        new DoNothingMove("performs the fire dance"),
                                        new DoNothingMove("continues to perform the fire dance"));
                    break;

                case "water dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Water,
                                        new List <FieldEffect>
                    {
                        new MagicMultiplierFieldEffect(TargetType.OwnTeam, "water dance", MagicType.Water, (4.0 / 3.0))
                    },
                                        new DoNothingMove("performs the water dance"),
                                        new DoNothingMove("continues to perform the water dance"));
                    break;

                case "wind dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Wind,
                                        new List <FieldEffect>
                    {
                        new MagicMultiplierFieldEffect(TargetType.OwnTeam, "wind dance", MagicType.Wind, (4.0 / 3.0))
                    },
                                        new DoNothingMove("performs the wind dance"),
                                        new DoNothingMove("continues to perform the wind dance"));
                    break;

                case "earth dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Earth,
                                        new List <FieldEffect>
                    {
                        new MagicMultiplierFieldEffect(TargetType.OwnTeam, "earth dance", MagicType.Earth, (4.0 / 3.0))
                    },
                                        new DoNothingMove("performs the earth dance"),
                                        new DoNothingMove("continues to perform the earth dance"));
                    break;

                case "heart dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Heart,
                                        new List <FieldEffect>
                    {
                        new StatMultiplierFieldEffect(TargetType.OwnTeam, "heart dance", StatType.Defense, (5 / 100.0))
                    },
                                        new DoNothingMove("performs the heart dance"),
                                        new DoNothingMove("continues to perform the heart dance"));
                    break;

                case "soul dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Soul,
                                        new List <FieldEffect>
                    {
                        new MagicMultiplierFieldEffect(TargetType.OwnTeam, "soul dance", MagicType.All, (5 / 100.0))
                    },
                                        new DoNothingMove("performs the soul dance"),
                                        new DoNothingMove("continues to perform the soul dance"));
                    break;

                case "mind dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Mind,
                                        new List <FieldEffect>
                    {
                        new StatMultiplierFieldEffect(TargetType.OwnTeam, "mind dance", StatType.Evade, (5.0 / 100.0), 1)
                    },
                                        new DoNothingMove("performs the mind dance"),
                                        new DoNothingMove("continues to perform the mind dance"));
                    break;

                case "danger dance":
                    ret = new DanceMove(description, TargetType.OwnTeam, 2, DanceEffectType.Danger,
                                        new List <FieldEffect>
                    {
                        new StatMultiplierFieldEffect(TargetType.OwnTeam, "danger dance", StatType.Strength, (5.0 / 100.0), 1)
                    },
                                        new DoNothingMove("performs the danger dance"),
                                        new DoNothingMove("continues to perform the danger dance"));
                    break;
                }
                break;

            case BattleMoveType.Status:
                Status status;
                switch (description)
                {
                default:
                    throw notFoundException;

                case "warrior's cry":
                    status = new StatMultiplierStatus(4, StatType.Strength, 2);
                    ret    = new StatusMove(description, TargetType.Self, status, "unleashes their warrior cry!");
                    break;

                case "evade":
                    status = new AutoEvadeStatus(1, false);
                    ret    = new StatusMove(description, TargetType.Self, status, "takes a ready stance", 1);
                    break;

                case "evadeAndCounter":
                    status = new AutoEvadeStatus(1, true);
                    ret    = new StatusMove(description, TargetType.Self, status, "prepares to counter", 1);
                    break;

                case "dark fog":
                    status = new BlindStatus(2);
                    ret    = new StatusMove(description, TargetType.SingleEnemy, status, $"draws a dark fog about {Globals.TargetReplaceText}", accuracy: 60);
                    break;
                }
                break;

            case BattleMoveType.Shield:
                switch (description)
                {
                case "iron shield":
                    IBattleShield shield = new IronBattleShield(5, 2, 0);
                    ret = new ShieldMove(description, TargetType.SingleAllyOrSelf, "created an iron shield", shield);
                    break;

                default:
                    throw notFoundException;
                }
                break;

            case BattleMoveType.ShieldFortifier:
                switch (description)
                {
                case "heal shield":
                    ret = new ShieldFortifyingMove(description, TargetType.SingleAllyOrSelf, $"healed {Globals.TargetReplaceText}'s shield", ShieldFortifyingType.Health, 5);
                    break;

                case "strengthen shield":
                    ret = new ShieldFortifyingMove(description, TargetType.SingleAllyOrSelf, $"strengthened {Globals.TargetReplaceText}'s shield", ShieldFortifyingType.Defense, 5);
                    break;

                default:
                    ret = null;
                    break;
                }
                break;

            case BattleMoveType.ShieldBuster:
                if (string.IsNullOrEmpty(description))
                {
                    description = "Shield buster";
                }
                switch (description)
                {
                case "Shield buster":
                    ret = new ShieldBusterMove(description, TargetType.SingleEnemy, "uses the shield buster on [target]");
                    break;

                case "Super shield buster":
                    ret = new ShieldBusterMove(description, TargetType.SingleEnemy, "uses the super shield buster on [target]", 1);
                    break;

                default:
                    throw notFoundException;
                }

                break;

            case BattleMoveType.BellMove:
                switch (description)
                {
                case "seal shade":
                default:
                    ret = Get(BellMoveType.SealMove);
                    break;

                case "control shade":
                    ret = Get(BellMoveType.ControlMove);
                    break;
                }
                break;

            case BattleMoveType.AbsorbShade:
                ret = new ShadeAbsorbingMove("absorb shade", $"has given into malice, targetting {Globals.TargetReplaceText}!");
                break;

            default:
                throw notFoundException;
            }

            return(ret);
        }