mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-24 04:53:08 +00:00
461fb70f90
* Added location to encounter slot to make verification againts the location of the encounter when the pokemon has lost met location, like generation 2 heabutt tree, jhoto surfing in route 45 and in the future generation 4 munchlax tree Added version to generation 1 and 2 encounter locations to filter by catch rate based of the version of the encounter and check initial moves of the encounter only for the game that match the encounter Filter generation 2 pokemon for crystal who have met location based of the time of day when it was captured Completed version to static and traded encounters for gen 1 pokemon, to avoid check a red encounter with yellow initial moves, if an encounter is possible in both games with diferent moves it is duplicated (like eevee), if it is possible in both games with the same moves is left as RBY, the encounter will only use red/blue moveset Verify some invalid gen 2 encounters. Crystall heabutt encounters based on the TID, using the tree selection algorithm of the game to determine if the encounter is possible for the TID (implemented base on https://bulbapedia.bulbagarden.net/wiki/Headbutt_tree#Mechanics). Coordinates of Crystal trees obtained with the programa G2Map Added checks for fishing encounters for unreacheable water tiles in gen 2, route 14, national park and the beta safari zone. * Fix gen 1 static encounters and trade encounters filter by version * Missing strings
146 lines
6.2 KiB
C#
146 lines
6.2 KiB
C#
using System.Linq;
|
|
|
|
namespace PKHeX.Core
|
|
{
|
|
// Pokemon Crystal Headbutt tree encounters by trainer id, base on mechanics described in
|
|
// https://bulbapedia.bulbagarden.net/wiki/Headbutt_tree#Mechanics
|
|
|
|
public enum TreeEncounterAvailable
|
|
{
|
|
ValidTree, // Encounter is possible a reacheable tree
|
|
InvalidTree, // Encounter is only possible a tree reacheable only with walk-trought walls cheats
|
|
Impossible // Encounter is not possible in any tree
|
|
}
|
|
|
|
public class TreeCoordinates
|
|
{
|
|
internal int X { get; set; }
|
|
internal int Y { get; set; }
|
|
internal int Index => ((X * Y + X + Y) / 5) % 10;
|
|
}
|
|
|
|
public class TreesArea
|
|
{
|
|
public int Location { get; private set; }
|
|
public TreeEncounterAvailable[] TrainerModerateEncounterTree { get; private set; }
|
|
public TreeEncounterAvailable[] TrainerLowEncounterTree { get; private set; }
|
|
|
|
private int[] ValidTreeIndex { get; set; }
|
|
private int[] InvalidTreeIndex { get; set; }
|
|
|
|
private TreeCoordinates[] ValidTrees { get; set; }
|
|
private TreeCoordinates[] InvalidTrees { get; set; }
|
|
private static int[][] TrainerModerateTreeIndex { get; set; }
|
|
|
|
internal static TreesArea[] GetArray(byte[][] entries)
|
|
{
|
|
if (entries == null)
|
|
return null;
|
|
TrainerModerateTreeIndex = GenerateTrainersTreeIndex();
|
|
var Areas = new TreesArea[entries.Length];
|
|
for(int i = 0; i < entries.Length; i++)
|
|
{
|
|
Areas[i] = GetArea(entries[i]);
|
|
}
|
|
return Areas;
|
|
}
|
|
|
|
private static int[][] GenerateTrainersTreeIndex()
|
|
{
|
|
// A tree have a low encounter or moderate encounter base on the TID Pivot Index ( TID % 10)
|
|
// Calculate for every Trainer Pivot Index the 5 tree index for low encounters
|
|
int[][] TrainersIndex = new int[10][];
|
|
for (int pivotindex = 0; pivotindex < 10; pivotindex++)
|
|
{
|
|
int[] ModerateEncounterTreeIndex = new int[5];
|
|
for(int index = 0; index <= 4; index++)
|
|
ModerateEncounterTreeIndex[index] = (pivotindex + index) % 10;
|
|
TrainersIndex[pivotindex] = ModerateEncounterTreeIndex.OrderBy(x => x).ToArray();
|
|
}
|
|
return TrainersIndex;
|
|
}
|
|
|
|
private static TreesArea GetArea(byte[] entrie)
|
|
{
|
|
var Area = new TreesArea();
|
|
|
|
Area.ReadAreaRawData(entrie);
|
|
Area.GenerateAreaTreeIndex();
|
|
Area.GenerateAreaTrainerEncounters();
|
|
return Area;
|
|
}
|
|
|
|
private void ReadAreaRawData(byte[] entrie)
|
|
{
|
|
// Coordinates of trees for every are obtained with programa G2Map
|
|
// ValidTrees are those accesible from the player
|
|
// Invalid tress are trees that the player can not reach without cheating devices, like a tree beyond other trees
|
|
Location = entrie[0];
|
|
ValidTrees = new TreeCoordinates[entrie[1]];
|
|
|
|
var ofs = 2;
|
|
for (int i = 0; i < ValidTrees.Length; i++)
|
|
{
|
|
ValidTrees[i] = new TreeCoordinates()
|
|
{
|
|
X = entrie[ofs],
|
|
Y = entrie[ofs + 1]
|
|
};
|
|
ofs += 2;
|
|
}
|
|
InvalidTrees = new TreeCoordinates[entrie[ofs]];
|
|
ofs += 1;
|
|
for (int i = 0; i < InvalidTrees.Length; i++)
|
|
{
|
|
InvalidTrees[i] = new TreeCoordinates()
|
|
{
|
|
X = entrie[ofs],
|
|
Y = entrie[ofs + 1]
|
|
};
|
|
ofs += 2;
|
|
}
|
|
}
|
|
|
|
private void GenerateAreaTreeIndex()
|
|
{
|
|
// For legallity purpose only the tree index is needed, group the trees data by their index, trees with the same index are indistinguible
|
|
ValidTreeIndex = ValidTrees.Select(t => t.Index).Distinct().OrderBy(i => i).ToArray();
|
|
InvalidTreeIndex = InvalidTrees.Select(t => t.Index).Distinct().OrderBy(i => i).Except(ValidTreeIndex).ToArray();
|
|
}
|
|
|
|
private void GenerateAreaTrainerEncounters()
|
|
{
|
|
// Check for every trainer pivot index if there is trees with low encounter and moderate encounter available in the area
|
|
TrainerModerateEncounterTree = new TreeEncounterAvailable[10];
|
|
TrainerLowEncounterTree = new TreeEncounterAvailable[10];
|
|
for (int pivotindex = 0; pivotindex < 10; pivotindex++)
|
|
{
|
|
var TrainerModerateTrees = TrainerModerateTreeIndex[pivotindex];
|
|
|
|
var ModerateValid = ValidTreeIndex.Any(t => TrainerModerateTrees.Contains(t));
|
|
var ModerateInvalid = InvalidTreeIndex.Any(t => TrainerModerateTrees.Contains(t));
|
|
if (ModerateValid)
|
|
// There is a valid tree with an index for moderate encounters
|
|
TrainerModerateEncounterTree[pivotindex] = TreeEncounterAvailable.ValidTree;
|
|
else if (ModerateInvalid)
|
|
// There is a tree with an index for moderate encounters but is invalid
|
|
TrainerModerateEncounterTree[pivotindex] = TreeEncounterAvailable.InvalidTree;
|
|
else
|
|
// No trees for moderate encounters
|
|
TrainerModerateEncounterTree[pivotindex] = TreeEncounterAvailable.Impossible;
|
|
|
|
var LowValid = ValidTreeIndex.Except(TrainerModerateTrees).Any();
|
|
var LowInvalid = InvalidTreeIndex.Except(TrainerModerateTrees).Any();
|
|
if (LowValid)
|
|
// There is a valid tree with an index for low encounters
|
|
TrainerLowEncounterTree[pivotindex] = TreeEncounterAvailable.ValidTree;
|
|
else if (LowInvalid)
|
|
// There is a tree with an index for low encounters but is invalid
|
|
TrainerLowEncounterTree[pivotindex] = TreeEncounterAvailable.InvalidTree;
|
|
else
|
|
// No trees for low encounters
|
|
TrainerLowEncounterTree[pivotindex] = TreeEncounterAvailable.Impossible;
|
|
}
|
|
}
|
|
}
|
|
}
|