private RbyPokemon ReadBattleStruct(RAMStream data, RAMStream battleStatus, RAMStream modifier, string unmodifiedStatsLabel) { RbyPokemon mon = new RbyPokemon(); mon.Species = Species[data.u8()]; mon.HP = data.u16be(); data.Seek(1); // party pos mon.Status = data.u8(); data.Seek(3); // type and catch rate (for transform, but unimportant to us right now) mon.Moves = Array.ConvertAll(data.Read(4), m => Moves[m]); mon.DVs = data.u16be(); mon.Level = data.u8(); mon.MaxHP = data.u16be(); mon.Attack = data.u16be(); mon.Defense = data.u16be(); mon.Speed = data.u16be(); mon.Special = data.u16be(); mon.PP = data.Read(4); mon.BattleStatus1 = battleStatus.u8(); mon.BattleStatus2 = battleStatus.u8(); mon.BattleStatus3 = battleStatus.u8(); mon.AttackModifider = modifier.u8(); mon.DefenseModifider = modifier.u8(); mon.SpeedModifider = modifier.u8(); mon.SpecialModifider = modifier.u8(); mon.AccuracyModifider = modifier.u8(); mon.EvasionModifider = modifier.u8(); mon.UnmodifiedMaxHP = CpuReadBE <ushort>(unmodifiedStatsLabel + "MaxHP"); mon.UnmodifiedAttack = CpuReadBE <ushort>(unmodifiedStatsLabel + "Attack"); mon.UnmodifiedDefense = CpuReadBE <ushort>(unmodifiedStatsLabel + "Defense"); mon.UnmodifiedSpeed = CpuReadBE <ushort>(unmodifiedStatsLabel + "Speed"); mon.UnmodifiedSpecial = CpuReadBE <ushort>(unmodifiedStatsLabel + "Special"); return(mon); }
public int[] CalcDamage(RbyPokemon attacker, RbyPokemon defender, RbyMove move, bool crit) { int[] ret = new int[39]; for (int i = 0; i < ret.Length; i++) { ret[i] = CalcDamage(attacker, defender, move, i + 217, crit); } return(ret); }
private RbyPokemon ReadPartyStruct(RAMStream data) { RbyPokemon mon = ReadBoxStruct(data); mon.Level = data.u8(); mon.MaxHP = data.u16be(); mon.Attack = data.u16be(); mon.Defense = data.u16be(); mon.Speed = data.u16be(); mon.Special = data.u16be(); return(mon); }
// Code ported from route one. (https://github.com/HRoll/poke-router/blob/master/src/DamageCalculator.java) public int CalcDamage(RbyPokemon attacker, RbyPokemon defender, RbyMove move, int damageRoll, bool crit) { damageRoll = Math.Clamp(damageRoll, 217, 255); if (move.Power == 0) { return(0); } bool special = move.Type.IsSpecial(); int attackUnmodified = special ? attacker.UnmodifiedSpecial : attacker.UnmodifiedAttack; int attack = special ? attacker.Special : attacker.Attack; int defenseUnmodified = special ? defender.UnmodifiedSpecial : defender.UnmodifiedDefense; int defense = special ? defender.Special : defender.Defense; if (move.Name == "SELFDESTRUCT" || move.Name == "EXPLOSION") { defenseUnmodified = Math.Max(defenseUnmodified / 2, 1); defense = Math.Max(defense / 2, 1); } bool stab = attacker.Species.Type1 == move.Type || attacker.Species.Type2 == move.Type; int damage = ((attacker.Level * (crit ? 2 : 1)) & 0xff) * 2 / 5 + 2; damage *= crit ? attackUnmodified : attack; damage *= move.Power; damage /= 50; damage /= crit ? defenseUnmodified : defense; damage += 2; if (stab) { damage = damage * 3 / 2; } damage = damage * move.Game.GetTypeEffectiveness(move.Type, defender.Species.Type1) / 10; damage = damage * move.Game.GetTypeEffectiveness(move.Type, defender.Species.Type2) / 10; if (damage == 0) { return(0); } damage *= damageRoll; damage /= 255; return(Math.Max(damage, 1)); }
private RbyPokemon ReadBoxStruct(RAMStream data) { RbyPokemon mon = new RbyPokemon(); mon.Species = Species[data.u8()]; mon.HP = data.u16be(); mon.Level = data.u8(); mon.Status = data.u8(); data.Seek(3); mon.Moves = Array.ConvertAll(data.Read(4), m => Moves[m]); data.Seek(2); mon.Experience = data.u24be(); mon.HPExp = data.u16be(); mon.AttackExp = data.u16be(); mon.DefenseExp = data.u16be(); mon.SpeedExp = data.u16be(); mon.SpecialExp = data.u16be(); mon.DVs = data.u16be(); mon.PP = data.Read(4); mon.CalculateUnmodifiedStats(); return(mon); }
public float OneShotPercentage(RbyPokemon attacker, RbyPokemon defender, RbyMove move, bool crit) { int[] damageRolls = CalcDamage(attacker, defender, move, crit); return((float)damageRolls.Where(dmg => dmg >= defender.HP).Count() / (float)damageRolls.Length); }