public AbilityEvent(Ability ability, AbilityModifiers modifiers, Combatant source, Combatant[] targets) : base(source, modifiers.ResetTurnTimer) { Hits = new bool[ability.Hits]; Steals = new string[modifiers.StealAsWell ? targets.Count() : 0]; TargetHitFlags = new bool[targets.Count()]; Targets = targets; Ability = ability; Modifiers = modifiers; if (modifiers.StealAsWell) { if (!(source is Ally)) { throw new GameDataException("Non-Ally source '{0}' attempted to steal.", source.Name); } else if (targets.Any(x => !(x is Enemy))) { throw new GameDataException("Source '{0}' attempted to steal from a non-Enemy target using ability '{1}'.", source.Name, ability.Name); } } }
protected int PhysicalAttack(Combatant source, Combatant target, AbilityModifiers modifiers) { int bd = PhysicalBase(source); int dam = PhysicalDamage(bd, Power, target); dam = Critical(dam, source, target); dam = Berserk(dam, source); dam = RowCheck(dam, source, target); dam = Frog(dam, target); dam = Sadness(dam, target); dam = Barrier(dam, target); dam = Mini(dam, source); dam = RandomVariation(source.CurrentBattle.Random, dam); return dam; }
public bool Hits(Combatant source, Combatant target, AbilityModifiers modifiers) { // auto hit conditions if (_odds >= 100) { return true; } if (Statuses.Count() == 1 && Statuses.Contains(Status.Frog) && target.Frog) { return true; } if (Statuses.Count() == 1 && Statuses.Contains(Status.Small) && target.Small) { return true; } if (target is Ally && Statuses.Any(s => new Status[] { Status.Haste, Status.Berserk, Status.Shield }.Contains(s))) { return true; } int odds = _odds; odds = MPTurbo(odds, modifiers); odds = Split(odds, modifiers); odds -= 1; return source.CurrentBattle.Random.Next(99) < odds; }
protected int MagicalAttack(Combatant source, Combatant target, AbilityModifiers modifiers) { int bd = MagicalBase(source); int dam = MagicalDamage(bd, Power, target); dam = Sadness(dam, target); dam = Split(dam, modifiers); dam = MBarrier(dam, target); dam = MPTurbo(dam, modifiers); dam = RandomVariation(source.CurrentBattle.Random, dam); return dam; }
protected int MPPercent(Combatant source, Combatant target, AbilityModifiers modifiers) { int dam = target.MP * Power / 32; dam = QuadraMagic(dam, modifiers); return dam; }
protected int Cure(Combatant source, Combatant target, AbilityModifiers modifiers) { int bd = MagicalBase(source); int dam = bd + 22 * Power; dam = Split(dam, modifiers); dam = MBarrier(dam, target); dam = MPTurbo(dam, modifiers); dam = RandomVariation(source.CurrentBattle.Random, dam); return dam; }
protected int Fixed(Combatant source, Combatant target, AbilityModifiers modifiers) { return Power; }
protected static int QuadraMagic(int dam, AbilityModifiers modifiers) { if (modifiers.QuadraMagic) { dam = dam / 2; } return dam; }
protected static int Split(int dam, AbilityModifiers modifiers) { if (modifiers.QuadraMagic) { dam = dam / 2; } else if (modifiers.Alled && !modifiers.NoSplit) { dam = dam * 2 / 3; } return dam; }
protected static int MPTurbo(int dam, AbilityModifiers modifiers) { dam = dam * (10 + modifiers.MPTurboFactor) / 10; return dam; }
/// <summary> /// Cast this ability. The <param name="source">source</param> is the <see cref="Combatant" /> which is responsible for casting the spell. /// The spell can have one or more <param name="targets">targets</param>. /// </summary> /// <param name='source'> /// Source. /// </param> /// <param name='targets'> /// Targets. /// </param> /// <param name='modifiers'> /// Modifiers. /// </param> /// <param name='resetTurnTimer'> /// If set to <c>true</c> reset turn timer. /// </param> public void Use(Combatant source, IEnumerable<Combatant> targets, AbilityModifiers modifiers) { bool canUse = true; if (!modifiers.CostsNothing) { if (source.MP >= MPCost) { source.UseMP(MPCost); } else { canUse = false; } } BattleEvent e = null; if (canUse) { e = new AbilityEvent(this, modifiers, source, targets.ToArray()); } else { e = new AbilityFailEvent(source, this, modifiers.ResetTurnTimer); } if (modifiers.CounterAttack) { source.CurrentBattle.EnqueueCounterAction(e); } else { source.CurrentBattle.EnqueueAction(e); } }
public bool PhysicalHit(Combatant source, Combatant target, AbilityModifiers modifiers) { int hitp; if (target.Absorbs(Elements) || target.Voids(Elements) || target.Death || target.Sleep || target.Confusion || target.Stop || target.Petrify || target.Manipulate || target.Paralysed || target.Peerless) { hitp = 255; } else { hitp = (source.Dexterity / 4) + Hitp + source.Defp - target.Defp; if (source.Fury) { hitp = hitp - hitp * 3 / 10; } } // Sanity if (hitp < 1) { hitp = 1; } int lucky = source.CurrentBattle.Random.Next(0, 100); // Lucky Hit if (lucky < Math.Floor(source.Luck / 4.0d)) { hitp = 255; } // Lucky Evade else if (lucky < Math.Floor(target.Luck / 4.0d)) { if (source is Ally && target is Enemy) { hitp = 0; } } int r = source.CurrentBattle.Random.Next(65536) * 99 / 65536 + 1; return r < hitp; }
public bool MagicHit(Combatant source, Combatant target, AbilityModifiers modifiers) { if (Hitp == 255 || target.Absorbs(Elements) || target.Voids(Elements)) { return true; } if (target.Death || target.Sleep || target.Confusion || target.Stop || target.Petrify || target.Paralysed || target.Peerless || target.Reflect) { return true; } if (source.Fury) { Hitp = Hitp - Hitp * 3 / 10; } // Magic Defense Percent if (source.CurrentBattle.Random.Next(1, 101) < target.MDefp) { return false; } int hitp = Hitp + source.Level - target.Level / 2 - 1; return source.CurrentBattle.Random.Next(100) < hitp; }
public bool[] Cast(Combatant source, Combatant[] targets, AbilityModifiers modifiers) { if (RandomTarget && targets.Count() > 1) { int index = source.CurrentBattle.Random.Next(targets.Count()); Combatant newTarget = targets.ToList()[index]; targets = new Combatant[] { newTarget }; } bool[] hits = new bool[targets.Length]; for (int i = 0; i < targets.Length; i++) { Combatant target = targets[i]; bool hit = HitFormula(source, target, modifiers); // We can still miss if each of the status changes misses bool actuallyHit = false; if (hit) { if (Power > 0) { int dam = DamageFormula(source, target, modifiers); dam = RunElementalChecks(dam, target, Elements); //dam = LowerSanityCkeck(dam); // not required as per the guides (besides, negative damage is OK (think cure) dam = UpperSanityCheck(dam); if (target.Peerless || target.Petrify) { dam = 0; } target.AcceptDamage(source, dam, Type); actuallyHit = true; } foreach (StatusChange statusChange in Statuses) { if (statusChange.Hits(source, target, modifiers)) { switch (statusChange.ChangeType) { case StatusChange.Effect.Cure: foreach (Status status in statusChange.Statuses) { target.GetType().GetMethod("Cure" + status).Invoke(target, new object[] { source }); } break; case StatusChange.Effect.Inflict: foreach (Status status in statusChange.Statuses) { target.GetType().GetMethod("Inflict" + status).Invoke(target, new object[] { source }); } break; case StatusChange.Effect.Toggle: foreach (Status status in statusChange.Statuses) { if ((bool)target.GetType().GetProperty(status.ToString()).GetValue(target, null)) { target.GetType().GetMethod("Cure" + status).Invoke(target, new object[] { source }); } else { target.GetType().GetMethod("Inflict" + status).Invoke(target, new object[] { source }); } } break; } actuallyHit = true; } } hits[i] = true; } if (!actuallyHit) { source.CurrentBattle.AddMissIcon(target); } } return hits; }