diff --git a/src/me/corriekay/pokegoutil/utils/pokemon/PokemonUtils.java b/src/me/corriekay/pokegoutil/utils/pokemon/PokemonUtils.java index 3ffc48e8..908c0a79 100644 --- a/src/me/corriekay/pokegoutil/utils/pokemon/PokemonUtils.java +++ b/src/me/corriekay/pokegoutil/utils/pokemon/PokemonUtils.java @@ -9,9 +9,51 @@ public final class PokemonUtils { private PokemonUtils() { /* Prevent initializing this class */ } - public static final long DUEL_ABILITY_MAX = 21_858_183_256L; - public static final long GYM_OFFENSE_MAX = 510_419L; - public static final long GYM_DEFENSE_MAX = 9_530_079_725L; + /** + * Maximum duel ability - moveset only + * Currently Mewtwo Pyscho Cut & Hyperbeam + */ + public static final long DUEL_ABILITY_MAX = 21_602_780_920L; + + /** + * Maximum duel ability - moveset & Max IV + * Currently Mewtwo Pyscho Cut & Hyperbeam + */ + public static final long DUEL_ABILITY_IV_MAX = 26_161_393_326L; + + /** + * Maximum gym offense - moveset only + * Currently Mewtwo Psycho Cut & Hyperbeam + */ + public static final long GYM_OFFENSE_MAX = 504_455L; + + /** + * Maximum gym offense - moveset & Max IV + * Currently Mewtwo Pyscho Cut & Hyperbeam + */ + public static final long GYM_OFFENSE_IV_MAX = 531_099L; + + /** + * Maximum gym defense - moveset only + * Currently Mewtwo Confusion & Psychic + */ + public static final long GYM_DEFENSE_MAX = 10_033_663_200L; + + /** + * Maximum gym defense - moveset & Max IV + * Currently Mewtwo Confusion & Psychic + */ + public static final long GYM_DEFENSE_IV_MAX = 12_150_963_825L; + + /** + * Damage bonus from a critical hit - currently no damage bonus in game, change when game is fixed + */ + public static final double CRIT_DAMAGE_BONUS = 0; + + /** + * Time in ms for a powermove to be performed + */ + public static final int MOVE2_CHARGE_DELAY_MS = 500; public static String convertTeamColorToName(int teamValue) { Team[] teams = Team.values(); @@ -64,12 +106,14 @@ private static double dpsForMove(Pokemon p, PokemonMove move, boolean primary) { * as then you can only attack for as long as you can stay positive on HP. * * @param p A Pokemon object + * @param useIV Use a pokemon's IV values in the calculations * @return Rating of a Pokemon's overall attacking power considering damage, health & defense * @see https://www.reddit.com/r/TheSilphRoad/comments/4vcobt/posthotfix_pokemon_go_full_moveset_rankings/ * @see i607ch00 */ - public static long duelAbility(Pokemon p) { - return PokemonUtils.gymOffense(p) * PokemonUtils.tankiness(p); + public static long duelAbility(Pokemon p, boolean useIV) { + double duelAbility = PokemonUtils.gymOffense(p, useIV) * PokemonUtils.tankiness(p, useIV); + return Math.round(duelAbility); } /** @@ -77,13 +121,16 @@ public static long duelAbility(Pokemon p) { * Pokemon's base attack to arrive at a ranking of raw damage output. * * @param p A Pokemon object + * @param useIV Use a pokemon's IV values in the calculations * @return Rating of a Pokemon's pure offensive ability over time considering move set * @see https://www.reddit.com/r/TheSilphRoad/comments/4vcobt/posthotfix_pokemon_go_full_moveset_rankings/ * @see i607ch00 */ - public static long gymOffense(Pokemon p) { - double gymOffense = Math.max(PokemonUtils.dpsForMove(p, true) * 100, PokemonUtils.weaveDPS(p, 0)) * (p.getMeta().getBaseAttack() + p.getIndividualAttack()); - return Math.round(gymOffense); + public static double gymOffense(Pokemon p, boolean useIV) { + + int attackIV = (useIV) ? p.getIndividualAttack() : 0; + + return Math.max(PokemonUtils.dpsForMove(p, true) * 100, PokemonUtils.weaveDPS(p, 0)) * (p.getMeta().getBaseAttack() + attackIV); } /** @@ -91,12 +138,16 @@ public static long gymOffense(Pokemon p) { * to arrive at a ranking of how much damage a Pokemon will output when defending a gym. * * @param p A Pokemon object + * @param useIV Use a pokemon's IV values in the calculations * @return Rating of a Pokemon's AI controlled gym defense over time considering move set * @see https://www.reddit.com/r/TheSilphRoad/comments/4vcobt/posthotfix_pokemon_go_full_moveset_rankings/ * @see i607ch00 */ - public static long gymDefense(Pokemon p) { - double gymDefense = PokemonUtils.weaveDPS(p, 2000) * (p.getMeta().getBaseAttack() + p.getIndividualAttack()) * PokemonUtils.tankiness(p); + public static long gymDefense(Pokemon p, boolean useIV) { + + int attackIV = (useIV) ? p.getIndividualAttack() : 0; + + double gymDefense = PokemonUtils.weaveDPS(p, 2000) * (p.getMeta().getBaseAttack() + attackIV) * PokemonUtils.tankiness(p, useIV); return Math.round(gymDefense); } @@ -107,12 +158,17 @@ public static long gymDefense(Pokemon p) { * Used for duel ability & gym defense calculations * * @param p A Pokemon object + * @param useIV Use a pokemon's IV values in the calculations * @return Rating of a Pokemon's tankiness :) * @see https://www.reddit.com/r/TheSilphRoad/comments/4vcobt/posthotfix_pokemon_go_full_moveset_rankings/ * @see i607ch00 */ - public static long tankiness(Pokemon p) { - return (p.getMeta().getBaseStamina() + p.getIndividualStamina()) * (p.getMeta().getBaseDefense() + p.getIndividualDefense()); + public static long tankiness(Pokemon p, boolean useIV) { + + int staminaIV = (useIV) ? p.getIndividualStamina() : 0; + int defenseIV = (useIV) ? p.getIndividualDefense() : 0; + + return (p.getMeta().getBaseStamina() + staminaIV) * (p.getMeta().getBaseDefense() + defenseIV); } /** @@ -128,55 +184,48 @@ public static long tankiness(Pokemon p) { * @see i607ch00 */ public static double weaveDPS(Pokemon p, Integer additionalDelay) { - double critDamageBonus = 0.5; - int chargeDelayMS = 500; PokemonMoveMeta pm1 = PokemonMoveMetaRegistry.getMeta(p.getMove1()); PokemonMoveMeta pm2 = PokemonMoveMetaRegistry.getMeta(p.getMove2()); double moveOneStab = (p.getMeta().getType1().equals(pm1.getType()) || p.getMeta().getType2().equals(pm1.getType())) ? 1.25 : 1; double moveTwoStab = (p.getMeta().getType1().equals(pm2.getType()) || p.getMeta().getType2().equals(pm2.getType())) ? 1.25 : 1; - //=CEILING(AB621/U621) - // *(R621*(1+S621*0.25)) - // +X621*(1+Y621*0.25)*(1+($AJ$1*Z621/100)) - //AB = Move 2 Energy - //U = Move 1 Energy + //Translation reference //R = Move 1 Power //S = Move 1 Stab + //T = Move 1 Speed + //U = Move 1 Energy //X = Move 2 Power //Y = Move 2 Stab - //AJ = Crit Damage Bonus //Z = Move 2 Crit Chance - double weaveCycleDmg = Math.ceil(Math.abs(pm2.getEnergy()) / pm1.getEnergy()) - * (pm1.getPower() * moveOneStab) - + pm2.getPower() * moveTwoStab * (1 + (critDamageBonus * pm2.getCritChance())); - - //=CEILING(AB621/U621) - // *T621 - // +(AA621+$AL$1) - //=CEILING(AB621/U621)*(T621+2000)+(AA621+$AL$1) - //AB = Move 2 Energy - //U = Move 1 Energy - //T = Move 1 Speed //AA = Move 2 Speed - //AL1 = Charge Delay - double weaveCycleLength = Math.ceil(Math.abs(pm2.getEnergy()) / pm1.getEnergy()) - * (pm1.getTime() + additionalDelay) - + (pm2.getTime() + chargeDelayMS); - - //=AC621*FLOOR(100000/AD621) - // + (R621*(1+(S621*0.25))) - // * FLOOR(MOD(100000,AD621)/T621) - //=AC621*FLOOR(100000/AF621)+(R621*(1+(S621*0.25)))*FLOOR(MOD(100000,AF621)/(2000+T621)) + //AB = Move 2 Energy //AC = Weave Cycle Damage - //AD = Weave Cycle Length (ms) - //R = Move 1 Power - //S = Move 1 Stab - //AD = Weave Cycle Length (ms) - //T = Move 1 Speed - double weaveDPS = weaveCycleDmg * Math.floor(100000 / weaveCycleLength) - + (pm1.getPower() * moveOneStab) - * Math.floor((100000 % weaveCycleLength) / (pm1.getTime() + additionalDelay)); + //AD = Average Weave Cycle Length (ms) + //AF = Average Gym Weave Cycle Length (ms) + //AJ1 = Crit Damage Bonus + //AL1 = Charge Delay + + //=IF(AB2=100,CEILING(AB2/U2),AB2/U2) + double weaveEnergyUsageRatio = (Math.abs(pm2.getEnergy()) == 100) ? Math.ceil((double) Math.abs(pm2.getEnergy()) / (double) pm1.getEnergy()) : (double) Math.abs(pm2.getEnergy()) / (double) pm1.getEnergy(); + + //=IF(AB2=100,CEILING(AB2/U2),AB2/U2)*T2+(AA2+$AL$1) + //=IF(AB2=100,CEILING(AB2/U2),AB2/U2)*(T2+2000)+(AA2+$AL$1) + double weaveCycleLength = weaveEnergyUsageRatio * (pm1.getTime() + additionalDelay) + (pm2.getTime() + PokemonUtils.MOVE2_CHARGE_DELAY_MS); + + //=FLOOR(100000/AD2) + //*(X2*(1+Y2*0.25) * (1+($AJ$1*Z2/100))) + //+CEILING(FLOOR(100000/AD2)*IF(AB2=100,CEILING(AB2/U2),AB2/U2)) + //*(R2*(1+(S2*0.25))) + //+FLOOR((100000-(FLOOR(100000/AD2)*(AA2+$AL$1)+CEILING(FLOOR(100000/AD2)*IF(AB2=100,CEILING(AB2/U2),AB2/U2))*T2))/T2) + //*(R2*(1+(S2*0.25))) + //=FLOOR(100000/AF2)*(X2*(1+Y2*0.25)*(1+($AJ$1*Z2/100)))+CEILING(FLOOR(100000/AF2)*IF(AB2=100,CEILING(AB2/U2),AB2/U2))*(R2*(1+(S2*0.25)))+FLOOR((100000-(FLOOR(100000/AF2)*(AA2+$AL$1)+CEILING(FLOOR(100000/AF2)*IF(AB2=100,CEILING(AB2/U2),AB2/U2))*(T2+2000)))/(T2+2000))*(R2*(1+(S2*0.25))) + double weaveDPS = Math.floor(100000 / weaveCycleLength) + * (pm2.getPower() * moveTwoStab * (1 + (PokemonUtils.CRIT_DAMAGE_BONUS * pm2.getCritChance()))) + + Math.ceil(Math.floor(100000 / weaveCycleLength) * weaveEnergyUsageRatio) + * (pm1.getPower() * moveOneStab) + + Math.floor((100000 - (Math.floor(100000 / weaveCycleLength) * (pm2.getTime() + PokemonUtils.MOVE2_CHARGE_DELAY_MS) + Math.ceil(Math.floor(100000 / weaveCycleLength) * weaveEnergyUsageRatio) * (pm1.getTime() + additionalDelay))) / (pm1.getTime() + additionalDelay)) + * (pm1.getPower() * moveOneStab); return weaveDPS; } diff --git a/src/me/corriekay/pokegoutil/windows/PokemonTab.java b/src/me/corriekay/pokegoutil/windows/PokemonTab.java index 0ea0d1aa..4b04a89c 100644 --- a/src/me/corriekay/pokegoutil/windows/PokemonTab.java +++ b/src/me/corriekay/pokegoutil/windows/PokemonTab.java @@ -656,6 +656,12 @@ private void refreshList() { gymAttackCol.setCellRenderer(new MoveSetRankingRenderer(PokemonUtils.GYM_OFFENSE_MAX)); TableColumn gymDefenseCol = this.pt.getColumnModel().getColumn(26); gymDefenseCol.setCellRenderer(new MoveSetRankingRenderer(PokemonUtils.GYM_DEFENSE_MAX)); + TableColumn duelAbilityIVCol = this.pt.getColumnModel().getColumn(29); + duelAbilityIVCol.setCellRenderer(new MoveSetRankingRenderer(PokemonUtils.DUEL_ABILITY_IV_MAX)); + TableColumn gymAttackIVCol = this.pt.getColumnModel().getColumn(30); + gymAttackIVCol.setCellRenderer(new MoveSetRankingRenderer(PokemonUtils.GYM_OFFENSE_IV_MAX)); + TableColumn gymDefenseIVCol = this.pt.getColumnModel().getColumn(31); + gymDefenseIVCol.setCellRenderer(new MoveSetRankingRenderer(PokemonUtils.GYM_DEFENSE_IV_MAX)); } catch (Exception e) { e.printStackTrace(); } @@ -722,10 +728,13 @@ private static class PokemonTable extends JTable { * 22 String(Date) - Caught at * 23 Boolean - Favorite * 24 Long - duelAbility - * 25 Integer - gymOffense - * 26 Integer - gymDefense + * 25 Double - gymOffense + * 26 Long - gymDefense * 27 Double - Move 1 Rating * 28 Double - Move 2 Rating + * 29 Long - duelAbility IV + * 30 Double - gymOffense IV + * 31 Long - gymDefense IV */ ConfigNew config = ConfigNew.getConfig(); @@ -781,10 +790,13 @@ private void constructNewTableModel(PokemonGo go, List pokes) { trs.setComparator(20, c); trs.setComparator(22, cDate); trs.setComparator(24, cLong); - trs.setComparator(25, cLong); + trs.setComparator(25, cDouble); trs.setComparator(26, cLong); trs.setComparator(27, cDouble); trs.setComparator(28, cDouble); + trs.setComparator(29, cLong); + trs.setComparator(30, cDouble); + trs.setComparator(31, cLong); setRowSorter(trs); List sortKeys = new ArrayList<>(); sortKeys.add(new SortKey(sortColIndex1, sortOrder1)); @@ -850,10 +862,13 @@ private static class PokemonTableModel extends AbstractTableModel { caughtCol = new ArrayList<>(),//22 favCol = new ArrayList<>();//23 private final ArrayList duelAbilityCol = new ArrayList<>();//24 - private final ArrayList gymOffenseCol = new ArrayList<>();//25 + private final ArrayList gymOffenseCol = new ArrayList<>();//25 private final ArrayList gymDefenseCol = new ArrayList<>();//26 private final ArrayList move1RatingCol = new ArrayList<>(),//27 move2RatingCol = new ArrayList<>();//28 + private final ArrayList duelAbilityIVCol = new ArrayList<>();//29 + private final ArrayList gymOffenseIVCol = new ArrayList<>();//30 + private final ArrayList gymDefenseIVCol = new ArrayList<>();//31 @Deprecated private PokemonTableModel(PokemonGo go, List pokes, PokemonTable pt) { @@ -955,9 +970,12 @@ private PokemonTableModel(PokemonGo go, List pokes, PokemonTable pt) { pokeballCol.add(i.getValue(), WordUtils.capitalize(p.getPokeball().toString().toLowerCase().replaceAll("item_", "").replaceAll("_", " "))); caughtCol.add(i.getValue(), DateHelper.toString(DateHelper.fromTimestamp(p.getCreationTimeMs()))); favCol.add(i.getValue(), (p.isFavorite()) ? "True" : ""); - duelAbilityCol.add(i.getValue(), PokemonUtils.duelAbility(p)); - gymOffenseCol.add(i.getValue(), PokemonUtils.gymOffense(p)); - gymDefenseCol.add(i.getValue(), PokemonUtils.gymDefense(p)); + duelAbilityCol.add(i.getValue(), PokemonUtils.duelAbility(p, false)); + gymOffenseCol.add(i.getValue(), PokemonUtils.gymOffense(p, false)); + gymDefenseCol.add(i.getValue(), PokemonUtils.gymDefense(p, false)); + duelAbilityIVCol.add(i.getValue(), PokemonUtils.duelAbility(p, true)); + gymOffenseIVCol.add(i.getValue(), PokemonUtils.gymOffense(p, true)); + gymDefenseIVCol.add(i.getValue(), PokemonUtils.gymDefense(p, true)); move1RatingCol.add(i.getValue(), PokemonUtils.moveRating(p, true)); move2RatingCol.add(i.getValue(), PokemonUtils.moveRating(p, false)); i.increment(); @@ -1034,6 +1052,12 @@ public String getColumnName(int columnIndex) { return "Move 1 Rating"; case 28: return "Move 2 Rating"; + case 29: + return "Duel Ability IV"; + case 30: + return "Gym Offense IV"; + case 31: + return "Gym Defense IV"; default: return "UNKNOWN?"; } @@ -1041,7 +1065,7 @@ public String getColumnName(int columnIndex) { @Override public int getColumnCount() { - return 29; + return 32; } @Override @@ -1110,6 +1134,12 @@ public Object getValueAt(int rowIndex, int columnIndex) { return move1RatingCol.get(rowIndex); case 28: return move2RatingCol.get(rowIndex); + case 29: + return duelAbilityIVCol.get(rowIndex); + case 30: + return gymOffenseIVCol.get(rowIndex); + case 31: + return gymDefenseIVCol.get(rowIndex); default: return null; }