public static Sprite GetMinisprite(PBESpecies species, PBEForm form, PBEGender gender, bool shiny) { string speciesStr = PBEDataUtils.GetNameOfForm(species, form) ?? species.ToString(); string genderStr = gender == PBEGender.Female && HasFemaleSprite(species, true) ? "_F" : string.Empty; return(Sprite.LoadOrGet("Pkmn.PKMN_" + speciesStr + (shiny ? "_S" : string.Empty) + genderStr + ".png")); }
// TODO: Include generation? // TODO: Sketch // TODO: Same goals as MoveLegalityCheck public static PBEMove[] GetLegalMoves(PBESpecies species, byte level, PBESettings settings) { PBEPokemonShell.ValidateSpecies(species); PBEPokemonShell.ValidateLevel(level, settings); var evolutionChain = new List <PBESpecies>(); void AddPreEvolutions(PBESpecies sp) { foreach (PBESpecies pkmn in PBEPokemonData.GetData(sp).PreEvolutions) { AddPreEvolutions(pkmn); } evolutionChain.Add(sp); } AddPreEvolutions(species); var moves = new List <PBEMove>(); foreach (PBESpecies pkmn in evolutionChain) { var pData = PBEPokemonData.GetData(pkmn); moves.AddRange(pData.LevelUpMoves.Where(t => t.Level <= level).Select(t => t.Move)); moves.AddRange(pData.OtherMoves.Select(t => t.Move)); if (PBEEventPokemon.Events.TryGetValue(pkmn, out ReadOnlyCollection <PBEEventPokemon> events)) { moves.AddRange(events.SelectMany(e => e.Moves)); } } return(moves.Distinct().Where(m => m != PBEMove.None).ToArray()); }
public static IReadOnlyCollection <PBEMove> GetLegalMoves(PBESpecies species, PBEForm form, byte level) { List <(PBESpecies, PBEForm)> speciesToStealFrom = GetSpecies(species, form); var moves = new List <PBEMove>(); foreach ((PBESpecies spe, PBEForm fo) in speciesToStealFrom) { IPBEDDPokemonDataExtended pData = PBEDefaultDataProvider.Instance.GetPokemonDataExtended(spe, fo); // Disallow moves learned after the current level moves.AddRange(pData.LevelUpMoves.Where(t => t.Level <= level).Select(t => t.Move)); // Disallow form-specific moves from other forms (Rotom) moves.AddRange(pData.OtherMoves.Where(t => (spe == species && fo == form) || t.ObtainMethod != PBEDDMoveObtainMethod.Form).Select(t => t.Move)); // Event Pokémon checking is extremely basic and wrong, but the goal is not to be super restricting or accurate if (PBEDDEventPokemon.Events.TryGetValue(spe, out ReadOnlyCollection <PBEDDEventPokemon>?events)) { // Disallow moves learned after the current level moves.AddRange(events.Where(e => e.Level <= level).SelectMany(e => e.Moves).Where(m => m != PBEMove.None)); } if (moves.FindIndex(m => PBEDataProvider.Instance.GetMoveData(m, cache: false).Effect == PBEMoveEffect.Sketch) != -1) { return(PBEDataUtils.SketchLegalMoves); } } return(moves.Distinct().Where(m => PBEDataUtils.IsMoveUsable(m)).ToArray()); }
public static PBEGender NextGender(this Random rand, PBESpecies species) { PBEPokemonData pData = PBEPokemonData.Data[species]; switch (pData.GenderRatio) { case PBEGenderRatio.M7_F1: return(rand.ApplyChance(875, 1000) ? PBEGender.Male : PBEGender.Female); case PBEGenderRatio.M3_F1: return(rand.ApplyChance(750, 1000) ? PBEGender.Male : PBEGender.Female); case PBEGenderRatio.M1_F1: return(rand.ApplyChance(500, 1000) ? PBEGender.Male : PBEGender.Female); case PBEGenderRatio.M1_F3: return(rand.ApplyChance(250, 1000) ? PBEGender.Male : PBEGender.Female); case PBEGenderRatio.M1_F7: return(rand.ApplyChance(125, 1000) ? PBEGender.Male : PBEGender.Female); case PBEGenderRatio.M0_F1: return(PBEGender.Female); case PBEGenderRatio.M0_F0: return(PBEGender.Genderless); case PBEGenderRatio.M1_F0: return(PBEGender.Male); default: throw new ArgumentOutOfRangeException(nameof(pData.GenderRatio)); } }
public static bool CanChangeForm(PBESpecies species, bool requireUsableOutsideOfBattle) { if (species <= 0 || species >= PBESpecies.MAX) { throw new ArgumentOutOfRangeException(nameof(species)); } switch (species) { case PBESpecies.Arceus: case PBESpecies.Burmy: case PBESpecies.Deerling: case PBESpecies.Deoxys: case PBESpecies.Genesect: case PBESpecies.Giratina: case PBESpecies.Keldeo: case PBESpecies.Kyurem: case PBESpecies.Landorus: case PBESpecies.Rotom: case PBESpecies.Sawsbuck: case PBESpecies.Shaymin: case PBESpecies.Thundurus: case PBESpecies.Tornadus: return(true); case PBESpecies.Castform: case PBESpecies.Cherrim: case PBESpecies.Darmanitan: case PBESpecies.Meloetta: return(!requireUsableOutsideOfBattle); default: return(false); } }
private void BufferSpeciesNameCommand() { byte buffer = (byte)ReadVarOrValue(); PBESpecies species = ReadVarOrEnum <PBESpecies>(); Game.Instance.StringBuffers.Buffers[buffer] = PBEDataProvider.Instance.GetSpeciesName(species).English; }
public Evo(JToken j) { Method = j[nameof(Method)].ReadEnumValue <EvoMethod>(); switch (Method) { case EvoMethod.Friendship_LevelUp: case EvoMethod.Friendship_Day_LevelUp: case EvoMethod.Friendship_Night_LevelUp: { Param = j["FriendshipRequired"].Value <ushort>(); break; } case EvoMethod.LevelUp: case EvoMethod.ATK_GT_DEF_LevelUp: case EvoMethod.ATK_EE_DEF_LevelUp: case EvoMethod.ATK_LT_DEF_LevelUp: case EvoMethod.Silcoon_LevelUp: case EvoMethod.Cascoon_LevelUp: case EvoMethod.Ninjask_LevelUp: case EvoMethod.Shedinja_LevelUp: case EvoMethod.Male_LevelUp: case EvoMethod.Female_LevelUp: { Param = j["LevelRequired"].Value <ushort>(); break; } case EvoMethod.Beauty_LevelUp: { Param = j["BeautyRequired"].Value <ushort>(); break; } case EvoMethod.Item_Trade: case EvoMethod.Stone: case EvoMethod.Male_Stone: case EvoMethod.Female_Stone: case EvoMethod.Item_Day_LevelUp: case EvoMethod.Item_Night_LevelUp: { Param = (ushort)j["ItemRequired"].ReadEnumValue <PBEItem>(); break; } case EvoMethod.Move_LevelUp: { Param = (ushort)j["MoveRequired"].ReadEnumValue <PBEMove>(); break; } case EvoMethod.PartySpecies_LevelUp: { Param = (ushort)j["SpeciesRequired"].ReadEnumValue <PBESpecies>(); break; } } Species = j[nameof(Species)].ReadEnumValue <PBESpecies>(); Form = j[nameof(Form)].FormValue(); }
private static bool HasFemaleSprite(PBESpecies species) { lock (_femaleSpriteLookupLockObj) { return(_femaleSpriteLookup.Contains(species)); } }
private static List <(PBESpecies, PBEForm)> GetSpecies(PBESpecies species, PBEForm form) { // Recursion BAYBEE // IDK what to name these functions so enjoy Add1 and Add2 var list = new List <(PBESpecies, PBEForm)>(); void Add1(PBESpecies s, PBEForm f) { // Do not take forms if unable to change into them (Wormadam) if (PBEDataUtils.CanChangeForm(s, true)) { foreach (PBEForm cf in PBEDataUtils.GetForms(s, true)) { Add2(s, cf); } } else { Add2(s, f); } } void Add2(PBESpecies s, PBEForm f) { foreach ((PBESpecies cs, PBEForm cf) in PBEDataProvider.Instance.GetPokemonData(s, f).PreEvolutions) { Add1(cs, cf); } list.Add((s, f)); } Add1(species, form); return(list); }
private static bool HasFemaleSprite(PBESpecies species, bool minisprite) { lock (_femaleSpriteLookupLockObj) { return((minisprite ? _femaleMinispriteLookup : _femaleSpriteLookup).Contains(species)); } }
private void PlayCryCommand() { PBESpecies species = ReadVarOrEnum <PBESpecies>(); PBEForm form = ReadVarOrEnum <PBEForm>(); SoundControl.PlayCry(species, form, onStopped: OnCryFinished); }
// TODO: Include generation? // TODO: Sketch // TODO: Same goals as MoveLegalityCheck public static IEnumerable <PBEMove> GetLegalMoves(PBESpecies species, byte level) { var evolutionChain = new List <PBESpecies>(); void AddPreEvolutions(PBESpecies sp) { foreach (PBESpecies pkmn in PBEPokemonData.GetData(sp).PreEvolutions) { AddPreEvolutions(pkmn); } evolutionChain.Add(sp); } AddPreEvolutions(species); var moves = new List <PBEMove>(); foreach (PBESpecies pkmn in evolutionChain) { var pData = PBEPokemonData.GetData(pkmn); moves.AddRange(pData.LevelUpMoves.Where(t => t.Level <= level).Select(t => t.Move).Union(pData.OtherMoves.Select(t => t.Move))); if (PBEEventPokemon.Events.TryGetValue(pkmn, out ReadOnlyCollection <PBEEventPokemon> events)) { moves.AddRange(events.SelectMany(e => e.Moves)); } } return(moves.Except(new[] { PBEMove.None })); }
public static Bitmap GetMinispriteBitmap(PBESpecies species, PBEForm form, PBEGender gender, bool shiny) { string speciesStr = PBEDataUtils.GetNameOfForm(species, form) ?? species.ToString(); string genderStr = gender == PBEGender.Female && HasFemaleSprite(species, true) ? "_F" : string.Empty; return(new Bitmap(GetResourceStream("PKMN.PKMN_" + speciesStr + (shiny ? "_S" : string.Empty) + genderStr + ".png"))); }
public static void ValidateSpecies(PBESpecies species, PBEForm form, bool requireUsableOutsideOfBattle) { if (!IsValidForm(species, form, requireUsableOutsideOfBattle)) { throw new ArgumentOutOfRangeException(nameof(form)); } }
private void Insert(PBESpecies species, byte level, bool fireEvent, int index) { InsertWithEvents(fireEvent, new PBEPokemonShell(species, level, Settings) { CanDispose = false }, index); }
public static PBELocalizedString GetSpeciesName(PBESpecies species) { if (species <= 0 || species >= PBESpecies.MAX) { throw new ArgumentOutOfRangeException(nameof(species)); } return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "SpeciesNames", (ushort)species))[0])); }
public Encounter(EndianBinaryReader r) { Chance = r.ReadByte(); MinLevel = r.ReadByte(); MaxLevel = r.ReadByte(); Species = r.ReadEnum <PBESpecies>(); Form = r.ReadEnum <PBEForm>(); }
private static PBEGender[] GetGenderKeys(PBESpecies species) { if (PokemonImageUtils.HasFemaleVersion(species, false)) { return(new[] { PBEGender.Male, PBEGender.Female }); } return(new[] { PBEGender.MAX }); }
private void GivePokemonCommand() { PBESpecies species = ReadVarOrEnum <PBESpecies>(); byte level = (byte)ReadVarOrValue(); var pkmn = PartyPokemon.CreatePlayerOwnedMon(species, 0, level); Game.Instance.Save.GivePokemon(pkmn); }
private void WildBattleCommand() { PBESpecies species = ReadVarOrEnum <PBESpecies>(); PBEForm form = ReadVarOrEnum <PBEForm>(); byte level = (byte)ReadVarOrValue(); Encounter.CreateStaticWildBattle(species, form, level); }
private void GivePokemonCommand() { PBESpecies species = _reader.ReadEnum <PBESpecies>(); byte level = _reader.ReadByte(); var pkmn = PartyPokemon.GetTestPokemon(species, 0, level); Game.Instance.Save.GivePokemon(pkmn); }
public static (PBESpecies, PBEForm) RandomSpecies(this IReadOnlyList <PBESpecies> eligible, bool requireUsableOutsideOfBattle) { PBESpecies species = eligible.RandomElement(); IReadOnlyList <PBEForm> forms = PBEDataUtils.GetForms(species, requireUsableOutsideOfBattle); PBEForm form = forms.Count > 0 ? forms.RandomElement() : 0; return(species, form); }
public Encounter(JToken j) { Chance = j[nameof(Chance)].Value <byte>(); MinLevel = j[nameof(MinLevel)].Value <byte>(); MaxLevel = j[nameof(MaxLevel)].Value <byte>(); Species = j[nameof(Species)].EnumValue <PBESpecies>(); Form = (PBEForm)j[nameof(Form)].Value <byte>(); // Do not use "EnumValue" because strings are bad for forms }
public Encounter() { Chance = 1; MinLevel = 1; MaxLevel = 1; Species = PBESpecies.Bulbasaur; Form = 0; }
public void CastformCherrim_Interacts_With_AirLock(PBESpecies species, PBEAbility ability, PBEForm form) { #region Setup PBEDataProvider.GlobalRandom.Seed = 0; PBESettings settings = PBESettings.DefaultSettings; var p0 = new TestPokemonCollection(2); p0[0] = new TestPokemon(settings, PBESpecies.Magikarp, 0, 100, PBEMove.Splash); p0[1] = new TestPokemon(settings, PBESpecies.Rayquaza, 0, 100, PBEMove.Splash) { Ability = PBEAbility.AirLock }; var p1 = new TestPokemonCollection(1); p1[0] = new TestPokemon(settings, species, 0, 100, PBEMove.Splash) { Ability = ability }; var battle = new PBEBattle(PBEBattleFormat.Single, settings, new PBETrainerInfo(p0, "Trainer 0"), new PBETrainerInfo(p1, "Trainer 1"), weather: PBEWeather.HarshSunlight); battle.OnNewEvent += PBEBattle.ConsoleBattleEventHandler; PBETrainer t0 = battle.Trainers[0]; PBETrainer t1 = battle.Trainers[1]; PBEBattlePokemon magikarp = t0.Party[0]; PBEBattlePokemon rayquaza = t0.Party[1]; PBEBattlePokemon castformCherrim = t1.Party[0]; battle.Begin(); #endregion #region Check Castform/Cherrim for correct form Assert.True(battle.Weather == PBEWeather.HarshSunlight && castformCherrim.Form == form); #endregion #region Swap Magikarp for Rayquaza and check for no form Assert.Null(t0.SelectActionsIfValid(new PBETurnAction(magikarp, rayquaza))); Assert.Null(t1.SelectActionsIfValid(new PBETurnAction(castformCherrim, PBEMove.Splash, PBETurnTarget.AllyCenter))); battle.RunTurn(); Assert.True(battle.Weather == PBEWeather.HarshSunlight && castformCherrim.Form == 0); #endregion #region Swap Rayquaza for Magikarp and check for correct form Assert.Null(t0.SelectActionsIfValid(new PBETurnAction(rayquaza, magikarp))); Assert.Null(t1.SelectActionsIfValid(new PBETurnAction(castformCherrim, PBEMove.Splash, PBETurnTarget.AllyCenter))); battle.RunTurn(); Assert.True(battle.Weather == PBEWeather.HarshSunlight && castformCherrim.Form == form); #endregion #region Cleanup battle.OnNewEvent -= PBEBattle.ConsoleBattleEventHandler; #endregion }
public static Bitmap GetMinisprite(PBESpecies species, PBEGender gender, bool shiny) { ushort speciesID = (ushort)species; uint formID = (uint)species >> 0x10; string sss = speciesID + (formID > 0 ? ("_" + formID) : string.Empty) + (shiny ? "_S" : string.Empty); string genderStr = gender == PBEGender.Female && DoesResourceExist("PKMN.PKMN_" + sss + "_F.png") ? "_F" : string.Empty; return(new Bitmap(GetResourceStream("PKMN.PKMN_" + sss + genderStr + ".png"))); }
public async Task Info([Remainder] string speciesName) { PBESpecies?nSpecies = PBELocalizedString.GetSpeciesByName(speciesName); if (!nSpecies.HasValue) { await Context.Channel.SendMessageAsync($"{Context.User.Mention} Invalid species!"); } else { PBESpecies species = nSpecies.Value; var pData = PBEPokemonData.GetData(species); string types = pData.Type1.ToString(); if (pData.Type2 != PBEType.None) { types += ", " + pData.Type2.ToString(); } string ratio; switch (pData.GenderRatio) { case PBEGenderRatio.M7_F1: ratio = "87.5% Male, 12.5% Female"; break; case PBEGenderRatio.M3_F1: ratio = "75% Male, 25% Female"; break; case PBEGenderRatio.M1_F1: ratio = "50% Male, 50% Female"; break; case PBEGenderRatio.M1_F3: ratio = "25% Male, 75% Female"; break; case PBEGenderRatio.M0_F1: ratio = "100% Female"; break; case PBEGenderRatio.M1_F0: ratio = "100% Male"; break; case PBEGenderRatio.M0_F0: ratio = "Genderless Species"; break; default: throw new ArgumentOutOfRangeException(nameof(pData.GenderRatio)); } EmbedBuilder embed = new EmbedBuilder() .WithAuthor(Context.User) .WithColor(Utils.GetColor(pData.Type1, pData.Type2)) .WithTitle($"{PBELocalizedString.GetSpeciesName(species).English} - {PBELocalizedString.GetSpeciesCategory(species).English}") .WithUrl(Utils.URL) .WithDescription(PBELocalizedString.GetSpeciesEntry(species).English.Replace('\n', ' ')) .AddField("Types", types, true) .AddField("Gender Ratio", ratio, true) .AddField("Weight", $"{pData.Weight:N1} kg", true) .AddField("Abilities", string.Join(", ", pData.Abilities.Select(a => PBELocalizedString.GetAbilityName(a).English)), false) .AddField("HP", pData.BaseStats[0], true) .AddField("Attack", pData.BaseStats[1], true) .AddField("Defense", pData.BaseStats[2], true) .AddField("Special Attack", pData.BaseStats[3], true) .AddField("Special Defense", pData.BaseStats[4], true) .AddField("Speed", pData.BaseStats[5], true) .WithImageUrl(Utils.GetPokemonSprite(species, PBEUtils.RandomShiny(), PBEUtils.RandomGender(pData.GenderRatio), false, false)); await Context.Channel.SendMessageAsync(string.Empty, embed : embed.Build()); } }
public static IReadOnlyList <PBEForm> GetForms(PBESpecies species, bool requireUsableOutsideOfBattle) { if (species <= 0 || species >= PBESpecies.MAX) { throw new ArgumentOutOfRangeException(nameof(species)); } switch (species) { case PBESpecies.Arceus: return(_arceus); case PBESpecies.Basculin: return(_basculin); case PBESpecies.Burmy: return(_burmy); case PBESpecies.Castform: return(requireUsableOutsideOfBattle ? (IReadOnlyList <PBEForm>)Array.Empty <PBEForm>() : _castform); case PBESpecies.Cherrim: return(requireUsableOutsideOfBattle ? (IReadOnlyList <PBEForm>)Array.Empty <PBEForm>() : _cherrim); case PBESpecies.Darmanitan: return(requireUsableOutsideOfBattle ? (IReadOnlyList <PBEForm>)Array.Empty <PBEForm>() : _darmanitan); case PBESpecies.Deerling: return(_deerling); case PBESpecies.Deoxys: return(_deoxys); case PBESpecies.Gastrodon: return(_gastrodon); case PBESpecies.Genesect: return(_genesect); case PBESpecies.Giratina: return(_giratina); case PBESpecies.Keldeo: return(_keldeo); case PBESpecies.Kyurem: return(_kyurem); case PBESpecies.Landorus: return(_landorus); case PBESpecies.Meloetta: return(requireUsableOutsideOfBattle ? (IReadOnlyList <PBEForm>)Array.Empty <PBEForm>() : _meloetta); case PBESpecies.Rotom: return(_rotom); case PBESpecies.Sawsbuck: return(_sawsbuck); case PBESpecies.Shaymin: return(_shaymin); case PBESpecies.Shellos: return(_shellos); case PBESpecies.Thundurus: return(_thundurus); case PBESpecies.Tornadus: return(_tornadus); case PBESpecies.Unown: return(_unown); case PBESpecies.Wormadam: return(_wormadam); default: return(Array.Empty <PBEForm>()); } }
public static bool IsValidForm(PBESpecies species, PBEForm form, bool requireUsableOutsideOfBattle) { if (species <= 0 || species >= PBESpecies.MAX) { throw new ArgumentOutOfRangeException(nameof(species)); } switch (species) { case PBESpecies.Arceus: return(form <= PBEForm.Arceus_Dark); case PBESpecies.Basculin: return(form <= PBEForm.Basculin_Blue); case PBESpecies.Burmy: return(form <= PBEForm.Burmy_Trash); case PBESpecies.Castform: return(form <= (requireUsableOutsideOfBattle ? 0 : PBEForm.Castform_Snowy)); case PBESpecies.Cherrim: return(form <= (requireUsableOutsideOfBattle ? 0 : PBEForm.Cherrim_Sunshine)); case PBESpecies.Darmanitan: return(form <= (requireUsableOutsideOfBattle ? 0 : PBEForm.Darmanitan_Zen)); case PBESpecies.Deerling: return(form <= PBEForm.Deerling_Winter); case PBESpecies.Deoxys: return(form <= PBEForm.Deoxys_Speed); case PBESpecies.Gastrodon: return(form <= PBEForm.Gastrodon_East); case PBESpecies.Genesect: return(form <= PBEForm.Genesect_Chill); case PBESpecies.Giratina: return(form <= PBEForm.Giratina_Origin); case PBESpecies.Keldeo: return(form <= PBEForm.Keldeo_Resolute); case PBESpecies.Kyurem: return(form <= PBEForm.Kyurem_Black); case PBESpecies.Landorus: return(form <= PBEForm.Landorus_Therian); case PBESpecies.Meloetta: return(form <= (requireUsableOutsideOfBattle ? 0 : PBEForm.Meloetta_Pirouette)); case PBESpecies.Rotom: return(form <= PBEForm.Rotom_Mow); case PBESpecies.Sawsbuck: return(form <= PBEForm.Sawsbuck_Winter); case PBESpecies.Shaymin: return(form <= PBEForm.Shaymin_Sky); case PBESpecies.Shellos: return(form <= PBEForm.Shellos_East); case PBESpecies.Thundurus: return(form <= PBEForm.Thundurus_Therian); case PBESpecies.Tornadus: return(form <= PBEForm.Tornadus_Therian); case PBESpecies.Unown: return(form <= PBEForm.Unown_Question); case PBESpecies.Wormadam: return(form <= PBEForm.Wormadam_Trash); default: return(form <= 0); } }
public static Bitmap GetMinisprite(PBESpecies species, PBEGender gender, bool shiny) { uint speciesID = (uint)species & 0xFFFF; uint formeID = (uint)species >> 0x10; string sss = $"{speciesID}{(formeID > 0 ? $"_{formeID}" : string.Empty)}{(shiny ? "_S" : string.Empty)}"; bool spriteIsGenderNeutral = DoesResourceExist($"Kermalis.PokemonBattleEngineClient.PKMN.PKMN_{sss}.png"); string genderStr = spriteIsGenderNeutral ? string.Empty : gender == PBEGender.Female ? "_F" : "_M"; return(UriToBitmap(new Uri($"resm:Kermalis.PokemonBattleEngineClient.PKMN.PKMN_{sss}{genderStr}.png?assembly=PokemonBattleEngineClient"))); }