just read the comments & code, this one is an annoying oversight
untraded pkm /should/ never have HT memory data, but sometimes it do be
like that
Closes#2571
Move EncounterOriginal to Legal info; needed in order to pass the
correct encounter to the EvoChain fetch.
The EncounterOriginal 'hack' might be unnecessary with the current state
of the legality checker... maybe can see if it can be removed later.
If the feeling is zero the game's string formatter will treat it as
null, and will newline before the period.
Gen6 (if I recall correctly) had "it was happy" as index 0
Gen8 (new) has "it was happy" as index 1, with 0 being invalid-bad.
Slice the array differently for gen8 to include the empty line as index
0.
Closes#2549 , ty @crzyc && @architdate for testing index 0 :)
.PID=$shiny0 will do squares
anything else will do stars
.RelearnMoves=$suggestAll will give ALL TR moves, not just the ones for
its current movepool.
.Ribbons=$suggest will give all valid ribbons
.Ribbons=$suggestNone will remove all ribbons (except required ones like
event ribbons)
Closes#2568
320 is max hp (31IV 252EV), is this just -60 from max HP (threshold to
evolve at?)
might need some more research to see what is going on with this
only trycatch in release builds; was confused until I stepped thru and
saw the crash
Rewrite a bunch of the history verification stuff
Fix a few test cases with incorrect OT Friendship (transferred), and
missing GeoCountry
Need to rewrite memory verification next
(All test cases currently pass)
#2545
GetDestinationForm for gen7+ is fine
gen7 and gen8 use the "form" argument as the destination form; -1 means
don't change
espurr-F just gets forced to 1 in gen7 since it's -1
Closes#2564 ty @iiippppk
only used for Zukan7b, but add in handling so that it works for <=gen6
games, and supports form alterations too!
update style to match GetPreEvolutions
could probably update this to yield tuples (species, form) but LGPE/SWSH
only needs species. If there's the need for tuples later, should be ez
tweak.
espurr-F evolves to form-1 from form0, even tho the form arg is -1 (gen7
consideration)
gen8 has 0/1 for the two evolutions, dictating the destination form
DexLevel was the initial abstraction, which was expanded/reused for
evolution details
I should probably merge the two classes since everything is passed as
EvoCriteria
The encounter generators do some silly form fuzzy match which can now be
more accurately checked since I've moved Form to DexLevel... maybe a
future commit can clean that up.
encounterarea2 was reusing this class, just use a throwaway readonly
struct as our temp value storage
- Use tail recursion and a lookup table (species | form) for reversing
- generate the reversal lookup by extrapolating all species-form
destination values (EvolutionLink)
All tests pass, and no special handling for forms is required. Kinda
suspicious that it works this simply...
Redo evolution banning (no wormhole for non-Alolan evolutions in SM), in
a style that we can ban the Gigantamax event evolutions
(pika/meowth/eevee). Their evolutions can't be resulted from a pre-evo,
because the in-game routine early aborts if the gigantamax flag is set
for those species.
Update gen4 personal tables (formCount was 0, needs to be a minimum of 1
by default)
Closes#2537
* update forme to showdown strings
Galarian is represented as Galar on PS!
Polteageist has no form atall
galarian now called Galar by default to match with Alola as a forme. changed darmanitan forme-strings in form converter. Added sinistea to the forme ignore list when converting to showdown
format >= 6 is always true (early return in entry)
don't double-flag/check memory presence in OTs from gen5 and below (hist
and OT verifier)
rename method; I'll probably rework the flow of things for gen6
verification and gen8 verification since the rules are slightly
different
Certain Mark values (ribbon) are only obtainable if the encounter was
obtained in some weather (I really hope there's no crossover cases for
this), and non-symbol encounters can't wander to another zone.
I wonder if you can wander from one zone with one exclusive weather, to
another zone, and get an 'unobtainable' mark (with the new zone's
weather) on the crossover mon's weather. yikes lmao
yeah your initial hacks were hacks
It appears there's a bug (in the game) for link trade memories --
applied to the OT memory instead of HT memory?? Fun!
Closes#2525
G4Celebi & G6Link met location match; Pokémon Link was only available
for Gen6 so just check for that origin.
Ty @Ammako
tbh I shouldn't even have this property ha
Private report with 3 specimens, 2 undocumented met locations
The other was a Gigantamax which matched another static encounter,
resulting in a partial match being accepted (the real match came after,
but was never iterated to).
Rather than adding deferrals for Enc8, do nest stuff first since it's
the most restrictive
In the past we didn't really have duplicate static encounters with
slightly different permissions.
Thanks @ReignOfComputer & {reporting user}!
linq dump code I used for ez vis:
var sav = new SAV8SWSH(File.ReadAllBytes(@"D:\Kurt\Downloads\main
(7)"));
var blocks = sav.Blocks;
var raid = blocks.Raid;
raid.GetAllRaids().Dump();
#2484
OH BOY REUSED INDEXES
smart to save space, but a small pain for legality
feels pretty bad breaking up abstractions for every minor difference in
verification...
* Static Locations Update
- Removed version lock on Motostoke Stadium Vulpix (may want to investigate Growlithe)
- Wild Area Updates
- Other Static Updates
* Squeeze in 2 more Statics
* Rhydon Static Location
Last one I promise.
Closes#2461 by implementing slightly differently
Dictionary instead of new[] every area
Checks original met location first before attempting the dictionary
lookup (missing in pull request)
Easy path forward if LGPE crossover is needed
Potential issues: Since encounter types aren't marked, shaking trees and
fishing encounters are allowed to cross over. Maybe need to have some
marking for encounter slots or something...
Now recognizes & reverses form-changing evolution chains like Sirfetch'd
basically the whole process is to build the tree but point in the
opposite direction (for de-evolution paths)
Was referencing wild caught mons that are given a single egg move; this
logic handles shared egg moves too via daycare.
Probably need to rework SplitBreed into a dictionary; this might not
catch Mime/etc split breeds if they have different tables.
Nothing for the PKM Editor; not sure how I want to handle the reused
FormDuration work value.
For the meantime, just use the Batch Editor for a targeted write.
Closes#2441
Gen3 item paste -> Gen3 item import => take item ID as is
once parsing moves starts, break if any following lines are not move
lines
Closes#2412 , thanks @The-Fireplace !
- Gender specific forms now set the correct flags
- Regular click on Check All doesn't set shiny flags
- Shift click on Check All sets shiny flags too.
Closes#2425 thanks @igniscitrinus !
Introducing Sword/Shield support!
Legality is still a work in progress, and documentation of encounters
and game features with respect to save data is ready for community
effort!
-Kurt
Zukan5/6 was pushing 0 for the formBit, which was an incorrect value. I
probably should have abstracted things since gen5/6 don't behave the
same as gen7
rewrite the SetDisplayedFlag for more clarity, and to early-return
without checking displayed state if the flag is being cleared.
Two birds with one stone:
- sav4 doesn't use Data (instead uses General/Storage), so we need to
use the abstracted method calls instead of trying to do things manually.
- setting a blank pkm at a party slot will decrease the party count!
don't decrease things twice.
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
With the approaching games, PKM sprites are a different size from the 3DS era (as already hinted by LGPE, which has 56x68). It'll be a little easier to manage with this portion of the library walled off from the rest of the codebase.
Eventually the net46 target will use fody or something to merge in these extra dependency dll's automatically to not disturb the usual exe/dll experience.
New in c# 8
Assert.True(check for null) doesn't give a hint that the obj isnt null
afterwards.
Assert.NotNull does have the compiler hint attribute
could probably use fluentexpression syntax, but resharper doesn't pick
up on the nonnullable hint like vs does.
GeneratorTests: swap FirstOrDefault to First, can keep the fluent style
and resharper gets the hint.
tl;dr : resharper doesn't look at external lib for hints, gotta use
Assert.NotNull or something that doesn't return null
I think I left these in so AutoLegality could function, but we already
have a couple breaking changes / build pause notice, so lets keep
cleaning our API 👍
Futureproof with transfer considerations
This is just a guess; gen7 didn't update the medal count and if we
assume pk8 overhauls the structure for a new console, they'll drop old
data.
With c#8 later next week, will move SuperTrainingMedalCount() to a
default interface method ez.
See previous commit for discussion; it's easier to read and maintain
this rather than have the precomputed min/max comparisons.
LevelMin - minDecrease <= min && max <= LevelMax + maxIncrease;
See EncounterArea7b:
Since we know min and minDecrease (0) before doing the linq filter we
can precompute the lowbound, same for highbound; but this isn't
immediately obvious to the reader. The perf cost is pretty much
negligible in the big picture, so leave it in the more readable state.
Thanks @fattard & @ammako !
#2389
The inputs to "IsLevelWithinRange" are the highest value the
lowest-level can be, and the lowest value the highest level can be...
seems confusing (hence the original error).
If a slot is 6-7, with a wild encounter (flute), we can go +/-3 from
6-7, which is 3-10.
With an encounter of level 5, the inputs are: 5+3, and 5-3 (8, 2).
Since 8>lvlmin and 2<lvlhi, we can get a level 5 pkm from the slot
(using a negative flute yielding a -1 adjustment).
I could probably refactor it to be a 3-input signature (lvl, lvlneg,
lvlpos), and have it do LevelMin - lvlneg <= lvl && lvl <= LevelMax +
lvlpos
I should probably refactor these methods to do minLevel & maxLevel (so
baseSpecies.Level to CurrentLevel for pkm that lost their original met
data) but nothing needs the extra logic at this time.
Were using default filter behavior, which needs to be tweaked to account
for the original met location/level not being present (ie skip the
minLevel bounds check).
Hardcode logic for HasOriginalMetLocation for simplicity
Closes#2389 , thanks @Ammako !
Extract Species Name logic to SpeciesName
Extract Language logic to Language
Remove FormConverter wrapper for string[] fetch
Rearrange some logic to more appropriate locations, update access
modifiers / types
Move some pkm array methods to arrayutil, make generic
PKX.GetVCLanguage was a dupe of _K12.GuessedLanguage() so just expose
the method
PKX is now back to pkm data manip only
Now logic is reasonably split, and each format of area has its own way
of yielding slots
Too much junk with checking flute boosts or catch combo applicability;
just let the area dictate how slots match.
dual bounds check -> single check via uint cast
pkx: keep array reference for reuse in next check
format return to second line to stick out more; lines of code are cheap
:)
Generating encounters from an EncounterArea is getting a little stupid
without inheritance; each type can now have its own specific behavior
without checking for each individual type of generation pattern. Will
add the abstract method implementations in a future commit
Move some string[] array fetch (for all languages) to Util
split some methods with optional parameters=null
add more xmldoc
replace some magic numbers -> enum/const references
consolidate common array operations (span soon maybe?)
Increase abstraction for arbitrary slot get/set operations, and fracture
SAV4 behavior for each game type.
Adds: Undo/Redo of party slot changes
Fixes: Fixed Gen5 daycare slot 2 reading, and EXP reading
Fixes: Some slot color glitchiness
Fixed: Box layout editor now hides the flag label if no flags are
present
Fixed: Gen7 box flags are now shown (unknown purpose lol)
Changed: savefile objects are generally smaller (removed a few shared
offset fields)
Closes#2381
Keep Raichu and Marowak at the end for ez referencing. Keep a separate
refence for alolan kanto stuff for futureproofing
Might want to improve the EncounterArea abstraction to do the
slot-finding labor themselves, but whatever, hardcode stuff until swsh
throws new monkey wrenches in. A good idea would be a dictionary with
level forcings [species | form << 10] = X and use the dictionary to
check on slot creation
A little bit cleaner when the logic is separated
Keep an abstraction of BoxEdit to cache the current box contents.
Already fetched to show sprites; any future fetches (for preview text /
hover sprite) can reuse the already fetched pkm data.
Should probably rewrite this stuff completely, but effort better spent
elsewhere
* corrections and styling
* FR/LG: some more story/item related variables
* FR/LG: More HMs and Oak's Aide's items
* FR/LG: League beaten flag fairly confirmed
* FR/LG: variables
* FR/LG/E: Altering Cave variable
* FR/LG: Pokemon Tower related variables
* FR/LG: Pokedex/Oak/Rival (part 1) related variables
* FR/LG: more story related variables
* FR/LG: Event flags for eventually reaching event-only places
(required to enable processing of the appropriate items; officially set by DLC scripts)
* FR/LG: Badge names and Running Shoes
Choosing G/S will initialize as GS
Choosing C will initialize as C
calling via their own code (GSC/GS) will choose the most recent (crystal
if possible).
Closes#2359
Remove some unnecessary properties from SaveFile
Enumerate checksum flag results for GC memcard checking
Remove unnecessary checks on savefile type
Add some documentation
Decapitalize some method parameters
move some pk3->pk4 stuff into object constructor
annotate pk3->pk4 string buffer (trash) quirks
split Heal into Party/PP method uses. Setting suggested stats no longer
refreshes PP
apply current level to Stat Level (wasn't being set previously)
event move only
still haven't bothered finding the table in the exefs that results in
the pkm with an oob move being dummied. hardcoded based on data for now
:)
Was initially implemented as fishy during SM's initial implementation. Any nonzero value in this byte is invalid, don't even bother checking unused/count.
Now that Gen6 (and Gen7) are no longer current gen, any hope for them being released is the same as hoping for Gen4's Azure Flute Arceus. Thus we mark as invalid :)
Closes#2353 by effect of no longer flagging as Fishy. I think that my initial implementation of VC stuff had assumed the Generation==7, but later used 1/2 for factual correctness.
c345688f6d
base(x) -> base(x - y) resulted in incorrect offsets for LGPE. Great.
Just make PokeDexLanguageFlags a shift offset instead of absolute;
update all usages.
Closes#2348
Feels pretty brittle with all the optional parameters; if things get
funky for SW/SH it may warrant a rewrite of this portion
Closes#2345 ty @iiippppk !
Closes#2343 ty @WEERSOQUEER !
#2338 was referenced by
4d08e21126
, that commit was incorrect. Looks like these 2 have OT Gender female.
Instead of marking every trade MALE except for these two, just update
the handling (i'll probably regret this lol)
LGPE will missingno your pokemon if it's not a Kanto/M&M, or one of its
moves is not obtainable. For the user's benefit, filter down these
sources to the non-baddata list.
Item filtering and ball filtering might be something to think about for
the future, but not much benefit vs effort.
Check the OT length for the deferral
other encounters are more permissive than trades, hence why we defer
unless we know for certain. Same OTs are possible, except for the
too-long ones!
Closes#2338 , thanks @WEERSOQUEER !
Needs to be checked prior to the strict Array Index search, as we can't
have an exact string match.
can probably be revised to a StartsWith to only check for the specific
language match, but that's a little less obvious & extra work :)
#2338
remove unnecessary %25 check (only applicable for gen4 encounters),
unneeded for gen5 method.
add a test case to generate a haxorus for all natures, verify shininess
Closes#2336
LangFlags is expected to be less than 0x500 or whatever, zero indexed to
the start of the dex block; NOT an absolute position.
I don't feel like making every usage consistent (gen5, gui editors)
which use the absolute position, so just adjust in the zukan
constructors
GameInfo has been the storage for the current Game Language environment
When using GameInfo, only one environment is tracked at a time, which is
initialized by the PKM editor (items, moves). Rework things to allow
multiple filtered sources to exist, and keep the filtering logic in
PKHeX.Core for reuse in other programs... ;)
Pass them as Legal for wild encounters similar to M1/M2/M4.
Add test cases & test pkm validation
Add pid generator support
I decided against checking these PIDIVs after all others; inlined
methods.
Closes#2328 , thanks @pokecal !
create custom comparer to do the work
reorder some parameters
simplify gb hm set (All and FindIndex is duplicate work)
only usages of linq remaining are for the bulk action Where filtering
(ok)
Shared base classes throw a new snag, where the property may be Declared
in the shared class.
eg:
PKM -> _K12 -> PK2
just filter all public ones that have a setter; works well enough idk
not enough documentation to know what every single flag does; just be
lenient
I assume that flags being present XK3->PK3 will set fateful, so we could
remove that logic...
Exposing bitflags for editing isn't fun for the editor, so just ignore
it behind the fateful bool get/set.
fateful required for all xk3 origin
#2289
transfer level exp and current exp not being different enough, which
limits the amount of natures possible. Could handle the 100&<=2 cases
the same way, but keep the branches for faster cases.
fix bad test cases
Not version specific; I'm assuming the 00020003 PID is a result of
hacking the save file to change OT gender. Legitimate saves haven't
yielded the Hardy PID. Changing gender probably results in a bad
pointer, fetching the wrong value.
Closes#2290
Remove usage of linq for sorting, use array.sort for in-place sorting.
Wasteful creating temp sorted buffers then enumerating them to dump into
the list.
existing logic had been overwriting the inner error messages with the
generic fail message
Remove backwards conversion precondition check; the ConvertPKM method
has no branches that allow conversion so it'll naturally fail -- end
result is the same with less upfront logic.
Fresh day, fresh tests of the new code :)
Fix assert conditions
Add extra considerations
Detected clones should be skipped for PID/EC/TID checks -- should
probably detect this a different way rather than checking a computed
string (bool array of flags for the clone check results)
FileInfo inherits from FileSystemInfo, which initializes a bunch of
strings that we don't need
this isn't a great optimization, just a fun exercise finding a quicker
approach to get these values