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); }
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)); }
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)); }
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); }
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); }
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); }