public PK1 convertToPK1() { PK1 pk1 = new PK1(null, Identifier, Japanese); Array.Copy(Data, 0x1, pk1.Data, 0x7, 0x1A); pk1.Species = Species; // This will take care of Typing :) pk1.Stat_HPCurrent = Stat_HPCurrent; pk1.Stat_Level = Stat_Level; // Status = 0 Array.Copy(otname, 0, pk1.otname, 0, otname.Length); Array.Copy(nick, 0, pk1.nick, 0, nick.Length); int[] newMoves = pk1.Moves; for (int i = 0; i < 4; i++) { if (newMoves[i] > 165) // not present in Gen 1 { newMoves[i] = 0; } } pk1.Moves = newMoves; pk1.FixMoves(); return(pk1); }
public PokemonList1(byte[] d, CapacityType c = CapacityType.Single, bool jp = false) { Japanese = jp; Data = d ?? getEmptyList(c, Japanese); Capacity = getCapacity(c); Entry_Size = getEntrySize(c); if (Data.Length != DataSize) { Array.Resize(ref Data, DataSize); } Pokemon = new PK1[Capacity]; for (int i = 0; i < Capacity; i++) { int base_ofs = 2 + Capacity; byte[] dat = Data.Skip(base_ofs + Entry_Size * i).Take(Entry_Size).ToArray(); Pokemon[i] = new PK1(dat, null, jp) { otname = Data.Skip(base_ofs + Capacity * Entry_Size + StringLength * i).Take(StringLength).ToArray(), nick = Data.Skip(base_ofs + Capacity * Entry_Size + StringLength * Capacity + StringLength * i) .Take(StringLength).ToArray() }; } }
public override PKM Clone() { PK1 new_pk1 = new PK1(Data, Identifier, Japanese); Array.Copy(otname, 0, new_pk1.otname, 0, otname.Length); Array.Copy(nick, 0, new_pk1.nick, 0, nick.Length); return new_pk1; }
private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1) { var Type_A = pk1.Type_A; var Type_B = pk1.Type_B; if (pk1.Species == 137) // Porygon { // Can have any type combination of any species by using Conversion. if (!GBRestrictions.Types_Gen1.Contains(Type_A)) { data.AddLine(GetInvalid(LG1TypePorygonFail1)); } else if (!GBRestrictions.Types_Gen1.Contains(Type_B)) { data.AddLine(GetInvalid(LG1TypePorygonFail2)); } else // Both match a type, ensure a gen1 species has this combo { var TypesAB_Match = PersonalTable.RB.IsValidTypeCombination(Type_A, Type_B); var result = TypesAB_Match ? GetValid(LG1TypeMatchPorygon) : GetInvalid(LG1TypePorygonFail); data.AddLine(result); } } else // Types must match species types { var Type_A_Match = Type_A == PersonalTable.RB[pk1.Species].Type1; var Type_B_Match = Type_B == PersonalTable.RB[pk1.Species].Type2; var first = Type_A_Match ? GetValid(LG1TypeMatch1) : GetInvalid(LG1Type1Fail); var second = Type_B_Match ? GetValid(LG1TypeMatch2) : GetInvalid(LG1Type2Fail); data.AddLine(first); data.AddLine(second); } }
private static bool IsValidCatchRatePK1(EncounterStatic e, PK1 pk1) { var catch_rate = pk1.Catch_Rate; // Pure gen 1, trades can be filter by catch rate if (pk1.Species == (int)Species.Pikachu || pk1.Species == (int)Species.Raichu) { if (catch_rate == 190) // Red Blue Pikachu, is not a static encounter { return(false); } if (catch_rate == 163 && e.Level == 5) // Light Ball (Yellow) starter { return(true); } } if (e.Version == GameVersion.Stadium) { // Amnesia Psyduck has different catch rates depending on language if (e.Species == (int)Species.Psyduck) { return(catch_rate == (pk1.Japanese ? 167 : 168)); } return(GBRestrictions.Stadium_CatchRate.Contains(catch_rate)); } // Encounters can have different Catch Rates (RBG vs Y) var table = e.Version == GameVersion.Y ? PersonalTable.Y : PersonalTable.RB; var rate = table[e.Species].CatchRate; return(catch_rate == rate); }
public override PKM Clone() { var clone = new PK1((byte[])Data.Clone(), Japanese); OT_Trash.CopyTo(clone.OT_Trash); Nickname_Trash.CopyTo(clone.Nickname_Trash); return(clone); }
public override PKM Clone() { PK1 new_pk1 = new PK1(Data, Identifier, Japanese); Array.Copy(otname, 0, new_pk1.otname, 0, otname.Length); Array.Copy(nick, 0, new_pk1.nick, 0, nick.Length); return(new_pk1); }
private void VerifyMiscG1CatchRate(LegalityAnalysis data, PK1 pk1) { var e = data.EncounterMatch; var catch_rate = pk1.Catch_Rate; switch (pk1.TradebackStatus) { case TradebackType.Any: case TradebackType.WasTradeback: if (catch_rate == 0 || Legal.HeldItems_GSC.Contains((ushort)catch_rate)) { data.AddLine(GetValid(V394)); } else if (pk1.TradebackStatus == TradebackType.WasTradeback) { data.AddLine(GetInvalid(V395)); } else { goto case TradebackType.Gen1_NotTradeback; } break; case TradebackType.Gen1_NotTradeback: if ((e as EncounterStatic)?.Version == GameVersion.Stadium || e is EncounterTradeCatchRate) { // Encounters detected by the catch rate, cant be invalid if match this encounters data.AddLine(GetValid(V398)); } else if ((pk1.Species == 149 && catch_rate == PersonalTable.Y[149].CatchRate) || (Legal.Species_NotAvailable_CatchRate.Contains(pk1.Species) && catch_rate == PersonalTable.RB[pk1.Species].CatchRate)) { data.AddLine(GetInvalid(V396)); } else if (!data.Info.EvoChainsAllGens[1].Any(c => RateMatchesEncounter(c.Species))) { data.AddLine(GetInvalid(pk1.Gen1_NotTradeback ? V397 : V399)); } else { data.AddLine(GetValid(V398)); } break; } bool RateMatchesEncounter(int species) { if (catch_rate == PersonalTable.RB[species].CatchRate) { return(true); } if (catch_rate == PersonalTable.Y[species].CatchRate) { return(true); } return(false); } }
private const int SIZE_RESERVED = 0x8000; // unpacked box data protected override byte[] GetFinalData() { var capacity = Japanese ? PokeListType.StoredJP : PokeListType.Stored; for (int i = 0; i < BoxCount; i++) { var boxPL = new PokeList1(capacity, Japanese); int slot = 0; for (int j = 0; j < boxPL.Pokemon.Length; j++) { PK1 boxPK = (PK1)GetPKM(GetData(GetBoxOffset(i) + (j * SIZE_STORED), SIZE_STORED)); if (boxPK.Species > 0) { boxPL[slot++] = boxPK; } } // copy to box location var boxdata = boxPL.Write(); int ofs = GetBoxRawDataOffset(i); SetData(boxdata, ofs); // copy to active loc if current box if (i == CurrentBox) { SetData(boxdata, Offsets.CurrentBox); } } var partyPL = new PokeList1(PokeListType.Party, Japanese); int pSlot = 0; for (int i = 0; i < 6; i++) { PK1 partyPK = (PK1)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) { partyPL[pSlot++] = partyPK; } } partyPL.Write().CopyTo(Data, Offsets.Party); // Daycare is read-only, but in case it ever becomes editable, copy it back in. byte[] rawDC = GetData(GetDaycareSlotOffset(loc: 0, slot: 0), SIZE_STORED); byte[] dc = new byte[1 + (2 * StringLength) + PKX.SIZE_1STORED]; dc[0] = rawDC[0]; Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY + StringLength, dc, 1, StringLength); Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY, dc, 1 + StringLength, StringLength); Array.Copy(rawDC, 2 + 1, dc, 1 + (2 * StringLength), PKX.SIZE_1STORED); dc.CopyTo(Data, Offsets.Daycare); SetChecksums(); byte[] outData = new byte[Data.Length - SIZE_RESERVED]; Array.Copy(Data, outData, outData.Length); return(outData); }
private void VerifyMiscG1CatchRate(LegalityAnalysis data, PK1 pk1) { var e = data.EncounterMatch; var catch_rate = pk1.Catch_Rate; var result = pk1.TradebackStatus == TradebackType.Gen1_NotTradeback ? GetWasNotTradeback() : GetWasTradeback(); data.AddLine(result); CheckResult GetWasTradeback() { if (catch_rate == 0 || Legal.HeldItems_GSC.Contains((ushort)catch_rate)) { return(GetValid(LG1CatchRateMatchTradeback)); } if (pk1.TradebackStatus == TradebackType.WasTradeback) { return(GetInvalid(LG1CatchRateItem)); } return(GetWasNotTradeback()); } CheckResult GetWasNotTradeback() { if ((e is EncounterStatic1 s && s.Version == GameVersion.Stadium) || e is EncounterTrade1) { return(GetValid(LG1CatchRateMatchPrevious)); // Encounters detected by the catch rate, cant be invalid if match this encounters } int species = pk1.Species; if ((species == (int)Species.Dragonite && catch_rate == 9) || (GBRestrictions.Species_NotAvailable_CatchRate.Contains(species) && catch_rate == PersonalTable.RB[species].CatchRate)) { return(GetInvalid(LG1CatchRateEvo)); } if (!data.Info.EvoChainsAllGens[1].Any(c => RateMatchesEncounter(c.Species))) { return(GetInvalid(pk1.Gen1_NotTradeback ? LG1CatchRateChain : LG1CatchRateNone)); } return(GetValid(LG1CatchRateMatchPrevious)); } bool RateMatchesEncounter(int species) { if (catch_rate == PersonalTable.RB[species].CatchRate) { return(true); } if (catch_rate == PersonalTable.Y[species].CatchRate) { return(true); } return(false); } }
private const int SIZE_RESERVED = 0x8000; // unpacked box data protected override byte[] Write(bool DSV) { for (int i = 0; i < BoxCount; i++) { PokemonList1 boxPL = new PokemonList1(Japanese ? PokemonList1.CapacityType.StoredJP : PokemonList1.CapacityType.Stored, Japanese); int slot = 0; for (int j = 0; j < boxPL.Pokemon.Length; j++) { PK1 boxPK = (PK1)GetPKM(GetData(GetBoxOffset(i) + j * SIZE_STORED, SIZE_STORED)); if (boxPK.Species > 0) { boxPL[slot++] = boxPK; } } if (i < BoxCount / 2) { boxPL.GetBytes().CopyTo(Data, 0x4000 + i * SIZE_STOREDBOX); } else { boxPL.GetBytes().CopyTo(Data, 0x6000 + (i - BoxCount / 2) * SIZE_STOREDBOX); } if (i == CurrentBox) { boxPL.GetBytes().CopyTo(Data, Japanese ? 0x302D : 0x30C0); } } PokemonList1 partyPL = new PokemonList1(PokemonList1.CapacityType.Party, Japanese); int pSlot = 0; for (int i = 0; i < 6; i++) { PK1 partyPK = (PK1)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) { partyPL[pSlot++] = partyPK; } } partyPL.GetBytes().CopyTo(Data, Japanese ? 0x2ED5 : 0x2F2C); // Daycare is read-only, but in case it ever becomes editable, copy it back in. byte[] rawDC = GetData(GetDaycareSlotOffset(loc: 0, slot: 0), SIZE_STORED); byte[] dc = new byte[1 + 2 * StringLength + PKX.SIZE_1STORED]; dc[0] = rawDC[0]; Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY + StringLength, dc, 1, StringLength); Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY, dc, 1 + StringLength, StringLength); Array.Copy(rawDC, 2 + 1, dc, 1 + 2 * StringLength, PKX.SIZE_1STORED); dc.CopyTo(Data, Japanese ? 0x2CA7 : 0x2CF4); SetChecksums(); byte[] outData = new byte[Data.Length - SIZE_RESERVED]; Array.Copy(Data, outData, outData.Length); return(outData); }
protected override PKM GetPKM(byte[] data) { const int len = StringLength; var nick = data.AsSpan(0x21, len); var ot = data.AsSpan(0x21 + len, len); data = data.Slice(0, 0x21); var pk1 = new PK1(data, true); nick.CopyTo(pk1.RawNickname); ot.CopyTo(pk1.RawOT); return(pk1); }
protected override PKM GetPKM(byte[] data) { int len = StringLength; var nick = data.AsSpan(PokeCrypto.SIZE_1STORED, len); var ot = data.AsSpan(PokeCrypto.SIZE_1STORED + len, len); data = data.Slice(0, PokeCrypto.SIZE_1STORED); var pk1 = new PK1(data, Japanese); nick.CopyTo(pk1.RawNickname); ot.CopyTo(pk1.RawOT); return(pk1); }
public override SlotGroup GetTeam(int team) { if ((uint)team >= TeamCount) { throw new ArgumentOutOfRangeException(nameof(team)); } var name = GetTeamName(team); var members = new PK1[6]; var ofs = GetTeamOffset(team); for (int i = 0; i < 6; i++) { var rel = ofs + ListHeaderSize + (i * SIZE_STORED); members[i] = (PK1)GetStoredSlot(Data, rel); } return(new SlotGroup(name, members)); }
private void VerifyMiscG1CatchRate(LegalityAnalysis data, PK1 pk1) { var EncounterMatch = data.EncounterMatch; var catch_rate = pk1.Catch_Rate; switch (pk1.TradebackStatus) { case TradebackType.Any: case TradebackType.WasTradeback: if (catch_rate == 0 || Legal.HeldItems_GSC.Any(h => h == catch_rate)) { data.AddLine(GetValid(V394)); } else if (pk1.TradebackStatus == TradebackType.WasTradeback) { data.AddLine(GetInvalid(V395)); } else { goto case TradebackType.Gen1_NotTradeback; } break; case TradebackType.Gen1_NotTradeback: if ((EncounterMatch as EncounterStatic)?.Version == GameVersion.Stadium || EncounterMatch is EncounterTradeCatchRate) { // Encounters detected by the catch rate, cant be invalid if match this encounters data.AddLine(GetValid(V398)); } else if (pk1.Species == 149 && catch_rate == PersonalTable.Y[149].CatchRate || Legal.Species_NotAvailable_CatchRate.Contains(pk1.Species) && catch_rate == PersonalTable.RB[pk1.Species].CatchRate) { data.AddLine(GetInvalid(V396)); } else if (!data.Info.EvoChainsAllGens[1].Any(e => catch_rate == PersonalTable.RB[e.Species].CatchRate || catch_rate == PersonalTable.Y[e.Species].CatchRate)) { data.AddLine(GetInvalid(pk1.Gen1_NotTradeback ? V397 : V399)); } else { data.AddLine(GetValid(V398)); } break; } }
private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1) { var Type_A = pk1.Type_A; var Type_B = pk1.Type_B; if (pk1.Species == 137) { // Porygon can have any type combination of any generation 1 species because of the move Conversion, // that change Porygon type to match the oponent types var Type_A_Match = Legal.Types_Gen1.Any(t => t == Type_A); var Type_B_Match = Legal.Types_Gen1.Any(t => t == Type_B); if (!Type_A_Match) { data.AddLine(GetInvalid(V386)); } if (!Type_B_Match) { data.AddLine(GetInvalid(V387)); } if (Type_A_Match && Type_B_Match) { var TypesAB_Match = PersonalTable.RB.IsValidTypeCombination(Type_A, Type_B); if (TypesAB_Match) { data.AddLine(GetValid(V391)); } else { data.AddLine(GetInvalid(V388)); } } } else // Types must match species types { var Type_A_Match = Type_A == PersonalTable.RB[pk1.Species].Type1; var Type_B_Match = Type_B == PersonalTable.RB[pk1.Species].Type2; var first = Type_A_Match ? GetValid(V392) : GetInvalid(V389); var second = Type_B_Match ? GetValid(V393) : GetInvalid(V390); data.AddLine(first); data.AddLine(second); } }
private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1) { var Type_A = pk1.Type_A; var Type_B = pk1.Type_B; var species = pk1.Species; if (species == (int)Species.Porygon) { // Can have any type combination of any species by using Conversion. if (!GBRestrictions.TypeIDExists(Type_A)) { data.AddLine(GetInvalid(LG1TypePorygonFail1)); } if (!GBRestrictions.TypeIDExists(Type_B)) { data.AddLine(GetInvalid(LG1TypePorygonFail2)); } else // Both types exist, ensure a Gen1 species has this combination { var TypesAB_Match = PersonalTable.RB.IsValidTypeCombination(Type_A, Type_B); var result = TypesAB_Match ? GetValid(LG1TypeMatchPorygon) : GetInvalid(LG1TypePorygonFail); data.AddLine(result); } } else // Types must match species types { var pi = PersonalTable.RB[species]; var Type_A_Match = Type_A == pi.Type1; var Type_B_Match = Type_B == pi.Type2; var first = Type_A_Match ? GetValid(LG1TypeMatch1) : GetInvalid(LG1Type1Fail); var second = Type_B_Match || (ParseSettings.AllowGBCartEra && ((species == (int)Species.Magnemite || species == (int)Species.Magneton) && Type_B == 9)) // Steel Magnemite via Stadium2 ? GetValid(LG1TypeMatch2) : GetInvalid(LG1Type2Fail); data.AddLine(first); data.AddLine(second); } }
public PK1 convertToPK1() { PK1 pk1 = new PK1(null, Identifier, Japanese); Array.Copy(Data, 0x1, pk1.Data, 0x7, 0x1A); pk1.Species = Species; // This will take care of Typing :) pk1.Stat_HPCurrent = Stat_HPCurrent; pk1.Stat_Level = Stat_Level; // Status = 0 Array.Copy(otname, 0, pk1.otname, 0, otname.Length); Array.Copy(nick, 0, pk1.nick, 0, nick.Length); int[] newMoves = pk1.Moves; for (int i = 0; i < 4; i++) if (newMoves[i] > 165) // not present in Gen 1 newMoves[i] = 0; pk1.Moves = newMoves; pk1.FixMoves(); return pk1; }
public PokemonList1(PK1 pk) : this(CapacityType.Single, pk.Japanese) { this[0] = pk; Count = 1; }
public PokemonList1(byte[] d, CapacityType c = CapacityType.Single, bool jp = false) { Japanese = jp; Data = d ?? getEmptyList(c, Japanese); Capacity = getCapacity(c); Entry_Size = getEntrySize(c); if (Data.Length != DataSize) { Array.Resize(ref Data, DataSize); } Pokemon = new PK1[Capacity]; for (int i = 0; i < Capacity; i++) { int base_ofs = 2 + Capacity; byte[] dat = Data.Skip(base_ofs + Entry_Size * i).Take(Entry_Size).ToArray(); Pokemon[i] = new PK1(dat, null, jp) { otname = Data.Skip(base_ofs + Capacity*Entry_Size + StringLength*i).Take(StringLength).ToArray(), nick = Data.Skip(base_ofs + Capacity*Entry_Size + StringLength*Capacity + StringLength*i) .Take(StringLength).ToArray() }; } }
public PokemonList1(PK1 pk) : this(CapacityType.Single, pk.Japanese) { this[0] = pk; Count = 1; }