summaryrefslogtreecommitdiff
path: root/src/com
diff options
context:
space:
mode:
authortom-overton <tom.overton@outlook.com>2022-03-31 00:07:36 -0700
committertom-overton <tom.overton@outlook.com>2022-03-31 00:07:36 -0700
commit8873998c7f06eb73f968ad007d4dc92b2f88fdd5 (patch)
treeccdd40432fb3f08c66175a50dc970e94942a8da3 /src/com
parentd9ad8f468729a12484df525c94012ccc260d3943 (diff)
Gen 7: Add support for randomizing egg moves
Diffstat (limited to 'src/com')
-rw-r--r--src/com/dabomstew/pkrandom/Randomizer.java11
-rw-r--r--src/com/dabomstew/pkrandom/Version.java5
-rw-r--r--src/com/dabomstew/pkrandom/config/gen7_offsets.ini2
-rwxr-xr-xsrc/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java331
-rwxr-xr-xsrc/com/dabomstew/pkrandom/romhandlers/Gen1RomHandler.java11
-rwxr-xr-xsrc/com/dabomstew/pkrandom/romhandlers/Gen2RomHandler.java11
-rwxr-xr-xsrc/com/dabomstew/pkrandom/romhandlers/Gen3RomHandler.java11
-rwxr-xr-xsrc/com/dabomstew/pkrandom/romhandlers/Gen4RomHandler.java11
-rwxr-xr-xsrc/com/dabomstew/pkrandom/romhandlers/Gen5RomHandler.java11
-rw-r--r--src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java11
-rw-r--r--src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java90
-rwxr-xr-xsrc/com/dabomstew/pkrandom/romhandlers/RomHandler.java6
12 files changed, 404 insertions, 107 deletions
diff --git a/src/com/dabomstew/pkrandom/Randomizer.java b/src/com/dabomstew/pkrandom/Randomizer.java
index 7af4c18..07b627d 100644
--- a/src/com/dabomstew/pkrandom/Randomizer.java
+++ b/src/com/dabomstew/pkrandom/Randomizer.java
@@ -294,6 +294,7 @@ public class Randomizer {
if (settings.getMovesetsMod() != Settings.MovesetsMod.UNCHANGED &&
settings.getMovesetsMod() != Settings.MovesetsMod.METRONOME_ONLY) {
romHandler.randomizeMovesLearnt(settings);
+ romHandler.randomizeEggMoves(settings);
movesetsChanged = true;
}
@@ -737,11 +738,11 @@ public class Randomizer {
log.println("--Pokemon Movesets--");
List<String> movesets = new ArrayList<>();
Map<Integer, List<MoveLearnt>> moveData = romHandler.getMovesLearnt();
+ Map<Integer, List<Integer>> eggMoves = romHandler.getEggMoves();
List<Move> moves = romHandler.getMoves();
List<Pokemon> pkmnList = romHandler.getPokemonInclFormes();
int i = 1;
for (Pokemon pkmn : pkmnList) {
-
if (pkmn == null || pkmn.actuallyCosmetic) {
continue;
}
@@ -780,6 +781,14 @@ public class Randomizer {
sb.append("invalid move at level").append(ml.level);
}
}
+ List<Integer> eggMove = eggMoves.get(pkmn.number);
+ if (eggMove != null && eggMove.size() != 0) {
+ sb.append("Egg Moves:").append(System.getProperty("line.separator"));
+ for (Integer move : eggMove) {
+ sb.append(" - ").append(moves.get(move).name).append(System.getProperty("line.separator"));
+ }
+ }
+
movesets.add(sb.toString());
}
Collections.sort(movesets);
diff --git a/src/com/dabomstew/pkrandom/Version.java b/src/com/dabomstew/pkrandom/Version.java
index 131c213..233a61f 100644
--- a/src/com/dabomstew/pkrandom/Version.java
+++ b/src/com/dabomstew/pkrandom/Version.java
@@ -28,8 +28,8 @@ import java.util.HashMap;
import java.util.Map;
public class Version {
- public static final int VERSION = 318; // Increment by 1 for new version. Updated for 4.4.0
- public static final String VERSION_STRING = "4.4.0";
+ public static final int VERSION = 319; // Increment by 1 for new version. Updated for 4.5.0-dev
+ public static final String VERSION_STRING = "4.5.0-dev";
public static final Map<Integer,String> oldVersions = setupVersionsMap();
@@ -58,6 +58,7 @@ public class Version {
map.put(315, "4.2.0");
map.put(316, "4.2.1");
map.put(317, "4.3.0");
+ map.put(318, "4.4.0");
// Latest version - when version is updated, add the old version as an explicit put
map.put(VERSION, VERSION_STRING);
diff --git a/src/com/dabomstew/pkrandom/config/gen7_offsets.ini b/src/com/dabomstew/pkrandom/config/gen7_offsets.ini
index d761f31..2b7b366 100644
--- a/src/com/dabomstew/pkrandom/config/gen7_offsets.ini
+++ b/src/com/dabomstew/pkrandom/config/gen7_offsets.ini
@@ -4,6 +4,7 @@ TitleId=0004000000164800
Type=SM
Acronym=Su
File<MoveData>=<a/0/1/1, [1E3831AE, 1E3831AE]>
+File<EggMoves>=<a/0/1/2, [0F68D82A, 9D2577C3]>
File<PokemonMovesets>=<a/0/1/3, [4DA9DF72, 4DA9DF72]>
File<PokemonEvolutions>=<a/0/1/4, [4732336F, 4732336F]>
File<MegaEvolutions>=<a/0/1/5, [4001BBAB, 4001BBAB]>
@@ -77,6 +78,7 @@ TitleId=00040000001B5000
Type=USUM
Acronym=US
File<MoveData>=<a/0/1/1, [E8CC46AA, E8CC46AA]>
+File<EggMoves>=<a/0/1/2, [7C24766C, 7C24766C]>
File<PokemonMovesets>=<a/0/1/3, [428BEF17, 428BEF17]>
File<PokemonEvolutions>=<a/0/1/4, [14B009D5, 14B009D5]>
File<MegaEvolutions>=<a/0/1/5, [AA8FA0AF, AA8FA0AF]>
diff --git a/src/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java
index ef3edb6..ae9dc53 100755
--- a/src/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java
@@ -2691,116 +2691,13 @@ public abstract class AbstractRomHandler implements RomHandler {
// Get current sets
Map<Integer, List<MoveLearnt>> movesets = this.getMovesLearnt();
- List<Integer> hms = this.getHMMoves();
- List<Move> allMoves = this.getMoves();
-
- @SuppressWarnings("unchecked")
- Set<Integer> allBanned = new HashSet<Integer>(noBroken ? this.getGameBreakingMoves() : Collections.EMPTY_SET);
- allBanned.addAll(hms);
- allBanned.addAll(this.getMovesBannedFromLevelup());
- allBanned.addAll(GlobalConstants.zMoves);
- allBanned.addAll(this.getIllegalMoves());
// Build sets of moves
List<Move> validMoves = new ArrayList<>();
List<Move> validDamagingMoves = new ArrayList<>();
Map<Type, List<Move>> validTypeMoves = new HashMap<>();
Map<Type, List<Move>> validTypeDamagingMoves = new HashMap<>();
-
- for (Move mv : allMoves) {
- if (mv != null && !GlobalConstants.bannedRandomMoves[mv.number] && !allBanned.contains(mv.number)) {
- validMoves.add(mv);
- if (mv.type != null) {
- if (!validTypeMoves.containsKey(mv.type)) {
- validTypeMoves.put(mv.type, new ArrayList<>());
- }
- validTypeMoves.get(mv.type).add(mv);
- }
-
- if (!GlobalConstants.bannedForDamagingMove[mv.number]) {
- if ((mv.power * mv.hitCount) >= 2 * GlobalConstants.MIN_DAMAGING_MOVE_POWER
- || ((mv.power * mv.hitCount) >= GlobalConstants.MIN_DAMAGING_MOVE_POWER && (mv.hitratio >= 90 || mv.hitratio == perfectAccuracy))) {
- validDamagingMoves.add(mv);
- if (mv.type != null) {
- if (!validTypeDamagingMoves.containsKey(mv.type)) {
- validTypeDamagingMoves.put(mv.type, new ArrayList<>());
- }
- validTypeDamagingMoves.get(mv.type).add(mv);
- }
- }
- }
- }
- }
-
- Map<Type,Double> avgTypePowers = new TreeMap<>();
- double totalAvgPower = 0;
-
- for (Type type: validTypeMoves.keySet()) {
- List<Move> typeMoves = validTypeMoves.get(type);
- int attackingSum = 0;
- for (Move typeMove: typeMoves) {
- if (typeMove.power > 0) {
- attackingSum += (typeMove.power * typeMove.hitCount);
- }
- }
- double avgTypePower = (double)attackingSum / (double)typeMoves.size();
- avgTypePowers.put(type, avgTypePower);
- totalAvgPower += (avgTypePower);
- }
-
- totalAvgPower /= (double)validTypeMoves.keySet().size();
-
- // Want the average power of each type to be within 25% both directions
- double minAvg = totalAvgPower * 0.75;
- double maxAvg = totalAvgPower * 1.25;
-
- // Add extra moves to type lists outside of the range to balance the average power of each type
-
- for (Type type: avgTypePowers.keySet()) {
- double avgPowerForType = avgTypePowers.get(type);
- List<Move> typeMoves = validTypeMoves.get(type);
- List<Move> alreadyPicked = new ArrayList<>();
- int iterLoops = 0;
- while (avgPowerForType < minAvg && iterLoops < 10000) {
- final double finalAvgPowerForType = avgPowerForType;
- List<Move> strongerThanAvgTypeMoves = typeMoves
- .stream()
- .filter(mv -> mv.power * mv.hitCount > finalAvgPowerForType)
- .collect(Collectors.toList());
- if (strongerThanAvgTypeMoves.isEmpty()) break;
- if (alreadyPicked.containsAll(strongerThanAvgTypeMoves)) {
- alreadyPicked = new ArrayList<>();
- } else {
- strongerThanAvgTypeMoves.removeAll(alreadyPicked);
- }
- Move extraMove = strongerThanAvgTypeMoves.get(random.nextInt(strongerThanAvgTypeMoves.size()));
- avgPowerForType = (avgPowerForType * typeMoves.size() + extraMove.power * extraMove.hitCount)
- / (typeMoves.size() + 1);
- typeMoves.add(extraMove);
- alreadyPicked.add(extraMove);
- iterLoops++;
- }
- iterLoops = 0;
- while (avgPowerForType > maxAvg && iterLoops < 10000) {
- final double finalAvgPowerForType = avgPowerForType;
- List<Move> weakerThanAvgTypeMoves = typeMoves
- .stream()
- .filter(mv -> mv.power * mv.hitCount < finalAvgPowerForType)
- .collect(Collectors.toList());
- if (weakerThanAvgTypeMoves.isEmpty()) break;
- if (alreadyPicked.containsAll(weakerThanAvgTypeMoves)) {
- alreadyPicked = new ArrayList<>();
- } else {
- weakerThanAvgTypeMoves.removeAll(alreadyPicked);
- }
- Move extraMove = weakerThanAvgTypeMoves.get(random.nextInt(weakerThanAvgTypeMoves.size()));
- avgPowerForType = (avgPowerForType * typeMoves.size() + extraMove.power * extraMove.hitCount)
- / (typeMoves.size() + 1);
- typeMoves.add(extraMove);
- alreadyPicked.add(extraMove);
- iterLoops++;
- }
- }
+ createSetsOfMoves(noBroken, validMoves, validDamagingMoves, validTypeMoves, validTypeDamagingMoves);
for (Integer pkmnNum : movesets.keySet()) {
List<Integer> learnt = new ArrayList<>();
@@ -2966,6 +2863,232 @@ public abstract class AbstractRomHandler implements RomHandler {
}
@Override
+ public void randomizeEggMoves(Settings settings) {
+ boolean typeThemed = settings.getMovesetsMod() == Settings.MovesetsMod.RANDOM_PREFER_SAME_TYPE;
+ boolean noBroken = settings.isBlockBrokenMovesetMoves();
+ double goodDamagingPercentage =
+ settings.isMovesetsForceGoodDamaging() ? settings.getMovesetsGoodDamagingPercent() / 100.0 : 0;
+
+ // Get current sets
+ Map<Integer, List<Integer>> movesets = this.getEggMoves();
+
+ // Build sets of moves
+ List<Move> validMoves = new ArrayList<>();
+ List<Move> validDamagingMoves = new ArrayList<>();
+ Map<Type, List<Move>> validTypeMoves = new HashMap<>();
+ Map<Type, List<Move>> validTypeDamagingMoves = new HashMap<>();
+ createSetsOfMoves(noBroken, validMoves, validDamagingMoves, validTypeMoves, validTypeDamagingMoves);
+
+ for (Integer pkmnNum : movesets.keySet()) {
+ List<Integer> learnt = new ArrayList<>();
+ List<Integer> moves = movesets.get(pkmnNum);
+ Pokemon pkmn = findPokemonInPoolWithSpeciesID(mainPokemonListInclFormes, pkmnNum);
+ if (pkmn == null) {
+ continue;
+ }
+
+ double atkSpAtkRatio = pkmn.getAttackSpecialAttackRatio();
+
+ if (pkmn.actuallyCosmetic) {
+ for (int i = 0; i < moves.size(); i++) {
+ moves.set(i, movesets.get(pkmn.baseForme.number).get(i));
+ }
+ continue;
+ }
+
+ // Force a certain amount of good damaging moves depending on the percentage
+ int goodDamagingLeft = (int)Math.round(goodDamagingPercentage * moves.size());
+
+ // Replace moves as needed
+ for (int i = 0; i < moves.size(); i++) {
+ // should this move be forced damaging?
+ boolean attemptDamaging = goodDamagingLeft > 0;
+
+ // type themed?
+ Type typeOfMove = null;
+ if (typeThemed) {
+ double picked = random.nextDouble();
+ if ((pkmn.primaryType == Type.NORMAL && pkmn.secondaryType != null) ||
+ (pkmn.secondaryType == Type.NORMAL)) {
+
+ Type otherType = pkmn.primaryType == Type.NORMAL ? pkmn.secondaryType : pkmn.primaryType;
+
+ // Normal/OTHER: 10% normal, 30% other, 60% random
+ if (picked < 0.1) {
+ typeOfMove = Type.NORMAL;
+ } else if (picked < 0.4) {
+ typeOfMove = otherType;
+ }
+ // else random
+ } else if (pkmn.secondaryType != null) {
+ // Primary/Secondary: 20% primary, 20% secondary, 60% random
+ if (picked < 0.2) {
+ typeOfMove = pkmn.primaryType;
+ } else if (picked < 0.4) {
+ typeOfMove = pkmn.secondaryType;
+ }
+ // else random
+ } else {
+ // Primary/None: 40% primary, 60% random
+ if (picked < 0.4) {
+ typeOfMove = pkmn.primaryType;
+ }
+ // else random
+ }
+ }
+
+ // select a list to pick a move from that has at least one free
+ List<Move> pickList = validMoves;
+ if (attemptDamaging) {
+ if (typeOfMove != null) {
+ if (validTypeDamagingMoves.containsKey(typeOfMove)
+ && checkForUnusedMove(validTypeDamagingMoves.get(typeOfMove), learnt)) {
+ pickList = validTypeDamagingMoves.get(typeOfMove);
+ } else if (checkForUnusedMove(validDamagingMoves, learnt)) {
+ pickList = validDamagingMoves;
+ }
+ } else if (checkForUnusedMove(validDamagingMoves, learnt)) {
+ pickList = validDamagingMoves;
+ }
+ MoveCategory forcedCategory = random.nextDouble() < atkSpAtkRatio ? MoveCategory.PHYSICAL : MoveCategory.SPECIAL;
+ List<Move> filteredList = pickList.stream().filter(mv -> mv.category == forcedCategory).collect(Collectors.toList());
+ if (!filteredList.isEmpty() && checkForUnusedMove(filteredList, learnt)) {
+ pickList = filteredList;
+ }
+ } else if (typeOfMove != null) {
+ if (validTypeMoves.containsKey(typeOfMove)
+ && checkForUnusedMove(validTypeMoves.get(typeOfMove), learnt)) {
+ pickList = validTypeMoves.get(typeOfMove);
+ }
+ }
+
+ // now pick a move until we get a valid one
+ Move mv = pickList.get(random.nextInt(pickList.size()));
+ while (learnt.contains(mv.number)) {
+ mv = pickList.get(random.nextInt(pickList.size()));
+ }
+
+ goodDamagingLeft--;
+ learnt.add(mv.number);
+ }
+
+ // write all moves for the pokemon
+ Collections.shuffle(learnt, random);
+ for (int i = 0; i < learnt.size(); i++) {
+ moves.set(i, learnt.get(i));
+ }
+ }
+ // Done, save
+ this.setEggMoves(movesets);
+ }
+
+ private void createSetsOfMoves(boolean noBroken, List<Move> validMoves, List<Move> validDamagingMoves,
+ Map<Type, List<Move>> validTypeMoves, Map<Type, List<Move>> validTypeDamagingMoves) {
+ List<Move> allMoves = this.getMoves();
+ List<Integer> hms = this.getHMMoves();
+ Set<Integer> allBanned = new HashSet<Integer>(noBroken ? this.getGameBreakingMoves() : Collections.EMPTY_SET);
+ allBanned.addAll(hms);
+ allBanned.addAll(this.getMovesBannedFromLevelup());
+ allBanned.addAll(GlobalConstants.zMoves);
+ allBanned.addAll(this.getIllegalMoves());
+
+ for (Move mv : allMoves) {
+ if (mv != null && !GlobalConstants.bannedRandomMoves[mv.number] && !allBanned.contains(mv.number)) {
+ validMoves.add(mv);
+ if (mv.type != null) {
+ if (!validTypeMoves.containsKey(mv.type)) {
+ validTypeMoves.put(mv.type, new ArrayList<>());
+ }
+ validTypeMoves.get(mv.type).add(mv);
+ }
+
+ if (!GlobalConstants.bannedForDamagingMove[mv.number]) {
+ if ((mv.power * mv.hitCount) >= 2 * GlobalConstants.MIN_DAMAGING_MOVE_POWER
+ || ((mv.power * mv.hitCount) >= GlobalConstants.MIN_DAMAGING_MOVE_POWER && (mv.hitratio >= 90 || mv.hitratio == perfectAccuracy))) {
+ validDamagingMoves.add(mv);
+ if (mv.type != null) {
+ if (!validTypeDamagingMoves.containsKey(mv.type)) {
+ validTypeDamagingMoves.put(mv.type, new ArrayList<>());
+ }
+ validTypeDamagingMoves.get(mv.type).add(mv);
+ }
+ }
+ }
+ }
+ }
+
+ Map<Type,Double> avgTypePowers = new TreeMap<>();
+ double totalAvgPower = 0;
+
+ for (Type type: validTypeMoves.keySet()) {
+ List<Move> typeMoves = validTypeMoves.get(type);
+ int attackingSum = 0;
+ for (Move typeMove: typeMoves) {
+ if (typeMove.power > 0) {
+ attackingSum += (typeMove.power * typeMove.hitCount);
+ }
+ }
+ double avgTypePower = (double)attackingSum / (double)typeMoves.size();
+ avgTypePowers.put(type, avgTypePower);
+ totalAvgPower += (avgTypePower);
+ }
+
+ totalAvgPower /= (double)validTypeMoves.keySet().size();
+
+ // Want the average power of each type to be within 25% both directions
+ double minAvg = totalAvgPower * 0.75;
+ double maxAvg = totalAvgPower * 1.25;
+
+ // Add extra moves to type lists outside of the range to balance the average power of each type
+
+ for (Type type: avgTypePowers.keySet()) {
+ double avgPowerForType = avgTypePowers.get(type);
+ List<Move> typeMoves = validTypeMoves.get(type);
+ List<Move> alreadyPicked = new ArrayList<>();
+ int iterLoops = 0;
+ while (avgPowerForType < minAvg && iterLoops < 10000) {
+ final double finalAvgPowerForType = avgPowerForType;
+ List<Move> strongerThanAvgTypeMoves = typeMoves
+ .stream()
+ .filter(mv -> mv.power * mv.hitCount > finalAvgPowerForType)
+ .collect(Collectors.toList());
+ if (strongerThanAvgTypeMoves.isEmpty()) break;
+ if (alreadyPicked.containsAll(strongerThanAvgTypeMoves)) {
+ alreadyPicked = new ArrayList<>();
+ } else {
+ strongerThanAvgTypeMoves.removeAll(alreadyPicked);
+ }
+ Move extraMove = strongerThanAvgTypeMoves.get(random.nextInt(strongerThanAvgTypeMoves.size()));
+ avgPowerForType = (avgPowerForType * typeMoves.size() + extraMove.power * extraMove.hitCount)
+ / (typeMoves.size() + 1);
+ typeMoves.add(extraMove);
+ alreadyPicked.add(extraMove);
+ iterLoops++;
+ }
+ iterLoops = 0;
+ while (avgPowerForType > maxAvg && iterLoops < 10000) {
+ final double finalAvgPowerForType = avgPowerForType;
+ List<Move> weakerThanAvgTypeMoves = typeMoves
+ .stream()
+ .filter(mv -> mv.power * mv.hitCount < finalAvgPowerForType)
+ .collect(Collectors.toList());
+ if (weakerThanAvgTypeMoves.isEmpty()) break;
+ if (alreadyPicked.containsAll(weakerThanAvgTypeMoves)) {
+ alreadyPicked = new ArrayList<>();
+ } else {
+ weakerThanAvgTypeMoves.removeAll(alreadyPicked);
+ }
+ Move extraMove = weakerThanAvgTypeMoves.get(random.nextInt(weakerThanAvgTypeMoves.size()));
+ avgPowerForType = (avgPowerForType * typeMoves.size() + extraMove.power * extraMove.hitCount)
+ / (typeMoves.size() + 1);
+ typeMoves.add(extraMove);
+ alreadyPicked.add(extraMove);
+ iterLoops++;
+ }
+ }
+ }
+
+ @Override
public void orderDamagingMovesByDamage() {
Map<Integer, List<MoveLearnt>> movesets = this.getMovesLearnt();
List<Move> allMoves = this.getMoves();
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen1RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen1RomHandler.java
index d7d6716..c6869d6 100755
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen1RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen1RomHandler.java
@@ -1323,6 +1323,17 @@ public class Gen1RomHandler extends AbstractGBCRomHandler {
writeEvosAndMovesLearnt(false, movesets);
}
+ @Override
+ public Map<Integer, List<Integer>> getEggMoves() {
+ // Gen 1 does not have egg moves
+ return new TreeMap<>();
+ }
+
+ @Override
+ public void setEggMoves(Map<Integer, List<Integer>> eggMoves) {
+ // Gen 1 does not have egg moves
+ }
+
private static class StaticPokemon {
protected int[] speciesOffsets;
protected int[] levelOffsets;
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen2RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen2RomHandler.java
index 123308b..72ded29 100755
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen2RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen2RomHandler.java
@@ -1059,6 +1059,17 @@ public class Gen2RomHandler extends AbstractGBCRomHandler {
return Gen2Constants.bannedLevelupMoves;
}
+ @Override
+ public Map<Integer, List<Integer>> getEggMoves() {
+ // Not currently implemented
+ return new TreeMap<>();
+ }
+
+ @Override
+ public void setEggMoves(Map<Integer, List<Integer>> eggMoves) {
+ // Not currently implemented
+ }
+
private static class StaticPokemon {
protected int[] speciesOffsets;
protected int[] levelOffsets;
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen3RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen3RomHandler.java
index db51baa..17ed875 100755
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen3RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen3RomHandler.java
@@ -1771,6 +1771,17 @@ public class Gen3RomHandler extends AbstractGBRomHandler {
}
}
+ @Override
+ public Map<Integer, List<Integer>> getEggMoves() {
+ // Not currently implemented
+ return new TreeMap<>();
+ }
+
+ @Override
+ public void setEggMoves(Map<Integer, List<Integer>> eggMoves) {
+ // Not currently implemented
+ }
+
private static class StaticPokemon {
private int[] speciesOffsets;
private int[] levelOffsets;
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen4RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen4RomHandler.java
index 9270bb3..4b13209 100755
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen4RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen4RomHandler.java
@@ -2787,6 +2787,17 @@ public class Gen4RomHandler extends AbstractDSRomHandler {
}
+ @Override
+ public Map<Integer, List<Integer>> getEggMoves() {
+ // Not currently implemented
+ return new TreeMap<>();
+ }
+
+ @Override
+ public void setEggMoves(Map<Integer, List<Integer>> eggMoves) {
+ // Not currently implemented
+ }
+
private static class ScriptEntry {
private int scriptFile;
private int scriptOffset;
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen5RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen5RomHandler.java
index 7826675..9168617 100755
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen5RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen5RomHandler.java
@@ -1712,6 +1712,17 @@ public class Gen5RomHandler extends AbstractDSRomHandler {
}
+ @Override
+ public Map<Integer, List<Integer>> getEggMoves() {
+ // Not currently implemented
+ return new TreeMap<>();
+ }
+
+ @Override
+ public void setEggMoves(Map<Integer, List<Integer>> eggMoves) {
+ // Not currently implemented
+ }
+
private static class FileEntry {
private int file;
private int offset;
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java
index 565dab2..9423f3c 100644
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java
@@ -2034,6 +2034,17 @@ public class Gen6RomHandler extends Abstract3DSRomHandler {
}
@Override
+ public Map<Integer, List<Integer>> getEggMoves() {
+ // Not currently implemented
+ return new TreeMap<>();
+ }
+
+ @Override
+ public void setEggMoves(Map<Integer, List<Integer>> eggMoves) {
+ // Not currently implemented
+ }
+
+ @Override
public boolean canChangeStaticPokemon() {
return romEntry.staticPokemonSupport;
}
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java
index 06d6ef4..6cdd19f 100644
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java
@@ -1792,6 +1792,96 @@ public class Gen7RomHandler extends Abstract3DSRomHandler {
}
@Override
+ public Map<Integer, List<Integer>> getEggMoves() {
+ Map<Integer, List<Integer>> eggMoves = new TreeMap<>();
+ try {
+ GARCArchive eggMovesGarc = this.readGARC(romEntry.getFile("EggMoves"),true);
+ TreeMap<Pokemon, Integer> altFormeEggMoveFiles = new TreeMap<>();
+ for (int i = 1; i <= Gen7Constants.getPokemonCount(romEntry.romType); i++) {
+ Pokemon pkmn = pokes[i];
+ byte[] movedata = eggMovesGarc.files.get(i).get(0);
+ int formeReference = readWord(movedata, 0);
+ if (formeReference != pkmn.number) {
+ altFormeEggMoveFiles.put(pkmn, formeReference);
+ }
+ int numberOfEggMoves = readWord(movedata, 2);
+ List<Integer> moves = new ArrayList<>();
+ for (int j = 0; j < numberOfEggMoves; j++) {
+ int move = readWord(movedata, 4 + (j * 2));
+ moves.add(move);
+ }
+ eggMoves.put(pkmn.number, moves);
+ }
+ Iterator<Pokemon> iter = altFormeEggMoveFiles.keySet().iterator();
+ while (iter.hasNext()) {
+ Pokemon originalForme = iter.next();
+ int formeNumber = 1;
+ int fileNumber = altFormeEggMoveFiles.get(originalForme);
+ Pokemon altForme = getAltFormeOfPokemon(originalForme, formeNumber);
+ while (!originalForme.equals(altForme)) {
+ byte[] movedata = eggMovesGarc.files.get(fileNumber).get(0);
+ int numberOfEggMoves = readWord(movedata, 2);
+ List<Integer> moves = new ArrayList<>();
+ for (int j = 0; j < numberOfEggMoves; j++) {
+ int move = readWord(movedata, 4 + (j * 2));
+ moves.add(move);
+ }
+ eggMoves.put(altForme.number, moves);
+ formeNumber++;
+ fileNumber++;
+ altForme = getAltFormeOfPokemon(originalForme, formeNumber);
+ }
+ iter.remove();
+ }
+ } catch (IOException e) {
+ throw new RandomizerIOException(e);
+ }
+ return eggMoves;
+ }
+
+ @Override
+ public void setEggMoves(Map<Integer, List<Integer>> eggMoves) {
+ try {
+ GARCArchive eggMovesGarc = this.readGARC(romEntry.getFile("EggMoves"), true);
+ TreeMap<Pokemon, Integer> altFormeEggMoveFiles = new TreeMap<>();
+ for (int i = 1; i <= Gen7Constants.getPokemonCount(romEntry.romType); i++) {
+ Pokemon pkmn = pokes[i];
+ byte[] movedata = eggMovesGarc.files.get(i).get(0);
+ int formeReference = readWord(movedata, 0);
+ if (formeReference != pkmn.number) {
+ altFormeEggMoveFiles.put(pkmn, formeReference);
+ }
+ List<Integer> moves = eggMoves.get(pkmn.number);
+ for (int j = 0; j < moves.size(); j++) {
+ writeWord(movedata, 4 + (j * 2), moves.get(j));
+ }
+ }
+ Iterator<Pokemon> iter = altFormeEggMoveFiles.keySet().iterator();
+ while (iter.hasNext()) {
+ Pokemon originalForme = iter.next();
+ int formeNumber = 1;
+ int fileNumber = altFormeEggMoveFiles.get(originalForme);
+ Pokemon altForme = getAltFormeOfPokemon(originalForme, formeNumber);
+ while (!originalForme.equals(altForme)) {
+ byte[] movedata = eggMovesGarc.files.get(fileNumber).get(0);
+ List<Integer> moves = eggMoves.get(altForme.number);
+ for (int j = 0; j < moves.size(); j++) {
+ writeWord(movedata, 4 + (j * 2), moves.get(j));
+ }
+ formeNumber++;
+ fileNumber++;
+ altForme = getAltFormeOfPokemon(originalForme, formeNumber);
+ }
+ iter.remove();
+ }
+ // Save
+ this.writeGARC(romEntry.getFile("EggMoves"), eggMovesGarc);
+ } catch (IOException e) {
+ throw new RandomizerIOException(e);
+ }
+ }
+
+ @Override
public boolean canChangeStaticPokemon() {
return true;
}
diff --git a/src/com/dabomstew/pkrandom/romhandlers/RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/RomHandler.java
index 5b0f266..a0f5dd6 100755
--- a/src/com/dabomstew/pkrandom/romhandlers/RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/RomHandler.java
@@ -303,8 +303,14 @@ public interface RomHandler {
List<Integer> getMovesBannedFromLevelup();
+ Map<Integer, List<Integer>> getEggMoves();
+
+ void setEggMoves(Map<Integer, List<Integer>> eggMoves);
+
void randomizeMovesLearnt(Settings settings);
+ void randomizeEggMoves(Settings settings);
+
void orderDamagingMovesByDamage();
void metronomeOnlyMode();