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);
            }
        }
        protected void PrintStatusAddedMessage(IFighter fighter, StatMultiplierStatus status)
        {
            StatType stat = status.StatType;
            string   increaseOrDecrease = (status.Multiplier > 1.0) ? "raised" : "lowered";

            string output = $"{fighter.DisplayName} had their {stat.ToString().ToLower()} {increaseOrDecrease} for {GetDurationString(status)}!";

            _output.WriteLine(output);
        }
示例#3
0
        public void TestUndoDebuffsEffect_IndividualEffect()
        {
            StatMultiplierStatus lowerAttackStatus    = new StatMultiplierStatus(3, StatType.Strength, 1.0 / 3);
            StatusMove           lowerEnemyAttackMove = new StatusMove("raise attack", TargetType.SingleEnemy, lowerAttackStatus);

            UndoDebuffsStatus undoDebuffStatus = new UndoDebuffsStatus(1);
            StatusMove        undoDebuffMove   = new StatusMove("reset stats", TargetType.SingleAlly, undoDebuffStatus);

            TestHumanFighter fighter2 = new TestHumanFighter("foo 2", 1);

            _humanTeam = new TestTeam(_humanFighter, fighter2);

            //enemy won't be killed if the status isn't assigned to _fighter2
            _enemy.SetHealth(3);
            _enemy.SetSpeed(2);
            _enemy.SetMove(lowerEnemyAttackMove);
            _chanceService.PushEventOccurs(true); //status hits
            _enemy.SetMoveTarget(fighter2);

            _humanFighter.SetSpeed(1);
            _humanFighter.SetMove(undoDebuffMove);
            _chanceService.PushEventOccurs(true); //status hits
            _humanFighter.SetMoveTarget(fighter2);
            _logger.Subscribe(EventType.StatusAdded, fighter2);
            _logger.Subscribe(EventType.StatusRemoved, fighter2);

            BattleMove attack = MoveFactory.Get(BattleMoveType.Attack);

            fighter2.SetStrength(3);
            fighter2.SetMove(attack);
            fighter2.SetMoveTarget(_enemy);
            _chanceService.PushEventOccurs(true);  //attack hits
            _chanceService.PushEventOccurs(false); //attack is not a crit

            //once Statuses are removed after battle, won't be able to
            _battleManager.Battle(_humanTeam, _enemyTeam);

            List <EventLog> logs = _logger.Logs;

            Assert.AreEqual(2, logs.Count);

            EventLog log = logs[1];

            Assert.AreEqual(EventType.StatusRemoved, log.Type);
            StatusRemovedEventArgs e = log.E as StatusRemovedEventArgs;

            Assert.NotNull(e);
            Assert.IsTrue(lowerAttackStatus.AreEqual(e.Status));
        }
示例#4
0
        public void StatusTechnique_AppropriatelyAssignsStatusToTarget()
        {
            StatMultiplierStatus status     = new StatMultiplierStatus(3, StatType.Strength, 1.5);
            StatusMove           statusMove = new StatusMove("raise attack", TargetType.SingleAlly, status);

            TestHumanFighter fighter2 = new TestHumanFighter("foo 2", 1);

            _humanTeam = new TestTeam(_humanFighter, fighter2);

            _humanFighter.SetSpeed(1);
            _humanFighter.SetMove(statusMove);
            _chanceService.PushEventOccurs(true);
            _humanFighter.SetMoveTarget(fighter2);
            _logger.Subscribe(EventType.StatusAdded, fighter2);

            BattleMove attack = MoveFactory.Get(BattleMoveType.Attack);

            fighter2.SetStrength(2);
            fighter2.SetMove(attack);
            fighter2.SetMoveTarget(_enemy);
            _chanceService.PushEventOccurs(true);  //attack hits
            _chanceService.PushEventOccurs(false); //attack is not a crit

            //enemy won't be killed if the status isn't assigned to _fighter2
            _enemy.SetHealth(3);
            _enemy.SetMove(_doNothing);
            _enemy.SetMoveTarget(_enemy);

            //once Statuses are removed after battle, won't be able to
            _battleManager.Battle(_humanTeam, _enemyTeam);

            List <EventLog> logs = _logger.Logs;

            Assert.AreEqual(1, logs.Count);

            EventLog log = logs[0];

            Assert.AreEqual(EventType.StatusAdded, log.Type);
            StatusAddedEventArgs e = log.E as StatusAddedEventArgs;

            Assert.NotNull(e);
            Assert.IsTrue(status.AreEqual(e.Status));
        }
示例#5
0
        public void AddStatus_AppropriatelyRaisesEvent()
        {
            StatMultiplierStatus status = new StatMultiplierStatus(2, StatType.Speed, 1.5);

            _fighter.AddStatus(status);

            List <EventLog> logs = _logger.Logs;

            Assert.AreEqual(1, logs.Count);

            EventLog log = logs[0];

            Assert.AreEqual(_fighter, log.Sender);
            Assert.AreEqual(EventType.StatusAdded, log.Type);

            StatusAddedEventArgs args = log.E as StatusAddedEventArgs;

            Assert.NotNull(args);
            Assert.AreEqual(status, args.Status);
        }
示例#6
0
        public void StatusesRemoved_OnRoundEnd()
        {
            StatMultiplierStatus boostDefenseStatus = new StatMultiplierStatus(1, StatType.Defense, 2);

            _humanFighter.SetDefense(1);
            _humanFighter.SetHealth(1);
            _humanFighter.AddStatus(boostDefenseStatus);
            _humanFighter.SetMove(_doNothing, 1);
            _humanFighter.SetMove(_runawayMove);

            _enemy.SetMove(_basicAttackMove);
            _enemy.SetMoveTarget(_humanFighter);
            _enemy.SetStrength(2);

            _chanceService.PushEventsOccur(true, false);

            _battleManager.Battle(_humanTeam, _enemyTeam);

            Assert.AreEqual(1, _humanFighter.CurrentHealth);
        }
示例#7
0
        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);
        }