Relocate the SetRandomEC at the tail end of the generator into the specific classes that set EC, so that our correlation generators don't have their EC overwritten at the end.
Disassociate pk4/pk6 backing byte[] when converting to pk5|pk7, as we no longer make a copy of the byte[] in the pkm's constructor.
Change UpdatePKM to include isParty, as we want it optional to update FormArgument too.
Change FormArgument saving to be handled by FormConverter; kinda not really good to have it there, but nothing else is handling FormArgument values.
Expand IFormArgument to have all FormArgument values exposed. "Maximum" is furfrou only.
PK6: Max is in the "FormArgument" u32, and the remain/elapsed is in party stats (hence the reverting when boxed)
PK7: u8 remain, u8 elapsed, u8 max, u8 unused.
PK8: assumedly the same as PK7, given the disassembly hints that it's the same as past games (even though Furfrou and Hoopa are not in SWSH).
Update dictionary to use proper format (yyyy-mm-dd), as well as verifier to properly check met year.
Also updated IsValidDateWC8 to clamp latest met date based on UTC, like with GO encounters.
Checks partial matches in the loop rather than outside; it'll only settle on the partial match if there's nothing else to settle on.
Gen1/2 generators can have partial matches bubble up before actual matches (gen1 fighting gen2).
I should probably have slot1/2 and static1/2 and trade1/2 implement GetBlank so that they can flexibly return a japanese/int/(kor) from template rather than default int, but eh
The Encounter dumper project already excluded all headbutt tree areas that can't be accessed. Every slot that is present in this project can be accessed.
Move the tree check to the eslot2 object
Check all gen2 slots regardless of crystal origin, since we now tag all of them with location IDs.
## Issue
We want to discard-but-remember any slots that aren't a perfect fit, on the off chance that a better one exists later in the search space. If there's no better match, then we gotta go with what we got.
## Example:
Wurmple exists in area `X`, and also has a more rare slot for Silcoon, with the same level for both slots.
* We have a Silcoon that we've leveled up a few times.
Was our Silcoon originally a Wurmple, or was it caught as a Silcoon?
* To be sure, we have to check the EC/PID if the Wurmple wouldn't evolve into Cascoon instead.
* We don't want to wholly reject that Wurmple slot, as maybe the Met Level isn't within Silcoon's slot range.
---
Existing implementation would store "deferred" matches in a list; we only need to keep 1 of these matches around (less allocation!). We also want to differentiate between a "good" deferral and a "bad" deferral; I don't think this is necessary but it's currently used by Mystery Gift matching (implemented for the Eeveelution mystery gifts which matter for evolution moves).
The existing logic didn't use inheritance, and instead had static methods being reused across generations. Quite kludgy. Also, the existing logic was a pain to modify the master encounter yield methods, as one generation's quirks had to not impact all other generations that used the method.
---
The new implementation splits out the encounter yielding methods to be separate for each generation / subset. Now, things don't have to check `WasLink` for Gen7 origin, because Pokémon Link wasn't a thing in Gen7.
---
## Future
Maybe refactoring yielders into "GameCores" that expose yielding behaviors / properties, rather than the static logic. As more generations and side-gamegroups get added (thanks LGPE/GO/GameCube), all this switch stuff gets annoying to maintain instead of just overriding/inheritance.
## Conclusion
This shouldn't impact any legality results negatively; if you notice any regressions, report them! This should reduce false flags where we didn't defer-discard an encounter when we should have (wild area mons being confused with raids).
Closes#3133
not an ideal solution, but the encounter matching API is kinda limited in deferred-invalid vs deferred-notIdeal.
probably need to unify the match logic and generators so they can cache one secondary-check invalid
See the EncounterSlotDumper with the memoization logic & json tree listing.
Simplifies things a lot, and improves checking speed. Unreachable trees are now treated the same as no-trees maps.
ez 1.5KB reduction in file size :P
Remove gen3 egg location hashset; only paths that reach it are for hatched eggs or current breed-eggs. Check breed eggs with the singular met location.
Simplify some logic flow
This only matches the weather table with the Pokemon and does not fully
account for whether a location can spawn a particular weather.
Additional minor changes:
- Adds ScriptedNoMarks to Regis and Glimwood Tangle static encounters
- Corrects a few version-specific Pokemon such as Ludicolo/Shiftry
- Removes erroneous encounters such as Milotic in East/West Lake Axewell
- Removes an unused Motostoke Stadium encounter
Nickname AND Trainer Name are verified in that method; we still want to execute it. If it has a fixed nickname, we can skip the wordfilter since it's already been checked.
clean:
if (!logical) return;
Existing logic had methods named to return true if fail, now method checks for passing, thus the logic now follows the above pattern.
Simplify some method signatures, reduce checks for MoveEgg.GetEggMoves
ran legality checks for 100,000 pkm, no more exceptions (Internal Error) -- added a "CanGameGenerateEggs" which filters out unused gameIDs
GameStrings: 10% of strings are unique; just mark everything. Stop a little early so we don't process the empty & (trade) string.
LearnsetReader: All empty entries are length==0; malformed should throw an exception (never).
EggMoves: Compute ptr inside the array fetch loop; don't use linq.
EggMoves & string shaves off 80ms of startup time according to profiling; some could be attributed to warm-up but yay more efficient.
Some special encounters don't set the Relearn Moves, so we can't really check the memory-moves unless we somehow late-reject a matching encounter. Not really worth the effort to try and verify cosmetic mismatches; just tag them as Fishy.
AltForm & Form & Forme => Form
GenNumber & Generation => Generation
Extract out SpeciesForm interface, and re-add IGeneration
For those using PKHeX as a dependency, this should be a pretty straightforward manual replacement... GenNumber and AltForm should be quick find-replace`s.
Metagross collision with wild beldum
deferral API is kinda crude, hence these janky workarounds. Was originally intended to hold onto close matches when there's no more possible matches to check.
I think a priority-deferral while only retaining a single encounter bad (instead of a list of retries) may work better than the current setup, but that would require more abstraction
Transporter remaps certain locale specific chars depending on the source ROM's version.
Since VC can trade between languages, there are 2 Spanish in-game trades that have glyphs subject to remapping, if it's transferred from a French game.
If the spanish trade is transferred from a french game, it must match the mutated string.
ty @Lusamine & helpers :D
Slap in friend safari at the end during object construction; saves about 1KB of allocation on startup (lol)
Change internal array types to match object types, similar to other encounter-generation definitions.
Trees:
- Only retain the objects needed after calculation
- Reduce size of TreeCoordinates and remove allocation penalty (now a struct)
No more warnings for Release compilation :D
I think this was a PKHeX issue that went unnoticed; originally, we didn't include the Á and Í chars in the dictionary.
I checked the transporter code:
The app maintains the international & japanese character tables, and depending on the ROM language, it may change a char to the language-specific entry. Refer to Bulbapedia's notes on the char tables for different languages:
https://bulbapedia.bulbagarden.net/wiki/Character_encoding_in_Generation_II
However, none of these char-changes are able to be reached with a legal char.
Á and Í (only accessible from the Spanish in-game trades) and the german 0xC0 && z <= 0xC6 chars are already in the international table. Every single difference in the VC1/VC2 table is an un-enterable char.
tl;dr -- all possible char codes are transferred fine with the VC2 table without extra language logic. We just keep out any inaccessible char (replaced with space).
Move form-info logic from FormConverter to AltFormInfo; now FormConverter is entirely form=>string[]
Add a bunch of xmldoc
Make pogo no-end-date cmp agaisnt UTCnow rather than local now.
from 319 (max HP-1) to 9999 (max saved value).
Causes a little bit of GUI lag when loading 10k items to the combobox; could be a number entry but meh. Lazily allocate the 10k strings; wait until it's requested.
Event Move special encounters are yielded after static encounters by the generator, so this iterator-picker will never behave as originally intended.
Since the encounter generator works fine for these events in its current form, we can just remove it. If we need to prefer GB era events before static, then we'd reinstate the priority and move the GenerateGBEvents before the static yielder.
bla bla bla this is just a cleanup from old preference code where we wanted to recognize the encounter as an event/trade as they're more recognizable. We just want to track the progress of the iterator so that g1/g2 follow a merged yielding order
Adds Nickname checks, thanks @ShadowMario3 for grabbing these into separate text files from Bulbapedia.
I reordered all the encounters to match Bulbapedia; each level is denoted if different if it can be sourced from RBY.
Extract common abstract class for GO transferred encounters
Clamp minlevel instead of met level
Add optional parameter for GO IV randomization
Update go legality binaries with latest
PKHeX.Core now accepts generated pkl binaries from PoGoEncounterTool (PGET).
Refer to pporg's repo. This will be treated like event data; occasionally updated.
took me less than an hour to do these changes, and i can flag bad form movesets no problemo
Expect tightening of restrictions (ball, level, shininess) later
if someone wants to curate met date restrictions, go ahead!
Sure it's nice to cache a valid array, but the amount of logic was small enough that it can be done with 10 lines of code rather than at the end of each verification method.
Reduces parameter passing & removes 1 field from the info object, as relearn suggestions are only done rarely after legality checking.
Allows for a simpler api surface (pkm, encounter) rather than a bigger object reference
4 legends have A/A/H on form-0, and B/B/B on form-1. You can get a form-1 by applying the patch on the form-0, and changing it to form-1 will retain the AbilityNumber=4.
Co-Authored-By: Matt <17801814+sora10pls@users.noreply.github.com>
Closes#3070
Exclude all classified as Legends; everything else is permitted assuming it can exist in SW/SH.
Co-Authored-By: Chris <28743231+Bappsack@users.noreply.github.com>
Closes#3040
Ty @Atrius97 !
"The Japanese Aurora Ticket was only distributed in Summer 2004, before Emerald (Sept 16th 2004) was released. The software at that time had no support for Emerald games."
Alakazam in the Insular Sea (on the Isle of Armor)
Zapdos at Watchtower Ruins (in a Wild Area)
Zapdos at West Lake Axewell (in a Wild Area)
Moltres in the Soothing Wetlands (on the Isle of Armor)
Moltres on Challenge Beach (on the Isle of Armor)
Moltres in Loop Lagoon (on the Isle of Armor)
Dragapult in the Giant’s Bed (in the Crown Tundra)
Nidorina in Frostpoint Field (in the Crown Tundra)
Glalie on Snowslide Slope (in the Crown Tundra)
Closes#3027
Roamers: Get PID generated externally
NPokemon: Get PID from a fixed value
Forced (Anti)Shiny: Get PID altered
Thanks @LegoFigure11 && Princess Emily (discord 4650) !
Handles conditions when Ability Patch has been used to modify the PKM's ability => hidden ability.
Per the description, it goes 1/2=>H, not the other way around.
Verify ability bit first, as mystery gift case handling skips the bit check logic :P
Rather than do backtracking logic to see if the slot can be yielded, don't acknowledge the slot exists if it can't be yielded.
See pk3DS commit where we check EscapeRate for the base wild slot prior to adding it to the exported slot list.
A Gen3 level 26 sylveon with a met level of 25 in Generation 8:
Transferred as Eevee at level 25, and leveled up to 26=>Sylveon
If we use met_level (25), we need to decrease 1 as we evolve. No, use Current Level and ensure the max isn't above the bare minimum (met level)
Starting in Generation 8, hatched language-traded eggs will take the Language from the trainer that hatched it.
Transferring from Gen7->Gen8 realigns the Nickname string to the Language, if not nicknamed.
The game uses 0x5E if 0x5A+everstone, otherwise it uses 0x58
For determining the seed species-form, we want to use everstone breeds as that resolves to the correct species-form values.
Co-Authored-By: Lusamine <30205550+Lusamine@users.noreply.github.com>
Co-Authored-By: Marty-D <1645989+Marty-D@users.noreply.github.com>
Handle yielding in the moveset generator as well
Future commits will trim down unused values/abstractions; probably can get all the stadium stuff handled innately
Revises the tradeback status to remove any index that could have been sourced from egg moves instead.
really should refactor this TradebackStatus away, but Move validation still remains one of the un-refined parts of the legality checks :P
now that stadium saves all expose registered teams, can just call from the parent class
rental sk2's have no TID; add that to the requirement to not get flagged for missing OT
Closes#3009
Make QRPK7 implement IEncounterable and remove hardcoded PKHeX strings
Let force hatching for WC3 eggs try to hatch from the savefile's language, then revert to english if failed to set an OT.
Use underscores for enum for ToString replacing with spaces
Don't flag empty-OT as SK2; Stadium0/1 use the "TRAINER" as rental, but leave it blank for SK2.
Don't set any terminators for an OT string if the string is empty; just wipe the buffer.
Introducing a new PKM format: SK2
Split ICaughtData2 off of PK2 so it can be shared with SK2 when type-checks occur
Add conversion for PK2<->SK2
Split the split-buffer handling for GBPKM to GBPKML (what a name), so that I can reuse shared accessor logic for SK2.
Move Home8 location to Locations.cs for documentation
Move FestaFacility to correct folder
Remove unnecessary public modifier on interface method
Pass the program's Version to any loaded plugins, if they wanted to check compatibility...?
Closes#2990 ty @Atrius97 !
Remove the `object Content` accessor only used for Mystery Gifts (used to trickle up the PKM object since the two ribbon interfaces weren't implemented on the IEncounterable). Just make PCD/PGT implement the ribbon interfaces and delegate the get/set to PKM directly.
Rewrite the national ribbon check for clarity
Optimize invalid/missing ribbon string replace to operate on the final string rather than do linq and replace each input. With this we make 1 temp string only, rather than 1-per-ribbon.
Replace hardcoded "Ribbon" strings to use a shared const string in a central spot.
Closes#2984
ty atrius & matt via discord
Co-Authored-By: Atrius97 <39707481+Atrius97@users.noreply.github.com>
Co-Authored-By: Matt <17801814+sora10pls@users.noreply.github.com>