From b6ddd1ee13de059b4678166afc6a9e8b5c846230 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Fri, 17 Jun 2022 19:53:33 +0200 Subject: [PATCH] =?UTF-8?q?First=20chunk=20of=20battling=20is=20now=20full?= =?UTF-8?q?y=20working,=20along=20with=20integration=20tests!=20?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 8 +- src/dynamic_data/choices/mod.rs | 56 + src/dynamic_data/event_hooks/event_hook.rs | 6 +- src/dynamic_data/flow/turn_runner.rs | 19 +- src/dynamic_data/libraries/damage_library.rs | 11 +- src/dynamic_data/libraries/dynamic_library.rs | 24 +- src/dynamic_data/models/battle.rs | 18 +- src/dynamic_data/models/battle_party.rs | 17 +- src/dynamic_data/models/battle_side.rs | 77 +- src/dynamic_data/models/pokemon.rs | 146 +- src/dynamic_data/models/pokemon_builder.rs | 20 +- src/dynamic_data/models/pokemon_party.rs | 9 +- src/dynamic_data/script_handling/mod.rs | 8 +- src/static_data/items/item.rs | 2 +- src/static_data/items/item_category.rs | 6 + src/static_data/libraries/data_library.rs | 2 +- src/static_data/libraries/item_library.rs | 2 +- src/static_data/libraries/species_library.rs | 18 +- src/static_data/libraries/static_data.rs | 57 +- src/static_data/species_data/form.rs | 43 +- .../species_data/learnable_moves.rs | 81 +- src/static_data/species_data/species.rs | 14 +- src/static_data/statistics.rs | 4 + src/utils/string_key.rs | 7 + tests/common/data_getter.rs | 22 + tests/common/library_loader.rs | 400 ++++ tests/common/mod.rs | 9 + tests/common/test_case.rs | 82 + tests/common/test_step.rs | 82 + tests/data/Items.json | 1746 +++++++++-------- tests/library_loader.rs | 136 -- tests/main.rs | 38 + tests/test_cases/basic_single_turn.yaml | 44 + tests/tests.rs | 13 - 34 files changed, 1934 insertions(+), 1293 deletions(-) create mode 100644 tests/common/data_getter.rs create mode 100644 tests/common/library_loader.rs create mode 100644 tests/common/mod.rs create mode 100644 tests/common/test_case.rs create mode 100644 tests/common/test_step.rs delete mode 100644 tests/library_loader.rs create mode 100644 tests/main.rs create mode 100644 tests/test_cases/basic_single_turn.yaml delete mode 100644 tests/tests.rs diff --git a/Cargo.toml b/Cargo.toml index 1bb8f72..0beca31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ path = "src/lib.rs" [features] c_interface = [] -serde = ["dep:serde", "dep:serde_json"] +serde = ["dep:serde"] default = ["serde"] [profile.dev] @@ -52,9 +52,11 @@ hashbrown = "0.12.1" indexmap = "1.8.2" parking_lot = "0.12.1" serde = { version = "1.0.137", optional = true, features = ["derive"] } -serde_json = { version = "1.0.81", optional = true } [dev-dependencies] csv = "1.1.6" project-root = "0.2.2" -syn = "1.0.96" +datatest = "0.7.1" +serde_yaml = "0.8.24" +serde_json = "1.0.81" +serde_plain = "1.0.0" diff --git a/src/dynamic_data/choices/mod.rs b/src/dynamic_data/choices/mod.rs index f8f253e..9d349e6 100644 --- a/src/dynamic_data/choices/mod.rs +++ b/src/dynamic_data/choices/mod.rs @@ -204,6 +204,20 @@ pub struct ItemChoice<'user, 'library> { choice_data: Box>, } +impl<'user, 'library> ItemChoice<'user, 'library> { + pub fn new(user: Arc>>) -> Self { + Self { + choice_data: Box::new(CommonChoiceData { + user, + speed: 0, + random_value: 0, + has_failed: false, + script_source_data: Default::default(), + }), + } + } +} + impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> { fn get_script_count(&self) -> usize { 0 @@ -225,6 +239,20 @@ pub struct SwitchChoice<'user, 'library> { choice_data: Box>, } +impl<'user, 'library> SwitchChoice<'user, 'library> { + pub fn new(user: Arc>>) -> Self { + Self { + choice_data: Box::new(CommonChoiceData { + user, + speed: 0, + random_value: 0, + has_failed: false, + script_source_data: Default::default(), + }), + } + } +} + impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> { fn get_script_count(&self) -> usize { 0 @@ -246,6 +274,20 @@ pub struct FleeChoice<'user, 'library> { choice_data: Box>, } +impl<'user, 'library> FleeChoice<'user, 'library> { + pub fn new(user: Arc>>) -> Self { + Self { + choice_data: Box::new(CommonChoiceData { + user, + speed: 0, + random_value: 0, + has_failed: false, + script_source_data: Default::default(), + }), + } + } +} + impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> { fn get_script_count(&self) -> usize { 0 @@ -267,6 +309,20 @@ pub struct PassChoice<'user, 'library> { choice_data: Box>, } +impl<'user, 'library> PassChoice<'user, 'library> { + pub fn new(user: Arc>>) -> Self { + Self { + choice_data: Box::new(CommonChoiceData { + user, + speed: 0, + random_value: 0, + has_failed: false, + script_source_data: Default::default(), + }), + } + } +} + impl<'user, 'library> ScriptSource<'user> for PassChoice<'user, 'library> { fn get_script_count(&self) -> usize { 0 diff --git a/src/dynamic_data/event_hooks/event_hook.rs b/src/dynamic_data/event_hooks/event_hook.rs index ed2dd65..b0dec9b 100644 --- a/src/dynamic_data/event_hooks/event_hook.rs +++ b/src/dynamic_data/event_hooks/event_hook.rs @@ -43,12 +43,12 @@ pub enum Event<'own, 'battle, 'library> { }, SpeciesChange { pokemon: &'own Pokemon<'battle, 'library>, - species: &'own Species<'library>, - form: &'own Form<'library>, + species: &'own Species, + form: &'own Form, }, FormChange { pokemon: &'own Pokemon<'battle, 'library>, - form: &'own Form<'library>, + form: &'own Form, }, Damage { pokemon: &'own Pokemon<'battle, 'library>, diff --git a/src/dynamic_data/flow/turn_runner.rs b/src/dynamic_data/flow/turn_runner.rs index 033425c..329b70e 100644 --- a/src/dynamic_data/flow/turn_runner.rs +++ b/src/dynamic_data/flow/turn_runner.rs @@ -83,7 +83,11 @@ impl<'own, 'library> Battle<'own, 'library> { return Ok(()); } match choice_guard.deref() { - TurnChoice::Move(..) => self.execute_move_choice(&choice)?, + TurnChoice::Move(..) => { + drop(user); + drop(choice_guard); + self.execute_move_choice(&choice)? + } TurnChoice::Item(_) => {} TurnChoice::Switch(_) => {} TurnChoice::Flee(_) => {} @@ -100,13 +104,12 @@ impl<'own, 'library> Battle<'own, 'library> { let choice = write_guard.get_move_turn_data(); let used_move = choice.used_move(); let move_data_lock = used_move.read(); - let mut move_data = move_data_lock.move_data(); + let move_data = move_data_lock.move_data(); let mut move_name = move_data.name().clone(); script_hook!(change_move, choice, choice, &mut move_name); - if move_name != *move_data.name() { - move_data = self.library().static_data().moves().get(&move_name).unwrap(); - // FIXME: also change the script on the choice. - } + let move_data = self.library().static_data().moves().get(&move_name).unwrap(); + drop(move_data_lock); + // FIXME: also change the script on the choice if changed; let target_type = move_data.target(); let targets = resolve_targets(choice.target_side(), choice.target_index(), target_type, self); @@ -154,8 +157,8 @@ impl<'own, 'library> Battle<'own, 'library> { fn handle_move_for_target( &self, - executing_move: &mut ExecutingMove<'_, 'own, '_>, - target: &Arc>>, + executing_move: &mut ExecutingMove<'_, 'own, 'library>, + target: &Arc>>, ) -> PkmnResult<()> { { let mut fail = false; diff --git a/src/dynamic_data/libraries/damage_library.rs b/src/dynamic_data/libraries/damage_library.rs index 0d9de22..94b861f 100644 --- a/src/dynamic_data/libraries/damage_library.rs +++ b/src/dynamic_data/libraries/damage_library.rs @@ -40,6 +40,7 @@ pub trait DamageLibrary: std::fmt::Debug { hit_data: &HitData, ) -> f32; } + #[derive(Debug)] pub struct Gen7DamageLibrary { has_randomness: bool, @@ -93,8 +94,14 @@ impl DamageLibrary for Gen7DamageLibrary { } if self.has_randomness { - let battle = executing_move.user().read().get_battle().unwrap().upgrade().unwrap(); - let random_percentage = 85 + battle.read().random().get_between(0, 16); + let random_percentage = 85 + + executing_move + .user() + .read() + .get_battle() + .unwrap() + .random() + .get_between(0, 16); float_damage = (float_damage * (random_percentage as f32 / 100.0)).floor(); } diff --git a/src/dynamic_data/libraries/dynamic_library.rs b/src/dynamic_data/libraries/dynamic_library.rs index 276ce59..9b5b79d 100644 --- a/src/dynamic_data/libraries/dynamic_library.rs +++ b/src/dynamic_data/libraries/dynamic_library.rs @@ -10,14 +10,32 @@ use crate::{PkmnResult, StringKey}; #[derive(Debug)] pub struct DynamicLibrary { - static_data: StaticData<'static>, + static_data: StaticData, stat_calculator: BattleStatCalculator, damage_calculator: Box, misc_library: Box>, } -impl<'library> DynamicLibrary { - pub fn static_data(&self) -> &StaticData<'library> { +unsafe impl Sync for DynamicLibrary {} + +unsafe impl Send for DynamicLibrary {} + +impl DynamicLibrary { + pub fn new( + static_data: StaticData, + stat_calculator: BattleStatCalculator, + damage_calculator: Box, + misc_library: Box>, + ) -> Self { + Self { + static_data, + stat_calculator, + damage_calculator, + misc_library, + } + } + + pub fn static_data(&self) -> &StaticData { &self.static_data } pub fn stat_calculator(&self) -> &BattleStatCalculator { diff --git a/src/dynamic_data/models/battle.rs b/src/dynamic_data/models/battle.rs index 47c0196..e4ac6db 100644 --- a/src/dynamic_data/models/battle.rs +++ b/src/dynamic_data/models/battle.rs @@ -47,14 +47,18 @@ impl<'own, 'library> Battle<'own, 'library> { number_of_sides: u8, pokemon_per_side: u8, random_seed: Option, - ) -> Arc> { + ) -> Self { let random = if let Some(seed) = random_seed { BattleRandom::new_with_seed(seed) } else { BattleRandom::default() }; - let sides = Vec::with_capacity(number_of_sides as usize); - let battle = Arc::new(RwLock::new(Self { + let mut sides = Vec::with_capacity(number_of_sides as usize); + for i in 0..number_of_sides { + sides.push(BattleSide::new(i, pokemon_per_side)); + } + + let mut battle = Self { library, parties, can_flee, @@ -71,11 +75,13 @@ impl<'own, 'library> Battle<'own, 'library> { volatile_scripts: Default::default(), last_turn_time: chrono::Duration::zero(), script_source_data: Default::default(), - })); + }; - for i in 0..number_of_sides { - battle.write().sides[i as usize] = BattleSide::new(i, Arc::downgrade(&battle), pokemon_per_side); + let ptr: *mut Battle = &mut battle; + for side in &mut battle.sides { + side.set_battle(ptr); } + battle } diff --git a/src/dynamic_data/models/battle_party.rs b/src/dynamic_data/models/battle_party.rs index 4aa7a69..91c9f33 100644 --- a/src/dynamic_data/models/battle_party.rs +++ b/src/dynamic_data/models/battle_party.rs @@ -1,12 +1,21 @@ +use crate::dynamic_data::models::pokemon::Pokemon; use crate::dynamic_data::models::pokemon_party::PokemonParty; +use parking_lot::RwLock; +use std::sync::Arc; #[derive(Debug)] pub struct BattleParty<'own, 'library> { - party: &'own PokemonParty<'own, 'library>, + party: Arc>, responsible_indices: Vec<(u8, u8)>, } impl<'own, 'library> BattleParty<'own, 'library> { + pub fn new(party: Arc>, responsible_indices: Vec<(u8, u8)>) -> Self { + Self { + party, + responsible_indices, + } + } pub fn is_responsible_for_index(&self, side: u8, index: u8) -> bool { for responsible_index in &self.responsible_indices { if responsible_index.0 == side && responsible_index.1 == index { @@ -18,11 +27,15 @@ impl<'own, 'library> BattleParty<'own, 'library> { pub fn has_pokemon_not_in_field(&self) -> bool { for pokemon in self.party.pokemon().iter().flatten() { - let pokemon = pokemon.read().unwrap(); + let pokemon = pokemon.read(); if pokemon.is_usable() && !pokemon.is_on_battlefield() { return true; } } false } + + pub fn get_pokemon(&self, index: usize) -> &Option>>> { + self.party.at(index) + } } diff --git a/src/dynamic_data/models/battle_side.rs b/src/dynamic_data/models/battle_side.rs index 918b7e6..57ac59e 100644 --- a/src/dynamic_data/models/battle_side.rs +++ b/src/dynamic_data/models/battle_side.rs @@ -9,8 +9,7 @@ use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts; use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; use crate::{script_hook, PkmnResult, StringKey}; use parking_lot::RwLock; -use std::ops::Deref; -use std::sync::{Arc, Weak}; +use std::sync::Arc; #[derive(Debug)] pub struct BattleSide<'own, 'library> { @@ -20,7 +19,7 @@ pub struct BattleSide<'own, 'library> { choices: Vec>>>>, fillable_slots: Vec, choices_set: u8, - battle: Weak>>, + battle: *mut Battle<'own, 'library>, has_fled_battle: bool, volatile_scripts: Arc>, @@ -28,15 +27,15 @@ pub struct BattleSide<'own, 'library> { } impl<'own, 'library> BattleSide<'own, 'library> { - pub fn new(index: u8, battle: Weak>>, pokemon_per_side: u8) -> Self { + pub fn new(index: u8, pokemon_per_side: u8) -> Self { let mut pokemon = Vec::with_capacity(pokemon_per_side as usize); let mut choices = Vec::with_capacity(pokemon_per_side as usize); let mut fillable_slots = Vec::with_capacity(pokemon_per_side as usize); - for i in 0..pokemon_per_side { - pokemon[i as usize] = None; - choices[i as usize] = None; - fillable_slots[i as usize] = true; + for _i in 0..pokemon_per_side { + pokemon.push(None); + choices.push(None); + fillable_slots.push(true); } Self { @@ -46,12 +45,17 @@ impl<'own, 'library> BattleSide<'own, 'library> { choices, fillable_slots, choices_set: 0, - battle, + battle: 0 as *mut Battle, has_fled_battle: false, volatile_scripts: Default::default(), script_source_data: Default::default(), } } + + pub(crate) fn set_battle(&mut self, battle: *mut Battle<'own, 'library>) { + self.battle = battle; + } + pub fn index(&self) -> u8 { self.index } @@ -74,8 +78,8 @@ impl<'own, 'library> BattleSide<'own, 'library> { pub fn choices_set(&self) -> u8 { self.choices_set } - pub fn battle(&self) -> &Weak>> { - &self.battle + pub fn battle(&self) -> &Battle<'own, 'library> { + unsafe { self.battle.as_ref().unwrap() } } pub fn has_fled_battle(&self) -> bool { self.has_fled_battle @@ -94,12 +98,7 @@ impl<'own, 'library> BattleSide<'own, 'library> { pub fn all_slots_filled(&self) -> bool { for (i, pokemon) in self.pokemon.iter().enumerate() { if (!pokemon.is_none() || !pokemon.as_ref().unwrap().read().is_usable()) - && self - .battle - .upgrade() - .unwrap() - .read() - .can_slot_be_filled(self.index, i as u8) + && self.battle().can_slot_be_filled(self.index, i as u8) { return false; } @@ -140,12 +139,11 @@ impl<'own, 'library> BattleSide<'own, 'library> { let pokemon = &self.pokemon[index as usize]; if let Some(pokemon_mutex) = pokemon { let mut pokemon = pokemon_mutex.write(); - pokemon.set_battle_data(self.battle.clone(), self.index); + pokemon.set_battle_data(self.battle, self.index); pokemon.set_on_battlefield(true); pokemon.set_battle_index(index); - let battle = self.battle.upgrade().unwrap(); - let battle = battle.read(); + let battle = self.battle(); for side in battle.sides() { if side.index() == self.index { continue; @@ -163,9 +161,7 @@ impl<'own, 'library> BattleSide<'own, 'library> { }); script_hook!(on_switch_in, pokemon, &pokemon); } else { - let battle = self.battle.upgrade().unwrap(); - let battle = battle.read(); - battle.event_hook().trigger(Event::Switch { + self.battle().event_hook().trigger(Event::Switch { side_index: self.index, index, pokemon: None, @@ -182,15 +178,8 @@ impl<'own, 'library> BattleSide<'own, 'library> { false } - pub fn mark_slot_as_unfillable(&mut self, pokemon: &Pokemon<'own, 'library>) { - for (i, slot) in self.pokemon.iter().enumerate() { - if let Some(p) = slot { - if p.read().deref() as *const Pokemon == pokemon as *const Pokemon { - self.fillable_slots[i] = false; - return; - } - } - } + pub fn mark_slot_as_unfillable(&mut self, index: u8) { + self.fillable_slots[index as usize] = false; } pub fn is_slot_unfillable(&self, pokemon: Arc>) -> bool { @@ -223,12 +212,7 @@ impl<'own, 'library> BattleSide<'own, 'library> { pub fn get_random_creature_index(&self) -> u8 { // TODO: Consider adding parameter to only get index for available creatures. - self.battle - .upgrade() - .unwrap() - .read() - .random() - .get_max(self.pokemon_per_side as i32) as u8 + self.battle().random().get_max(self.pokemon_per_side as i32) as u8 } pub fn swap_positions(&mut self, a: u8, b: u8) -> bool { @@ -241,12 +225,10 @@ impl<'own, 'library> BattleSide<'own, 'library> { return false; } - let battle = self.battle.upgrade().unwrap(); - let battle = battle.read(); // Fetch parties for the two indices. let mut party_a = None; let mut party_b = None; - for party in battle.parties() { + for party in self.battle().parties() { if party.is_responsible_for_index(self.index, a) { party_a = Some(party); } @@ -264,7 +246,7 @@ impl<'own, 'library> BattleSide<'own, 'library> { } self.pokemon.swap(a as usize, b as usize); - battle.event_hook().trigger(Event::Swap { + self.battle().event_hook().trigger(Event::Swap { side_index: self.index, index_a: a, index_b: b, @@ -279,18 +261,13 @@ impl<'own, 'library> VolatileScripts<'own> for BattleSide<'own, 'library> { } fn load_volatile_script(&self, key: &StringKey) -> PkmnResult>> { - self.battle - .upgrade() - .unwrap() - .read() - .library() - .load_script(crate::ScriptCategory::Side, key) + self.battle().library().load_script(crate::ScriptCategory::Side, key) } } impl<'own, 'library> ScriptSource<'own> for BattleSide<'own, 'library> { fn get_script_count(&self) -> usize { - self.battle.upgrade().unwrap().read().get_script_count() + 1 + self.battle().get_script_count() + 1 } fn get_script_source_data(&self) -> &RwLock { @@ -303,6 +280,6 @@ impl<'own, 'library> ScriptSource<'own> for BattleSide<'own, 'library> { fn collect_scripts(&self, scripts: &mut Vec) { self.get_own_scripts(scripts); - self.battle.upgrade().unwrap().read().collect_scripts(scripts); + self.battle().collect_scripts(scripts); } } diff --git a/src/dynamic_data/models/pokemon.rs b/src/dynamic_data/models/pokemon.rs index 38ca045..b2f7630 100644 --- a/src/dynamic_data/models/pokemon.rs +++ b/src/dynamic_data/models/pokemon.rs @@ -3,7 +3,7 @@ use crate::dynamic_data::event_hooks::event_hook::Event; use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary; use crate::dynamic_data::models::battle::Battle; use crate::dynamic_data::models::damage_source::DamageSource; -use crate::dynamic_data::models::learned_move::LearnedMove; +use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod}; use crate::dynamic_data::script_handling::script::{Script, ScriptContainer}; use crate::dynamic_data::script_handling::script_set::ScriptSet; use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts; @@ -16,7 +16,7 @@ use crate::static_data::species_data::form::Form; use crate::static_data::species_data::gender::Gender; use crate::static_data::species_data::species::Species; use crate::static_data::statistic_set::{ClampedStatisticSet, StatisticSet}; -use crate::static_data::statistics::Statistic; +use crate::static_data::DataLibrary; use crate::utils::random::Random; use crate::{script_hook, PkmnResult, ScriptCategory, StringKey}; use parking_lot::RwLock; @@ -24,7 +24,7 @@ use std::sync::{Arc, Weak}; #[derive(Debug)] pub struct PokemonBattleData<'pokemon, 'library> { - battle: Weak>>, + battle: *mut Battle<'pokemon, 'library>, battle_side_index: u8, index: u8, on_battle_field: bool, @@ -32,9 +32,13 @@ pub struct PokemonBattleData<'pokemon, 'library> { } impl<'pokemon, 'library> PokemonBattleData<'pokemon, 'library> { - pub fn battle(&mut self) -> &mut Weak>> { - &mut self.battle + pub fn battle_mut(&mut self) -> Option<&mut Battle<'pokemon, 'library>> { + unsafe { self.battle.as_mut() } } + pub fn battle(&self) -> Option<&Battle<'pokemon, 'library>> { + unsafe { self.battle.as_ref() } + } + pub fn battle_side_index(&self) -> u8 { self.battle_side_index } @@ -52,11 +56,11 @@ where 'own: 'library, { library: &'own DynamicLibrary, - species: &'own Species<'library>, - form: &'own Form<'library>, + species: &'own Species, + form: &'own Form, - display_species: Option<&'own Species<'library>>, - display_form: Option<&'own Form<'library>>, + display_species: Option<&'own Species>, + display_form: Option<&'own Form>, level: LevelInt, experience: u32, @@ -84,7 +88,7 @@ where battle_data: Option>, - moves: [Option>; MAX_MOVES], + moves: [Option>>>; MAX_MOVES], allowed_experience: bool, types: Vec, @@ -116,14 +120,13 @@ impl<'own, 'library> Pokemon<'own, 'library> { .static_data() .growth_rates() .calculate_experience(species.growth_rate(), level); - let health = form.get_base_stat(Statistic::HP) as u32; let weight = form.weight(); let height = form.height(); let nature = library .static_data() .natures() .get_nature(&nature) - .expect("Unknown nature name was given."); + .unwrap_or_else(|| panic!("Unknown nature name was given: {}.", &nature)); let mut pokemon = Self { library, species, @@ -136,7 +139,7 @@ impl<'own, 'library> Pokemon<'own, 'library> { gender, coloring, held_item: None, - current_health: health, + current_health: 1, weight, height, stat_boost: Default::default(), @@ -162,26 +165,29 @@ impl<'own, 'library> Pokemon<'own, 'library> { script_source_data: Default::default(), }; pokemon.recalculate_flat_stats(); + let health = pokemon.flat_stats().hp(); + pokemon.current_health = health; + pokemon } pub fn library(&self) -> &'own DynamicLibrary { self.library } - pub fn species(&self) -> &'own Species<'library> { + pub fn species(&self) -> &'own Species { self.species } - pub fn form(&self) -> &'own Form<'library> { + pub fn form(&self) -> &'own Form { self.form } - pub fn display_species(&self) -> &'own Species<'library> { + pub fn display_species(&self) -> &'own Species { if let Some(v) = self.display_species { v } else { self.species } } - pub fn display_form(&self) -> &'own Form<'library> { + pub fn display_form(&self) -> &'own Form { if let Some(v) = self.display_form { v } else { @@ -254,7 +260,7 @@ impl<'own, 'library> Pokemon<'own, 'library> { pub fn types(&self) -> &Vec { &self.types } - pub fn learned_moves(&self) -> &[Option; MAX_MOVES] { + pub fn learned_moves(&self) -> &[Option>>>; MAX_MOVES] { &self.moves } pub fn status(&self) -> &ScriptContainer { @@ -276,9 +282,9 @@ impl<'own, 'library> Pokemon<'own, 'library> { &self.effort_values } - pub fn get_battle(&self) -> Option<&Weak>>> { + pub fn get_battle(&self) -> Option<&Battle<'own, 'library>> { if let Some(data) = &self.battle_data { - Some(&data.battle) + Some(&data.battle().unwrap()) } else { None } @@ -298,7 +304,11 @@ impl<'own, 'library> Pokemon<'own, 'library> { return v; } } - self.form.get_ability(self.ability_index) + self.library + .static_data() + .abilities() + .get(self.form.get_ability(self.ability_index)) + .unwrap() } pub fn ability_script(&self) -> &ScriptContainer { @@ -337,17 +347,8 @@ impl<'own, 'library> Pokemon<'own, 'library> { // If we're in battle, use the battle random for predictability if self.battle_data.is_some() { let battle_data = self.battle_data.as_mut().unwrap(); - self.gender = species.get_random_gender( - &mut battle_data - .battle - .upgrade() - .unwrap() - .read() - .random() - .get_rng() - .lock() - .unwrap(), - ); + self.gender = + species.get_random_gender(&mut battle_data.battle().unwrap().random().get_rng().lock().unwrap()); } else { // If we're not in battle, just use a new random. self.gender = species.get_random_gender(&mut Random::default()); @@ -358,8 +359,8 @@ impl<'own, 'library> Pokemon<'own, 'library> { self.gender = Gender::Genderless; } if let Some(battle_data) = &self.battle_data { - if let Some(battle) = battle_data.battle.upgrade() { - battle.read().event_hook().trigger(Event::SpeciesChange { + if let Some(battle) = battle_data.battle() { + battle.event_hook().trigger(Event::SpeciesChange { pokemon: self, species, form, @@ -408,11 +409,8 @@ impl<'own, 'library> Pokemon<'own, 'library> { // TODO: consider form specific attacks? if let Some(battle_data) = &self.battle_data { - if let Some(battle) = battle_data.battle.upgrade() { - battle - .read() - .event_hook() - .trigger(Event::FormChange { pokemon: self, form }) + if let Some(battle) = battle_data.battle() { + battle.event_hook().trigger(Event::FormChange { pokemon: self, form }) } } } @@ -425,7 +423,7 @@ impl<'own, 'library> Pokemon<'own, 'library> { self.current_health == 0 } - pub fn set_battle_data(&mut self, battle: Weak>>, battle_side_index: u8) { + pub fn set_battle_data(&mut self, battle: *mut Battle<'own, 'library>, battle_side_index: u8) { if let Some(battle_data) = &mut self.battle_data { battle_data.battle = battle; battle_data.battle_side_index = battle_side_index; @@ -485,8 +483,8 @@ impl<'own, 'library> Pokemon<'own, 'library> { } let new_health = self.current_health() - damage; if let Some(battle_data) = &self.battle_data { - if let Some(battle) = battle_data.battle.upgrade() { - battle.read().event_hook().trigger(Event::Damage { + if let Some(battle) = battle_data.battle() { + battle.event_hook().trigger(Event::Damage { pokemon: self, source, original_health: self.current_health(), @@ -502,36 +500,56 @@ impl<'own, 'library> Pokemon<'own, 'library> { } } - pub fn on_faint(&self, source: DamageSource) { - if let Some(battle_data) = &self.battle_data { - if let Some(battle) = battle_data.battle.upgrade() { - battle.read().event_hook().trigger(Event::Faint { pokemon: self }); - script_hook!(on_faint, self, self, source); - script_hook!(on_remove, self,); - } - // TODO: Experience gain + pub fn on_faint(&mut self, source: DamageSource) { + if self.battle_data.is_some() && self.battle_data.as_ref().unwrap().battle().is_some() { + self.battle_data + .as_ref() + .unwrap() + .battle() + .unwrap() + .event_hook() + .trigger(Event::Faint { pokemon: self }); + script_hook!(on_faint, self, self, source); + script_hook!(on_remove, self,); - if let Some(battle) = battle_data.battle.upgrade() { - if !battle - .read() - .can_slot_be_filled(battle_data.battle_side_index, battle_data.index) - { - let mut battle = battle.write(); - let side = &mut battle.sides_mut()[battle_data.battle_side_index as usize]; - side.mark_slot_as_unfillable(self); - } - battle.write().validate_battle_state(); + let side_index = self.battle_data.as_ref().unwrap().battle_side_index; + let index = self.battle_data.as_ref().unwrap().index; + if !self + .battle_data + .as_ref() + .unwrap() + .battle() + .unwrap() + .can_slot_be_filled(side_index, index) + { + self.battle_data.as_mut().unwrap().battle_mut().unwrap().sides_mut()[side_index as usize] + .mark_slot_as_unfillable(index); } + self.battle_data + .as_mut() + .unwrap() + .battle_mut() + .unwrap() + .validate_battle_state(); } } + + pub fn learn_move(&mut self, move_name: &StringKey, learn_method: MoveLearnMethod) { + let move_pos = self.learned_moves().iter().position(|a| a.is_none()); + if move_pos.is_none() { + panic!("No more moves with an empty space found."); + } + let move_data = self.library.static_data().moves().get(move_name).unwrap(); + self.moves[move_pos.unwrap()] = Some(Arc::new(RwLock::new(LearnedMove::new(move_data, learn_method)))); + } } impl<'own, 'library> ScriptSource<'own> for Pokemon<'own, 'library> { fn get_script_count(&self) -> usize { let mut c = 3; if let Some(battle_data) = &self.battle_data { - if let Some(battle) = battle_data.battle.upgrade() { - c += battle.read().sides()[battle_data.battle_side_index as usize].get_script_count(); + if let Some(battle) = battle_data.battle() { + c += battle.sides()[battle_data.battle_side_index as usize].get_script_count(); } } c @@ -551,8 +569,8 @@ impl<'own, 'library> ScriptSource<'own> for Pokemon<'own, 'library> { fn collect_scripts(&self, scripts: &mut Vec) { self.get_own_scripts(scripts); if let Some(battle_data) = &self.battle_data { - if let Some(battle) = battle_data.battle.upgrade() { - battle.read().sides()[battle_data.battle_side_index as usize].collect_scripts(scripts); + if let Some(battle) = battle_data.battle() { + battle.sides()[battle_data.battle_side_index as usize].collect_scripts(scripts); } } } diff --git a/src/dynamic_data/models/pokemon_builder.rs b/src/dynamic_data/models/pokemon_builder.rs index 77d2965..9e93a99 100644 --- a/src/dynamic_data/models/pokemon_builder.rs +++ b/src/dynamic_data/models/pokemon_builder.rs @@ -1,5 +1,6 @@ use crate::defines::LevelInt; use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary; +use crate::dynamic_data::models::learned_move::MoveLearnMethod; use crate::dynamic_data::models::pokemon::Pokemon; use crate::static_data::{AbilityIndex, DataLibrary, Gender}; use crate::StringKey; @@ -8,6 +9,7 @@ pub struct PokemonBuilder<'own> { library: &'own DynamicLibrary, species: StringKey, level: LevelInt, + learned_moves: Vec, } impl<'own> PokemonBuilder<'own> { @@ -16,13 +18,18 @@ impl<'own> PokemonBuilder<'own> { library, species, level, + learned_moves: vec![], } } + pub fn learn_move(mut self, learned_move: StringKey) -> Self { + self.learned_moves.push(learned_move); + self + } - pub fn build<'func>(self) -> Pokemon<'own, 'own> { + pub fn build(self) -> Pokemon<'own, 'own> { let species = self.library.static_data().species().get(&self.species).unwrap(); let form = species.get_default_form(); - Pokemon::new( + let mut p = Pokemon::new( self.library, species, form, @@ -34,7 +41,12 @@ impl<'own> PokemonBuilder<'own> { 0, Gender::Male, 0, - &"test_nature".into(), - ) + &"hardy".into(), + ); + for learned_move in self.learned_moves { + p.learn_move(&learned_move, MoveLearnMethod::Unknown); + } + + p } } diff --git a/src/dynamic_data/models/pokemon_party.rs b/src/dynamic_data/models/pokemon_party.rs index f729242..49f4e8d 100644 --- a/src/dynamic_data/models/pokemon_party.rs +++ b/src/dynamic_data/models/pokemon_party.rs @@ -1,5 +1,6 @@ use crate::dynamic_data::models::pokemon::Pokemon; -use std::sync::{Arc, RwLock}; +use parking_lot::RwLock; +use std::sync::Arc; #[derive(Debug)] pub struct PokemonParty<'pokemon, 'library> { @@ -15,6 +16,10 @@ impl<'own, 'library> PokemonParty<'own, 'library> { Self { pokemon } } + pub fn new_from_vec(pokemon: Vec>>>>) -> Self { + Self { pokemon } + } + pub fn at(&self, index: usize) -> &Option>>> { let opt = self.pokemon.get(index); if let Some(v) = opt { @@ -43,7 +48,7 @@ impl<'own, 'library> PokemonParty<'own, 'library> { pub fn has_usable_pokemon(&self) -> bool { for pokemon in self.pokemon.iter().flatten() { - if pokemon.read().unwrap().is_usable() { + if pokemon.read().is_usable() { return true; } } diff --git a/src/dynamic_data/script_handling/mod.rs b/src/dynamic_data/script_handling/mod.rs index d650180..4b2af2d 100644 --- a/src/dynamic_data/script_handling/mod.rs +++ b/src/dynamic_data/script_handling/mod.rs @@ -149,9 +149,11 @@ impl ScriptAggregator { self.index = index; let wrapper = unsafe { &self.scripts.as_ref().unwrap()[self.index as usize] }; if let ScriptWrapper::Set(s) = wrapper { - if let Some(..) = s.upgrade() { - self.set_index = 0; - return true; + if let Some(set) = s.upgrade() { + if set.read().count() > 0 { + self.set_index = 0; + return true; + } } } else if let ScriptWrapper::Script(script) = wrapper { if let Some(v) = script.upgrade() { diff --git a/src/static_data/items/item.rs b/src/static_data/items/item.rs index 220084d..5441267 100644 --- a/src/static_data/items/item.rs +++ b/src/static_data/items/item.rs @@ -1,6 +1,6 @@ use super::item_category::{BattleItemCategory, ItemCategory}; use crate::StringKey; -use std::collections::HashSet; +use hashbrown::HashSet; #[derive(Debug)] pub struct Item { diff --git a/src/static_data/items/item_category.rs b/src/static_data/items/item_category.rs index 8c0be59..ae4b363 100644 --- a/src/static_data/items/item_category.rs +++ b/src/static_data/items/item_category.rs @@ -1,4 +1,8 @@ +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + #[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum ItemCategory { MiscItem, @@ -12,8 +16,10 @@ pub enum ItemCategory { } #[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum BattleItemCategory { + None, Healing, StatusHealing, Pokeball, diff --git a/src/static_data/libraries/data_library.rs b/src/static_data/libraries/data_library.rs index 4f93d1c..c7f3277 100644 --- a/src/static_data/libraries/data_library.rs +++ b/src/static_data/libraries/data_library.rs @@ -20,7 +20,7 @@ pub trait DataLibrary<'a, T: 'a> { modifies.1.remove(index); } - fn get(&self, key: &StringKey) -> Option<&T> { + fn get(&'a self, key: &StringKey) -> Option<&'a T> { self.map().get(key) } diff --git a/src/static_data/libraries/item_library.rs b/src/static_data/libraries/item_library.rs index a7ecdf3..318df44 100644 --- a/src/static_data/libraries/item_library.rs +++ b/src/static_data/libraries/item_library.rs @@ -38,7 +38,7 @@ pub mod tests { use crate::static_data::items::item_category::{BattleItemCategory, ItemCategory}; use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::item_library::ItemLibrary; - use std::collections::HashSet; + use hashbrown::HashSet; fn build_item() -> Item { Item::new( diff --git a/src/static_data/libraries/species_library.rs b/src/static_data/libraries/species_library.rs index 1b9f0a8..62d1736 100644 --- a/src/static_data/libraries/species_library.rs +++ b/src/static_data/libraries/species_library.rs @@ -4,13 +4,13 @@ use crate::StringKey; use hashbrown::HashMap; #[derive(Debug)] -pub struct SpeciesLibrary<'a> { - map: HashMap>>, +pub struct SpeciesLibrary { + map: HashMap>, list: Vec, } -impl<'a> SpeciesLibrary<'a> { - pub fn new(capacity: usize) -> SpeciesLibrary<'a> { +impl SpeciesLibrary { + pub fn new(capacity: usize) -> SpeciesLibrary { SpeciesLibrary { map: HashMap::with_capacity(capacity), list: Vec::with_capacity(capacity), @@ -18,8 +18,8 @@ impl<'a> SpeciesLibrary<'a> { } } -impl<'a> DataLibrary<'a, Box>> for SpeciesLibrary<'a> { - fn map(&self) -> &HashMap>> { +impl<'a> DataLibrary<'a, Box> for SpeciesLibrary { + fn map(&self) -> &HashMap> { &self.map } @@ -27,7 +27,7 @@ impl<'a> DataLibrary<'a, Box>> for SpeciesLibrary<'a> { &self.list } - fn get_modify(&mut self) -> (&mut HashMap>>, &mut Vec) { + fn get_modify(&mut self) -> (&mut HashMap>, &mut Vec) { (&mut self.map, &mut self.list) } } @@ -42,7 +42,7 @@ pub mod tests { use crate::static_data::statistic_set::StatisticSet; use hashbrown::HashSet; - fn build_species<'a>() -> Species<'a> { + fn build_species<'a>() -> Species { Species::new( 0, &"foo".into(), @@ -65,7 +65,7 @@ pub mod tests { ) } - pub fn build<'a>() -> SpeciesLibrary<'a> { + pub fn build<'a>() -> SpeciesLibrary { let mut lib = SpeciesLibrary::new(1); let species = build_species(); // Borrow as mut so we can insert diff --git a/src/static_data/libraries/static_data.rs b/src/static_data/libraries/static_data.rs index 4a71502..356148d 100644 --- a/src/static_data/libraries/static_data.rs +++ b/src/static_data/libraries/static_data.rs @@ -8,9 +8,9 @@ use crate::static_data::SpeciesLibrary; use crate::static_data::TypeLibrary; #[derive(Debug)] -pub struct StaticData<'a> { +pub struct StaticData { settings: LibrarySettings, - species: SpeciesLibrary<'a>, + species: SpeciesLibrary, moves: MoveLibrary, items: ItemLibrary, growth_rates: GrowthRateLibrary, @@ -19,53 +19,66 @@ pub struct StaticData<'a> { abilities: AbilityLibrary, } -impl<'a> StaticData<'a> { - pub fn new( - settings: LibrarySettings, - species: SpeciesLibrary<'a>, - moves: MoveLibrary, - items: ItemLibrary, - growth_rates: GrowthRateLibrary, - types: TypeLibrary, - natures: NatureLibrary, - abilities: AbilityLibrary, - ) -> Self { +impl StaticData { + pub fn new(settings: LibrarySettings) -> Self { Self { settings, - species, - moves, - items, - growth_rates, - types, - natures, - abilities, + species: SpeciesLibrary::new(0), + moves: MoveLibrary::new(0), + items: ItemLibrary::new(0), + growth_rates: GrowthRateLibrary::new(0), + types: TypeLibrary::new(0), + natures: NatureLibrary::new(0), + abilities: AbilityLibrary::new(0), } } pub fn settings(&self) -> &LibrarySettings { &self.settings } - pub fn species(&self) -> &SpeciesLibrary<'a> { + pub fn species(&self) -> &SpeciesLibrary { &self.species } + pub fn species_mut(&mut self) -> &mut SpeciesLibrary { + &mut self.species + } pub fn moves(&self) -> &MoveLibrary { &self.moves } + pub fn moves_mut(&mut self) -> &mut MoveLibrary { + &mut self.moves + } pub fn items(&self) -> &ItemLibrary { &self.items } + pub fn items_mut(&mut self) -> &mut ItemLibrary { + &mut self.items + } + pub fn growth_rates(&self) -> &GrowthRateLibrary { &self.growth_rates } + pub fn growth_rates_mut(&mut self) -> &mut GrowthRateLibrary { + &mut self.growth_rates + } pub fn types(&self) -> &TypeLibrary { &self.types } + pub fn types_mut(&mut self) -> &mut TypeLibrary { + &mut self.types + } pub fn natures(&self) -> &NatureLibrary { &self.natures } + pub fn natures_mut(&mut self) -> &mut NatureLibrary { + &mut self.natures + } pub fn abilities(&self) -> &AbilityLibrary { &self.abilities } + pub fn abilities_mut<'a>(&'a mut self) -> &'a mut AbilityLibrary { + &mut self.abilities + } } #[cfg(test)] @@ -77,7 +90,7 @@ pub mod test { }; use crate::static_data::natures; - pub fn build<'a>() -> StaticData<'a> { + pub fn build<'a>() -> StaticData { StaticData { settings: LibrarySettings::new(100), species: species_library::tests::build(), diff --git a/src/static_data/species_data/form.rs b/src/static_data/species_data/form.rs index 095e6f2..5e822a6 100644 --- a/src/static_data/species_data/form.rs +++ b/src/static_data/species_data/form.rs @@ -6,23 +6,22 @@ use crate::static_data::StatisticSet; use crate::Random; use crate::StringKey; use hashbrown::HashSet; -use std::ops::Deref; #[derive(Debug)] -pub struct Form<'a> { +pub struct Form { name: StringKey, height: f32, weight: f32, base_experience: u32, types: Vec, base_stats: StatisticSet, - abilities: Vec<&'a Ability>, - hidden_abilities: Vec<&'a Ability>, - moves: LearnableMoves<'a>, + abilities: Vec, + hidden_abilities: Vec, + moves: LearnableMoves, flags: HashSet, } -impl<'a> Form<'a> { +impl Form { pub fn new( name: &StringKey, height: f32, @@ -30,11 +29,11 @@ impl<'a> Form<'a> { base_experience: u32, types: Vec, base_stats: StatisticSet, - abilities: Vec<&'a Ability>, - hidden_abilities: Vec<&'a Ability>, - moves: LearnableMoves<'a>, + abilities: Vec, + hidden_abilities: Vec, + moves: LearnableMoves, flags: HashSet, - ) -> Form<'a> { + ) -> Form { Form { name: name.clone(), height, @@ -67,13 +66,13 @@ impl<'a> Form<'a> { pub fn base_stats(&self) -> StatisticSet { self.base_stats } - pub fn abilities(&self) -> &Vec<&'a Ability> { + pub fn abilities(&self) -> &Vec { &self.abilities } - pub fn hidden_abilities(&self) -> &Vec<&'a Ability> { + pub fn hidden_abilities(&self) -> &Vec { &self.hidden_abilities } - pub fn moves(&self) -> &LearnableMoves<'a> { + pub fn moves(&self) -> &LearnableMoves { &self.moves } pub fn flags(&self) -> &HashSet { @@ -90,7 +89,7 @@ impl<'a> Form<'a> { pub fn find_ability_index(&self, ability: &Ability) -> Option { for (index, a) in self.abilities.iter().enumerate() { - if std::ptr::eq(a.deref(), ability as *const Ability) { + if a == ability.name() { return Some(AbilityIndex { hidden: false, index: index as u8, @@ -98,7 +97,7 @@ impl<'a> Form<'a> { } } for (index, a) in self.hidden_abilities.iter().enumerate() { - if std::ptr::eq(a.deref(), ability as *const Ability) { + if a == ability.name() { return Some(AbilityIndex { hidden: true, index: index as u8, @@ -108,19 +107,19 @@ impl<'a> Form<'a> { None } - pub fn get_ability(&self, index: AbilityIndex) -> &Ability { + pub fn get_ability(&self, index: AbilityIndex) -> &StringKey { if index.hidden { - self.hidden_abilities[index.index as usize] + &self.hidden_abilities[index.index as usize] } else { - self.abilities[index.index as usize] + &self.abilities[index.index as usize] } } - pub fn get_random_ability(&self, rand: &mut Random) -> &Ability { - self.abilities[rand.get_between_unsigned(0, self.abilities.len() as u32) as usize] + pub fn get_random_ability(&self, rand: &mut Random) -> &StringKey { + &self.abilities[rand.get_between_unsigned(0, self.abilities.len() as u32) as usize] } - pub fn get_random_hidden_ability(&self, rand: &mut Random) -> &Ability { - self.hidden_abilities[rand.get_between_unsigned(0, self.hidden_abilities.len() as u32) as usize] + pub fn get_random_hidden_ability(&self, rand: &mut Random) -> &StringKey { + &self.hidden_abilities[rand.get_between_unsigned(0, self.hidden_abilities.len() as u32) as usize] } pub fn has_flag(&self, key: &StringKey) -> bool { diff --git a/src/static_data/species_data/learnable_moves.rs b/src/static_data/species_data/learnable_moves.rs index 71b169f..6e5ceb5 100644 --- a/src/static_data/species_data/learnable_moves.rs +++ b/src/static_data/species_data/learnable_moves.rs @@ -1,112 +1,73 @@ use crate::defines::LevelInt; -use crate::static_data::MoveData; +use crate::StringKey; use hashbrown::hash_map::Entry::{Occupied, Vacant}; use hashbrown::HashMap; #[derive(Default, PartialEq, Debug)] -pub struct LearnableMoves<'a> { - learned_by_level: HashMap>, - distinct_level_moves: Vec<&'a MoveData>, +pub struct LearnableMoves { + learned_by_level: HashMap>, + distinct_level_moves: Vec, } -impl<'a> LearnableMoves<'a> { - pub fn new() -> LearnableMoves<'a> { +impl LearnableMoves { + pub fn new() -> LearnableMoves { LearnableMoves::default() } - pub fn add_level_move(&mut self, level: LevelInt, m: &'a MoveData) { + pub fn add_level_move(&mut self, level: LevelInt, m: &StringKey) { match self.learned_by_level.entry(level) { Occupied(x) => { - x.into_mut().push(m); + x.into_mut().push(m.clone()); } Vacant(_) => { - self.learned_by_level.insert(level, vec![m]); + self.learned_by_level.insert(level, vec![m.clone()]); } } if !self.distinct_level_moves.contains(&m) { - self.distinct_level_moves.push(m); + self.distinct_level_moves.push(m.clone()); } } - pub fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<&'a MoveData>> { + pub fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec> { self.learned_by_level.get(&level) } - pub fn get_distinct_level_moves(&self) -> &Vec<&'a MoveData> { + pub fn get_distinct_level_moves(&self) -> &Vec { &self.distinct_level_moves } } #[cfg(test)] mod tests { - use crate::static_data::moves::move_data::{MoveCategory, MoveData, MoveTarget}; - use crate::static_data::moves::secondary_effect::SecondaryEffect; use crate::static_data::species_data::learnable_moves::LearnableMoves; #[test] fn adds_level_moves() { - let move1 = MoveData::new( - &"foo".into(), - 0, - MoveCategory::Physical, - 0, - 0, - 0, - MoveTarget::Adjacent, - 0, - SecondaryEffect::empty(), - Default::default(), - ); - let move2 = MoveData::new( - &"bar".into(), - 0, - MoveCategory::Physical, - 0, - 0, - 0, - MoveTarget::Adjacent, - 0, - SecondaryEffect::empty(), - Default::default(), - ); - let mut moves = LearnableMoves::new(); - moves.add_level_move(1, &move1); - moves.add_level_move(1, &move2); + moves.add_level_move(1, &"foo".into()); + moves.add_level_move(1, &"bar".into()); let m = moves.get_learned_by_level(1u8).unwrap(); assert_eq!(m.len(), 2); - assert_eq!(m[0], &move1); - assert_eq!(m[1], &move2); + assert_eq!(m[0], "foo".into()); + assert_eq!(m[1], "bar".into()); } #[test] fn adds_two_same_moves_at_different_level() { - let move1 = MoveData::new( - &"foo".into(), - 0, - MoveCategory::Physical, - 0, - 0, - 0, - MoveTarget::Adjacent, - 0, - SecondaryEffect::empty(), - Default::default(), - ); let mut moves = LearnableMoves::new(); - moves.add_level_move(1, &move1); - moves.add_level_move(5, &move1); + moves.add_level_move(1, &"foo".into()); + moves.add_level_move(5, &"foo".into()); let m = moves.get_learned_by_level(1u8).unwrap(); assert_eq!(m.len(), 1); - assert_eq!(m[0], &move1); + assert_eq!(m[0], "foo".into()); let m2 = moves.get_learned_by_level(5u8).unwrap(); assert_eq!(m2.len(), 1); - assert_eq!(m2[0], &move1); + assert_eq!(m2[0], "foo".into()); let distinct = moves.get_distinct_level_moves(); assert_eq!(distinct.len(), 1); - assert_eq!(distinct[0], &move1); + assert_eq!(distinct[0], "foo".into()); } } diff --git a/src/static_data/species_data/species.rs b/src/static_data/species_data/species.rs index f8df3a6..0724eed 100644 --- a/src/static_data/species_data/species.rs +++ b/src/static_data/species_data/species.rs @@ -6,28 +6,28 @@ use hashbrown::{HashMap, HashSet}; use std::lazy::SyncLazy; #[derive(Debug)] -pub struct Species<'a> { +pub struct Species { id: u16, name: StringKey, gender_rate: f32, growth_rate: StringKey, capture_rate: u8, - forms: HashMap>, + forms: HashMap, flags: HashSet, } static DEFAULT_KEY: SyncLazy = SyncLazy::new(|| StringKey::new("default")); -impl<'a> Species<'a> { +impl Species { pub fn new( id: u16, name: &StringKey, gender_rate: f32, growth_rate: &StringKey, capture_rate: u8, - default_form: Form<'a>, + default_form: Form, flags: HashSet, - ) -> Species<'a> { + ) -> Species { let mut forms = HashMap::with_capacity(1); forms.insert_unique_unchecked(DEFAULT_KEY.clone(), default_form); Species { @@ -55,14 +55,14 @@ impl<'a> Species<'a> { pub fn capture_rate(&self) -> u8 { self.capture_rate } - pub fn forms(&self) -> &HashMap> { + pub fn forms(&self) -> &HashMap { &self.forms } pub fn flags(&self) -> &HashSet { &self.flags } - pub fn add_form(&mut self, id: StringKey, form: Form<'a>) { + pub fn add_form(&mut self, id: StringKey, form: Form) { self.forms.insert(id, form); } diff --git a/src/static_data/statistics.rs b/src/static_data/statistics.rs index 9b7c263..5045d3a 100644 --- a/src/static_data/statistics.rs +++ b/src/static_data/statistics.rs @@ -1,4 +1,8 @@ +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + #[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Statistic { HP, Attack, diff --git a/src/utils/string_key.rs b/src/utils/string_key.rs index 8faf1b0..1f9f2ee 100644 --- a/src/utils/string_key.rs +++ b/src/utils/string_key.rs @@ -1,4 +1,5 @@ use hashbrown::HashMap; +use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; use std::lazy::SyncLazy; use std::sync::{Arc, Mutex, Weak}; @@ -86,6 +87,12 @@ impl From<&str> for StringKey { } } +impl Display for StringKey { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(&*self.str) + } +} + const fn to_lower(c: u8) -> u8 { if c >= b'A' && c <= b'Z' { return c + (b'a' - b'A'); diff --git a/tests/common/data_getter.rs b/tests/common/data_getter.rs new file mode 100644 index 0000000..c6d45d4 --- /dev/null +++ b/tests/common/data_getter.rs @@ -0,0 +1,22 @@ +use pkmn_lib::dynamic_data::models::battle::Battle; +use serde::Deserialize; + +#[derive(Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum TestDataGetter { + PokemonHealth { index: [u8; 2] }, +} + +impl TestDataGetter { + pub fn get(&self, battle: &Battle) -> String { + match self { + TestDataGetter::PokemonHealth { index } => battle + .get_pokemon(index[0], index[1]) + .as_ref() + .unwrap() + .read() + .current_health() + .to_string(), + } + } +} diff --git a/tests/common/library_loader.rs b/tests/common/library_loader.rs new file mode 100644 index 0000000..52a2bd3 --- /dev/null +++ b/tests/common/library_loader.rs @@ -0,0 +1,400 @@ +use hashbrown::HashSet; +use num_traits::PrimInt; +use pkmn_lib::defines::LevelInt; +use pkmn_lib::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator; +use pkmn_lib::dynamic_data::libraries::damage_library::Gen7DamageLibrary; +use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary; +use pkmn_lib::dynamic_data::libraries::misc_library::Gen7MiscLibrary; +use pkmn_lib::static_data::{ + Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, Item, + ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, Nature, NatureLibrary, + SecondaryEffect, Species, StaticData, Statistic, StatisticSet, TypeLibrary, +}; +use pkmn_lib::StringKey; +use project_root::get_project_root; +use serde_json::Value; +use std::convert::TryFrom; +use std::fmt::Debug; +use std::fs::File; +use std::io::Read; + +pub fn load_library() -> DynamicLibrary { + let mut path = get_project_root().unwrap(); + path.push("tests/data/"); + let path = path.to_str().unwrap().to_string(); + let mut data = StaticData::new(LibrarySettings::new(100)); + load_types(&path, data.types_mut()); + load_natures(&path, data.natures_mut()); + load_items(&path, data.items_mut()); + load_growth_rates(&path, data.growth_rates_mut()); + load_abilities(&path, data.abilities_mut()); + load_moves(&path, &mut data); + load_species(&path, &mut data); + let dynamic = DynamicLibrary::new( + data, + BattleStatCalculator {}, + Box::new(Gen7DamageLibrary::new(false)), + Box::new(Gen7MiscLibrary::new()), + ); + dynamic +} + +pub fn load_types(path: &String, type_library: &mut TypeLibrary) { + let mut reader = csv::ReaderBuilder::new() + .delimiter(b'|') + .from_path(path.to_string() + "Types.csv") + .unwrap(); + let headers = reader.headers().unwrap(); + for header in headers.iter().skip(1) { + type_library.register_type(&StringKey::new(header.clone())); + } + + for record in reader.records() { + let record = record.unwrap(); + let offensive_type = record.get(0).unwrap(); + let offensive_type_id = type_library.get_type_id(&StringKey::new(offensive_type.clone())); + + for (i, v) in record.iter().skip(1).enumerate() { + let effectiveness = v.parse::().unwrap(); + type_library.set_effectiveness(offensive_type_id, i as u8, effectiveness); + } + } +} + +pub fn load_natures(path: &String, nature_library: &mut NatureLibrary) { + let mut reader = csv::ReaderBuilder::new() + .delimiter(b'|') + .from_path(path.to_string() + "Natures.csv") + .unwrap(); + + for record in reader.records() { + let record = record.unwrap(); + let nature_name = StringKey::new(record.get(0).unwrap()); + let increased_statistic_str = record.get(1).unwrap(); + let decreased_statistic_str = record.get(2).unwrap(); + if increased_statistic_str.is_empty() || decreased_statistic_str.is_empty() { + nature_library.load_nature(nature_name, Nature::new(Statistic::HP, Statistic::HP, 1.0, 1.0)); + } else { + let increased_statistic = serde_plain::from_str(increased_statistic_str).unwrap(); + let decreased_statistic = serde_plain::from_str(decreased_statistic_str).unwrap(); + nature_library.load_nature( + nature_name, + Nature::new(increased_statistic, decreased_statistic, 1.1, 0.9), + ); + } + } +} + +pub fn load_items(path: &String, lib: &mut ItemLibrary) { + let mut file = File::open(path.to_string() + "Items.json").unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); + let json: Value = serde_json::from_str(&data).unwrap(); + let json_array = json.as_array().unwrap(); + + for v in json_array { + let name = StringKey::new(v["name"].as_str().unwrap()); + let category = serde_json::from_value(v["itemType"].clone()).unwrap(); + let mut battle_category = BattleItemCategory::None; + if let Some(c) = v.get("battleType") { + battle_category = serde_json::from_value(c.clone()).unwrap(); + } + let price = v["price"].as_i64().unwrap(); + let mut flags = HashSet::new(); + if let Some(f) = v.get("flags") { + let a = f.as_array().unwrap(); + for flag in a { + flags.insert(StringKey::new(flag.as_str().unwrap())); + } + } + + lib.add( + &name, + Box::new(Item::new(&name, category, battle_category, price as i32, flags)), + ); + } +} + +pub fn load_growth_rates(path: &String, growth_rate_library: &mut GrowthRateLibrary) { + let mut file = File::open(path.to_string() + "GrowthRates.json").unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); + let json: Value = serde_json::from_str(&data).unwrap(); + let o = json.as_object().unwrap(); + + for (key, value) in o { + let name = StringKey::new(key); + let experience_required_json = value.as_array().unwrap(); + let mut experience_required = Vec::with_capacity(experience_required_json.len()); + for v in experience_required_json { + experience_required.push(v.as_i64().unwrap() as u32); + } + + growth_rate_library.add_growth_rate(&name, Box::new(LookupGrowthRate::new(experience_required))); + } +} + +pub fn load_abilities(path: &String, ability_library: &mut AbilityLibrary) { + let mut file = File::open(path.to_string() + "Abilities.json").unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); + let json: Value = serde_json::from_str(&data).unwrap(); + let o = json.as_object().unwrap(); + + for (key, value) in o { + let name = StringKey::new(key); + let mut effect = StringKey::empty(); + if let Some(e) = value.get("effect") { + effect = StringKey::new(e.as_str().unwrap()); + } + let mut parameters = Vec::new(); + if let Some(p) = value.get("parameters") { + for par in p.as_array().unwrap() { + parameters.push(parse_effect_parameter(par)); + } + } + + ability_library.add(&name, Box::new(Ability::new(&name, &effect, parameters))); + } +} + +pub fn load_moves(path: &String, lib: &mut StaticData) { + let mut file = File::open(path.to_string() + "Moves.json").unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); + let json: Value = serde_json::from_str(&data).unwrap(); + let data = json.as_object().unwrap().get("data").unwrap().as_array().unwrap(); + for move_data in data { + let move_data = move_data.as_object().unwrap(); + let move_name = StringKey::new(move_data["name"].as_str().unwrap().clone()); + let move_type = StringKey::new(move_data["type"].as_str().unwrap()); + let move_type_id = lib.types().get_type_id(&move_type); + let move_category = serde_json::from_value(move_data["category"].clone()).unwrap(); + let base_power = move_data["power"].as_i64().unwrap() as u8; + let accuracy = move_data["accuracy"].as_i64().unwrap() as u8; + let pp = move_data["pp"].as_i64().unwrap() as u8; + let target = serde_json::from_value(move_data["target"].clone()).unwrap(); + let priority = move_data["priority"].as_i64().unwrap() as i8; + let secondary_effect = if let Some(v) = move_data.get("effect") { + let mut chance = -1.0; + if let Some(chance_value) = v.get("chance") { + chance = chance_value.as_f64().unwrap() as f32; + } + let mut parameters = Vec::new(); + if let Some(pars) = v.get("parameters") { + let pars = pars.as_array().unwrap(); + for par in pars { + parameters.push(parse_effect_parameter(par)); + } + } + + SecondaryEffect::new(chance, StringKey::new(v["name"].as_str().unwrap().clone()), parameters) + } else { + SecondaryEffect::empty() + }; + + let mut flags = HashSet::new(); + if let Some(f) = move_data.get("flags") { + let f = f.as_array().unwrap(); + for flag in f { + flags.insert(StringKey::new(flag.as_str().unwrap())); + } + } + + lib.moves_mut().add( + &move_name, + MoveData::new( + &move_name.clone(), + move_type_id, + move_category, + base_power, + accuracy, + pp, + target, + priority, + secondary_effect, + flags, + ), + ); + } +} + +pub fn load_species(path: &String, library: &mut StaticData) { + let mut file = File::open(path.to_string() + "Pokemon.json").unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); + let json: Value = serde_json::from_str(&data).unwrap(); + let o = json.as_object().unwrap(); + + for (key, value) in o { + if key.starts_with("$") { + continue; + } + let name = StringKey::new(key); + let id = value["id"].as_i64().unwrap(); + let gender_rate = value["genderRatio"].as_f64().unwrap(); + let growth_rate_name = StringKey::new(value["growthRate"].as_str().unwrap()); + let _base_happiness = value["baseHappiness"].as_i64().unwrap(); + let catch_rate = value["catchRate"].as_i64().unwrap(); + let _color = value["color"].as_str().unwrap(); + // let egg_groups = value["eggGroups"] + // .as_array() + // .unwrap() + // .iter() + // .map(|&a| a.as_str().unwrap()) + // .collect(); + let _egg_cycle = value["eggCycles"].as_i64().unwrap(); + // TODO: tags + // TODO: evolutions + + let forms = value["formes"].as_object().unwrap(); + let default_form_value = &forms["default"]; + let default_form = parse_form("default".into(), default_form_value, library); + + let mut species = Box::new(Species::new( + id as u16, + &name, + gender_rate as f32, + &growth_rate_name, + catch_rate as u8, + default_form, + Default::default(), + )); + library.species_mut().add(&name, species); + } +} + +fn parse_form(name: StringKey, value: &Value, library: &mut StaticData) -> Form { + let mut abilities = Vec::new(); + for a in value["abilities"].as_array().unwrap() { + abilities.push(StringKey::new(a.as_str().unwrap())); + } + let mut hidden_abilities = Vec::new(); + for a in value["hiddenAbilities"].as_array().unwrap() { + hidden_abilities.push(StringKey::new(a.as_str().unwrap())); + } + let base_stats = parse_statistics(&value["baseStats"]); + // TODO: ev reward + let height = value["height"].as_f64().unwrap(); + let weight = value["weight"].as_f64().unwrap(); + let base_experience = value["baseExp"].as_u64().unwrap(); + let types = value["types"] + .as_array() + .unwrap() + .iter() + .map(|a| library.types().get_type_id(&StringKey::new(a.as_str().unwrap()))) + .collect(); + + let moves = parse_moves(&value["moves"], library.moves()); + + Form::new( + &name, + height as f32, + weight as f32, + base_experience as u32, + types, + base_stats, + abilities, + hidden_abilities, + moves, + Default::default(), + ) +} + +fn parse_statistics(value: &Value) -> StatisticSet +where + T: PrimInt + TryFrom, + >::Error: Debug, +{ + StatisticSet::new( + >::try_from(value.get("hp").unwrap_or(&Value::Number(0.into())).as_u64().unwrap()).unwrap(), + >::try_from( + value + .get("attack") + .unwrap_or(&Value::Number(0.into())) + .as_u64() + .unwrap(), + ) + .unwrap(), + >::try_from( + value + .get("defense") + .unwrap_or(&Value::Number(0.into())) + .as_u64() + .unwrap(), + ) + .unwrap(), + >::try_from( + value + .get("specialAttack") + .unwrap_or(&Value::Number(0.into())) + .as_u64() + .unwrap(), + ) + .unwrap(), + >::try_from( + value + .get("specialDefense") + .unwrap_or(&Value::Number(0.into())) + .as_u64() + .unwrap(), + ) + .unwrap(), + >::try_from(value.get("speed").unwrap_or(&Value::Number(0.into())).as_u64().unwrap()) + .unwrap(), + ) +} + +fn parse_moves(value: &Value, move_library: &MoveLibrary) -> LearnableMoves { + let mut moves = LearnableMoves::default(); + + let level_moves = value["levelMoves"].as_array().unwrap(); + for level_move in level_moves { + let name = StringKey::new(level_move["name"].as_str().unwrap()); + let level = level_move["level"].as_u64().unwrap() as LevelInt; + assert!(move_library.get(&name).is_some()); + moves.add_level_move(level, &name); + } + + moves +} + +fn parse_effect_parameter(value: &Value) -> EffectParameter { + match value { + Value::Null => { + panic!("Unexpected type") + } + Value::Bool(b) => EffectParameter::Bool(*b), + Value::Number(n) => { + if n.is_f64() { + EffectParameter::Float(n.as_f64().unwrap() as f32) + } else { + EffectParameter::Int(n.as_i64().unwrap()) + } + } + Value::String(s) => EffectParameter::String(s.clone()), + Value::Array(_) => { + panic!("Unexpected type") + } + Value::Object(_) => { + panic!("Unexpected type") + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] +fn test_type_library_loaded() { + let mut path = get_project_root().unwrap(); + path.push("tests/data/"); + let mut lib = TypeLibrary::new(18); + load_types(&path.to_str().unwrap().to_string(), &mut lib); + + assert_eq!( + lib.get_effectiveness( + lib.get_type_id(&StringKey::new("fire")), + &vec![lib.get_type_id(&StringKey::new("grass"))], + ), + 2.0 + ); +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..ea7572b --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,9 @@ +pub mod data_getter; +pub mod library_loader; +pub mod test_case; +pub mod test_step; + +pub use data_getter::*; +pub use library_loader::*; +pub use test_case::*; +pub use test_step::*; diff --git a/tests/common/test_case.rs b/tests/common/test_case.rs new file mode 100644 index 0000000..f7a15ac --- /dev/null +++ b/tests/common/test_case.rs @@ -0,0 +1,82 @@ +use super::test_step::TestStep; +use parking_lot::RwLock; +use pkmn_lib::defines::LevelInt; +use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary; +use pkmn_lib::dynamic_data::models::battle::Battle; +use pkmn_lib::dynamic_data::models::battle_party::BattleParty; +use pkmn_lib::dynamic_data::models::pokemon::Pokemon; +use pkmn_lib::dynamic_data::models::pokemon_builder::PokemonBuilder; +use pkmn_lib::dynamic_data::models::pokemon_party::PokemonParty; +use pkmn_lib::StringKey; +use serde::Deserialize; +use std::sync::Arc; + +#[derive(Deserialize)] +pub struct TestCase { + pub name: String, + battle_setup: TestBattleSetup, + actions: Vec, +} + +#[derive(Deserialize)] +struct TestBattleSetup { + seed: u128, + can_flee: bool, + number_of_sides: u8, + pokemon_per_side: u8, + parties: Vec, +} + +#[derive(Deserialize)] +struct TestParty { + indices: Vec<[u8; 2]>, + pokemon: Vec, +} + +#[derive(Deserialize)] +struct TestPokemon { + species: String, + level: LevelInt, + moves: Vec, +} + +impl TestCase { + pub fn run_test(&self, library: &DynamicLibrary) { + let mut parties = Vec::new(); + for party in &self.battle_setup.parties { + let pokemon = party + .pokemon + .iter() + .map(|a| Some(Arc::new(RwLock::new(a.to_pokemon(library))))) + .collect(); + let indices = party.indices.iter().map(|a| (a[0], a[1])).collect(); + parties.push((Arc::new(PokemonParty::new_from_vec(pokemon)), indices)); + } + let mut battle_parties = Vec::new(); + for party in parties { + battle_parties.push(BattleParty::new(party.0.clone(), party.1)); + } + let mut battle = Battle::new( + library, + battle_parties, + self.battle_setup.can_flee, + self.battle_setup.number_of_sides, + self.battle_setup.pokemon_per_side, + Some(self.battle_setup.seed), + ); + for action in &self.actions { + action.execute(&mut battle); + } + } +} + +impl TestPokemon { + fn to_pokemon<'a>(&'a self, library: &'a DynamicLibrary) -> Pokemon { + let mut builder = PokemonBuilder::new(library, StringKey::new(self.species.as_str()), self.level); + for move_name in &self.moves { + builder = builder.learn_move(StringKey::new(move_name)); + } + + builder.build() + } +} diff --git a/tests/common/test_step.rs b/tests/common/test_step.rs new file mode 100644 index 0000000..fe5fbc6 --- /dev/null +++ b/tests/common/test_step.rs @@ -0,0 +1,82 @@ +use super::data_getter::TestDataGetter; +use pkmn_lib::dynamic_data::choices::{MoveChoice, PassChoice, TurnChoice}; +use pkmn_lib::dynamic_data::models::battle::Battle; +use pkmn_lib::StringKey; +use serde::Deserialize; + +#[derive(Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum TestStep { + SetPokemon { + place: [u8; 2], + from_party: [u8; 2], + }, + SetMoveChoice { + #[serde(rename = "for")] + for_pokemon: [u8; 2], + #[serde(rename = "move")] + use_move: String, + target: [u8; 2], + }, + SetPassChoice { + #[serde(rename = "for")] + for_pokemon: [u8; 2], + }, + Assert { + value: TestDataGetter, + expected: String, + }, +} + +impl TestStep { + pub fn execute(&self, battle: &mut Battle) { + match self { + TestStep::SetPokemon { place, from_party } => { + let p = battle.parties()[from_party[0] as usize] + .get_pokemon(from_party[1] as usize) + .clone(); + battle.sides_mut()[place[0] as usize].set_pokemon(place[1], p); + } + TestStep::SetMoveChoice { + for_pokemon, + use_move, + target, + } => { + let p = battle.sides()[for_pokemon[0] as usize].pokemon()[for_pokemon[1] as usize] + .as_ref() + .unwrap() + .clone(); + let mut used_move = None; + let pokemon_guard = p.read(); + for learned_move in pokemon_guard.learned_moves().iter().flatten() { + if learned_move.read().move_data().name() == &StringKey::new(use_move) { + used_move = Some(learned_move.clone()); + break; + } + } + assert!(used_move.is_some()); + drop(pokemon_guard); + + assert!(battle + .try_set_choice(TurnChoice::Move(MoveChoice::new( + p, + used_move.unwrap(), + target[0], + target[1], + ))) + .unwrap()); + } + TestStep::SetPassChoice { for_pokemon } => { + let p = battle.sides()[for_pokemon[0] as usize].pokemon()[for_pokemon[1] as usize] + .as_ref() + .unwrap() + .clone(); + assert!(battle.try_set_choice(TurnChoice::Pass(PassChoice::new(p))).unwrap()); + } + TestStep::Assert { value, expected } => { + let v = value.get(battle); + assert_eq!(&v, expected) + } + } + } +} diff --git a/tests/data/Items.json b/tests/data/Items.json index 1016c06..38a3e1e 100644 --- a/tests/data/Items.json +++ b/tests/data/Items.json @@ -1,56 +1,56 @@ [ { "name": "ability_capsule", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "ability_urge", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "abomasite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "absolite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "absorb_bulb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "acro_bike", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "adamant_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 60 }, { "name": "adrenaline_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "battleType": "MiscBattleItem", "flags": [], "price": 300, @@ -58,91 +58,91 @@ }, { "name": "adventure_rules", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "aerodactylite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "aggronite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "aguav_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "air_balloon", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "air_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "alakazite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "aloraichium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "altarianite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "amaze_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "ampharosite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "amulet_coin", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "antidote", - "itemType": "medicine", + "itemType": "Medicine", "battleType": "StatusHealing", "flags": [], "price": 200, @@ -150,35 +150,35 @@ }, { "name": "apicot_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "apricorn_box", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "aqua_suit", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "armor_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "aspear_berry", - "itemType": "berry", + "itemType": "Berry", "battleType": "StatusHealing", "flags": [], "price": 20, @@ -186,28 +186,28 @@ }, { "name": "assault_vest", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 80 }, { "name": "audinite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "auroraticket", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "awakening", - "itemType": "medicine", + "itemType": "Medicine", "battleType": "StatusHealing", "flags": [], "price": 100, @@ -215,49 +215,49 @@ }, { "name": "azure_flute", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "babiri_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "balm_mushroom", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 15000, "flingPower": 30 }, { "name": "banettite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "basement_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "bead_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "beast_ball", - "itemType": "pokeball", + "itemType": "Pokeball", "battleType": "Pokeball", "flags": [], "price": -1, @@ -265,21 +265,21 @@ }, { "name": "beedrillite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "belue_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "berry_juice", - "itemType": "medicine", + "itemType": "Medicine", "battleType": "Healing", "flags": [], "price": 200, @@ -287,28 +287,28 @@ }, { "name": "berry_pots", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "berry_pouch", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "bicycle", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "big_malasada", - "itemType": "medicine", + "itemType": "Medicine", "battleType": "StatusHealing", "flags": [], "price": 350, @@ -316,119 +316,119 @@ }, { "name": "big_mushroom", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 30 }, { "name": "big_nugget", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 40000, "flingPower": 30 }, { "name": "big_pearl", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 8000, "flingPower": 30 }, { "name": "big_root", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "bike_voucher", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "binding_band", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "black_apricorn", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 20, "flingPower": 0 }, { "name": "black_belt", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "black_flute", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 20, "flingPower": 30 }, { "name": "black_glasses", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "black_sludge", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "blastoisinite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "blazikenite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "bloom_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "blue_apricorn", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 20, "flingPower": 0 }, { "name": "blue_card", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "blue_flute", - "itemType": "miscitem", + "itemType": "MiscItem", "battleType": "StatusHealing", "flags": [], "price": 20, @@ -436,133 +436,133 @@ }, { "name": "blue_orb", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "blue_scarf", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 10 }, { "name": "blue_shard", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "bluk_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "boost_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "bottle_cap", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 30 }, { "name": "brick_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "bridge_mail_d", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "bridge_mail_m", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "bridge_mail_s", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "bridge_mail_t", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "bridge_mail_v", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "bright_powder", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "bubble_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "bug_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "bug_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "buginium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "burn_drive", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 70 }, { "name": "burn_heal", - "itemType": "medicine", + "itemType": "Medicine", "battleType": "StatusHealing", "flags": [], "price": 300, @@ -570,86 +570,86 @@ }, { "name": "calcium", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "cameruptite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "carbos", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "card_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "casteliacone", - "itemType": "medicine", - "battleType":"StatusHealing", + "itemType": "Medicine", + "battleType": "StatusHealing", "flags": [], "price": 350, "flingPower": 30 }, { "name": "cell_battery", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "charcoal", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "charizardite_x", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "charizardite_y", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "charti_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "cheri_berry", - "itemType": "berry", - "battleType":"StatusHealing", + "itemType": "Berry", + "battleType": "StatusHealing", "flags": [], "price": 20, "flingPower": 10 }, { "name": "cherish_ball", - "itemType": "pokeball", + "itemType": "Pokeball", "battleType": "Pokeball", "flags": [], "price": -1, @@ -657,389 +657,389 @@ }, { "name": "chesto_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "chilan_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "chill_drive", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 70 }, { "name": "choice_band", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "choice_scarf", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "choice_specs", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "chople_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "claw_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "cleanse_tag", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 30 }, { "name": "clear_bell", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "clever_wing", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 20 }, { "name": "coba_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "coin_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "colbur_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "colress_machine", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "comet_shard", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 60000, "flingPower": 30 }, { "name": "common_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "contest_costume__jacket", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "contest_pass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "cornn_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "coupon_1", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "coupon_2", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "coupon_3", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "cover_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "custap_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "damp_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "damp_rock", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 60 }, { "name": "dark_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "dark_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "dark_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "darkinium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "dawn_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 80 }, { "name": "decidium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "deep_sea_scale", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "deep_sea_tooth", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 90 }, { "name": "destiny_knot", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "diancite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "dire_hit", - "itemType": "miscitem", - "battleType":"MiscBattleItem", + "itemType": "MiscItem", + "battleType": "MiscBattleItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "dire_hit_2", - "itemType": "miscitem", - "battleType":"MiscBattleItem", + "itemType": "MiscItem", + "battleType": "MiscBattleItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "dire_hit_3", - "itemType": "miscitem", - "battleType":"MiscBattleItem", + "itemType": "MiscItem", + "battleType": "MiscBattleItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "discount_coupon", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 20, "flingPower": 10 }, { "name": "dive_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "dna_splicers", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "dome_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "douse_drive", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 70 }, { "name": "dowsing_machine", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "draco_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "dragon_fang", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 70 }, { "name": "dragon_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "dragon_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "dragon_scale", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "dragon_skull", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "dragonium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "dread_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "dream_ball", - "itemType": "pokeball", + "itemType": "Pokeball", "battleType": "Pokeball", "flags": [], "price": -1, @@ -1047,179 +1047,179 @@ }, { "name": "dream_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "dropped_item", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "dubious_disc", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 50 }, { "name": "durin_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "dusk_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "dusk_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 80 }, { "name": "earth_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "eevium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "eject_button", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "electirizer", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 80 }, { "name": "electric_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "electric_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "electric_seed", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "electrium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "elevator_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "elixir", - "itemType": "medicine", - "battleType":"Healing", + "itemType": "Medicine", + "battleType": "Healing", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "energy_powder", - "itemType": "medicine", - "battleType":"Healing", + "itemType": "Medicine", + "battleType": "Healing", "flags": [], "price": 500, "flingPower": 30 }, { "name": "energy_root", - "itemType": "medicine", - "battleType":"Healing", + "itemType": "Medicine", + "battleType": "Healing", "flags": [], "price": 1200, "flingPower": 30 }, { "name": "enigma_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "enigma_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "enigmatic_card", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "eon_flute", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "eon_ticket", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "escape_rope", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "ether", - "itemType": "medicine", + "itemType": "Medicine", "battleType": "Healing", "flags": [], "price": 1200, @@ -1227,4685 +1227,4689 @@ }, { "name": "everstone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "eviolite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 40 }, { "name": "exp_share", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "expert_belt", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "explorer_kit", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "fab_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "fairium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "fairy_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "fairy_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "fame_checker", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "fashion_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "fast_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "favored_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "festival_ticket", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 10, "flingPower": 0 }, { "name": "fighting_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "fighting_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "fightinium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "figy_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "fire_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "fire_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "fire_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "firium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "fishing_rod", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "fist_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "flame_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "flame_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "flame_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "float_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "fluffy_tail", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 30 }, { "name": "flying_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "flying_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "flyinium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "focus_band", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "focus_sash", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "forage_bag", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "fresh_water", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 200, "flingPower": 30 }, { "name": "friend_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "full_heal", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 400, "flingPower": 30 }, { "name": "full_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 10 }, { "name": "full_restore", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "galactic_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "galladite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "ganlon_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "garchompite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "gardevoirite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "gb_sounds", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "gengarite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "genius_wing", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 20 }, { "name": "ghost_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "ghost_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "ghostium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "glalitite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "glitter_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "go_goggles", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "god_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "gold_bottle_cap", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "gold_teeth", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "good_rod", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "gooey_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "gracidea", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "gram_1", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "gram_2", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "gram_3", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "grass_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "grass_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "grass_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "grassium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "grassy_seed", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "great_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 600, "flingPower": 0 }, { "name": "green_apricorn", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 20, "flingPower": 0 }, { "name": "green_scarf", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 10 }, { "name": "green_shard", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "greet_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "grepa_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "grip_claw", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 90 }, { "name": "griseous_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 60 }, { "name": "ground_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "ground_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "groundium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "growth_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "grubby_hanky", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "guard_spec", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1500, "flingPower": 30 }, { "name": "gyaradosite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "haban_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "harbor_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "hard_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 100 }, { "name": "heal_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 300, "flingPower": 0 }, { "name": "heal_powder", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 30 }, { "name": "health_wing", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 20 }, { "name": "heart_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "heart_scale", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 30 }, { "name": "heat_rock", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 60 }, { "name": "heavy_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "helix_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "heracronite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "hm01", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hm02", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hm03", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hm04", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hm05", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hm06", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hm07", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hm08", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": -1, "flingPower": 0 }, { "name": "holo_caster", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "hondew_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "honey", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 300, "flingPower": 30 }, { "name": "honor_of_kalos", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "houndoominite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "hp_up", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "hyper_potion", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 1500, "flingPower": 30 }, { "name": "iapapa_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "ice_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "ice_heal", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 100, "flingPower": 30 }, { "name": "ice_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "ice_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "icicle_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "icium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "icy_rock", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 40 }, { "name": "incinium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "inquiry_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "insect_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "intriguing_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "iron", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "iron_ball", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 130 }, { "name": "iron_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "item_drop", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "item_urge", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "jaboca_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "jade_orb", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "jaw_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "journal", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "kangaskhanite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "kasib_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "kebia_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "kee_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "kelpsy_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "key_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "key_to_room_1", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "key_to_room_2", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "key_to_room_4", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "key_to_room_6", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "kings_rock", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 30 }, { "name": "lagging_tail", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "lansat_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "latiasite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "latiosite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "lava_cookie", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 350, "flingPower": 30 }, { "name": "lax_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 10 }, { "name": "leaf_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "leftovers", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "lemonade", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 400, "flingPower": 30 }, { "name": "lens_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "leppa_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "letter", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "level_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "liberty_pass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "liechi_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "life_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "lift_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "light_ball", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "light_clay", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "light_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "like_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "lock_capsule", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "looker_ticket", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "loot_sack", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "lopunnite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "lost_item", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "love_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "lucarionite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "luck_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 11000, "flingPower": 10 }, { "name": "lucky_egg", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "lucky_punch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 40 }, { "name": "lum_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "luminous_moss", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "lumiose_galette", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 350, "flingPower": 30 }, { "name": "lunar_wing", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "lure_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "lustrous_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 60 }, { "name": "luxury_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "mach_bike", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "machine_part", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "macho_brace", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 60 }, { "name": "magma_emblem", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "magma_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "magma_suit", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "magmarizer", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 80 }, { "name": "magnet", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "mago_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "magost_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "makeup_bag", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "manectite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "maranga_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "marshadium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "master_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mawilite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "max_elixir", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 4500, "flingPower": 30 }, { "name": "max_ether", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "max_potion", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 2500, "flingPower": 30 }, { "name": "max_repel", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 900, "flingPower": 30 }, { "name": "max_revive", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "meadow_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "mech_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "medal_box", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "medichamite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "mega_anchor", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_anklet", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_bracelet", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_charm", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_cuff", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_glasses", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_glove", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_pendant", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_ring", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_stickpin", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mega_tiara", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "member_card", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mental_herb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "metagrossite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "metal_coat", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "metal_powder", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 10 }, { "name": "meteorite", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "meteorite_shard", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "metronome", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "mewnium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mewtwonite_x", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "mewtwonite_y", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "micle_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "mind_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "miracle_seed", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "misty_seed", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "moomoo_milk", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 600, "flingPower": 30 }, { "name": "moon_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "moon_flute", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "moon_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "mosaic_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "muscle_band", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "muscle_wing", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 20 }, { "name": "mystery_egg", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "mystic_water", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "mysticticket", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "nanab_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "nest_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "net_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "never_melt_ice", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "nomel_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "normal_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 0 }, { "name": "normalium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "nugget", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "oaks_letter", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "oaks_parcel", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "occa_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "odd_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 10 }, { "name": "odd_keystone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2100, "flingPower": 80 }, { "name": "old_amber", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 10000, "flingPower": 100 }, { "name": "old_charm", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "old_gateau", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 350, "flingPower": 30 }, { "name": "old_rod", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "old_sea_map", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "oran_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "orange_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "oval_charm", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "oval_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 80 }, { "name": "pair_of_tickets", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pal_pad", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pamtre_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "paralyze_heal", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 30 }, { "name": "parcel", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "park_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pass_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "passho_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "payapa_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "pearl", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "pearl_string", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 30000, "flingPower": 30 }, { "name": "pecha_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "permit", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "persim_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "petaya_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "photo_album", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pidgeotite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "pikanium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pikashunium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pinap_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "pink_apricorn", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 20, "flingPower": 0 }, { "name": "pink_nectar", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 300, "flingPower": 10 }, { "name": "pink_scarf", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 10 }, { "name": "pinsirite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "pixie_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "plasma_card", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "plume_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "poffin_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "point_card", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "poison_barb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 70 }, { "name": "poison_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "poison_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "poisonium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "poke_ball", - "itemType": "pokeball", + "itemType": "Pokeball", "battleType": "Pokeball", "flags": [], "price": 200, "flingPower": 0, "battleEffect": { - "name": "pokeball", - "parameters": [1.0] + "name": "Pokeball", + "parameters": [ + 1.0 + ] } }, { "name": "poke_doll", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 30 }, { "name": "poke_flute", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "poke_radar", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "poke_toy", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 30 }, { "name": "pokeblock_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pokeblock_kit", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pomeg_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "potion", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 200, "flingPower": 30, "effect": { "name": "heal", - "parameters": [20] + "parameters": [ + 20 + ] } }, { "name": "powder_jar", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "power_anklet", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 70 }, { "name": "power_band", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 70 }, { "name": "power_belt", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 70 }, { "name": "power_bracer", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 70 }, { "name": "power_herb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "power_lens", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 70 }, { "name": "power_plant_pass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "power_weight", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 70 }, { "name": "pp_max", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "pp_up", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "premier_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 20, "flingPower": 0 }, { "name": "pretty_wing", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 20 }, { "name": "primarium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "prism_scale", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "prison_bottle", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "professors_mask", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "profs_letter", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "prop_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "protective_pads", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "protector", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 80 }, { "name": "protein", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "psychic_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "psychic_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "psychic_seed", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "psychium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "pure_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 6000, "flingPower": 10 }, { "name": "purple_nectar", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 300, "flingPower": 10 }, { "name": "qualot_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "quick_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "quick_claw", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 80 }, { "name": "quick_powder", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 10 }, { "name": "rabuta_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "rage_candy_bar", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 350, "flingPower": 30 }, { "name": "rainbow_pass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rainbow_wing", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rare_bone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 100 }, { "name": "rare_candy", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "rawst_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "razor_claw", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 80 }, { "name": "razor_fang", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 5000, "flingPower": 30 }, { "name": "razz_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "reaper_cloth", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 10 }, { "name": "red_apricorn", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 20, "flingPower": 0 }, { "name": "red_card", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "red_chain", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "red_flute", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 20, "flingPower": 30 }, { "name": "red_nectar", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 300, "flingPower": 10 }, { "name": "red_orb", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "red_scale", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "red_scarf", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 10 }, { "name": "red_shard", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "relic_band", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 30 }, { "name": "relic_copper", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 30 }, { "name": "relic_crown", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 30 }, { "name": "relic_gold", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 60000, "flingPower": 30 }, { "name": "relic_silver", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 30 }, { "name": "relic_statue", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 30 }, { "name": "relic_vase", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 30 }, { "name": "repeat_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "repel", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 400, "flingPower": 30 }, { "name": "reply_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "reset_urge", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "resist_wing", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 20 }, { "name": "retro_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": -1, "flingPower": 0 }, { "name": "reveal_glass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "revival_herb", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 2800, "flingPower": 30 }, { "name": "revive", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "rich_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "ride_pager", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rindo_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "ring_target", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "rm_1_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rm_2_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rm_4_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rm_6_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rock_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "rock_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 10 }, { "name": "rock_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "rockium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rocky_helmet", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 60 }, { "name": "roller_skates", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "root_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "rose_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 10 }, { "name": "roseli_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "rowap_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "rsvp_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "ruby", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "rule_book", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "running_shoes", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "sablenite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "sachet", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 80 }, { "name": "sacred_ash", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 50000, "flingPower": 30 }, { "name": "safari_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": -1, "flingPower": 0 }, { "name": "safety_goggles", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 80 }, { "name": "sail_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "salac_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "salamencite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "sapphire", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "scanner", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "sceptilite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "scizorite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "scope_lens", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "sea_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 10 }, { "name": "seal_bag", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "seal_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "secret_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "secret_potion", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "shadow_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "shalour_sable", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 350, "flingPower": 30 }, { "name": "sharp_beak", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "sharpedonite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "shed_shell", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "shell_bell", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "shiny_charm", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "shiny_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 80 }, { "name": "shoal_salt", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 20, "flingPower": 30 }, { "name": "shoal_shell", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 20, "flingPower": 30 }, { "name": "shock_drive", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 70 }, { "name": "shuca_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "silk_scarf", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 10 }, { "name": "silph_scope", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "silver_powder", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 10 }, { "name": "silver_wing", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "sitrus_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "skull_fossil", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 7000, "flingPower": 100 }, { "name": "sky_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "slowbronite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "slowpoke_tail", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "smoke_ball", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "smooth_rock", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "snorlium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "snow_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "snowball", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "soda_pop", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 30 }, { "name": "soft_sand", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 10 }, { "name": "soot_sack", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "soothe_bell", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "soul_dew", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 30 }, { "name": "space_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "sparkling_stone", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "spell_tag", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "spelon_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "splash_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "spooky_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "sport_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 300, "flingPower": 0 }, { "name": "sprayduck", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "sprinklotad", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "squirt_bottle", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "ss_ticket", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "stable_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "star_piece", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 12000, "flingPower": 30 }, { "name": "stardust", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "starf_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "steel_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "steel_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "steel_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "steelium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "steelixite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "stick", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 60 }, { "name": "sticky_barb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 80 }, { "name": "stone_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "storage_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "strange_souvenir", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "suite_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "sun_flute", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "sun_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "super_potion", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 700, "flingPower": 30 }, { "name": "super_repel", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 700, "flingPower": 30 }, { "name": "super_rod", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "surprise_mulch", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 30 }, { "name": "swampertite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "sweet_heart", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "swift_wing", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 300, "flingPower": 20 }, { "name": "tamato_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "tanga_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "tapunium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "tea", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "teachy_tv", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "terrain_extender", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 60 }, { "name": "thanks_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "thick_club", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "thunder_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "tidal_bell", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "timer_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 1000, "flingPower": 0 }, { "name": "tiny_mushroom", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 500, "flingPower": 30 }, { "name": "tm01", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm02", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm03", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm04", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm05", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm06", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm07", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 50000, "flingPower": 0 }, { "name": "tm08", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm09", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm10", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm100", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 5000, "flingPower": 0 }, { "name": "tm11", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 50000, "flingPower": 0 }, { "name": "tm12", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm13", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm14", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm15", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 50000, "flingPower": 0 }, { "name": "tm16", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm17", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm18", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 50000, "flingPower": 0 }, { "name": "tm19", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm20", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm21", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm22", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm23", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm24", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm25", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm26", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm27", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm28", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm29", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm30", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm31", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm32", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm33", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm34", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm35", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm36", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm37", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 50000, "flingPower": 0 }, { "name": "tm38", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm39", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm40", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm41", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm42", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm43", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm44", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm45", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm46", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm47", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm48", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm49", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm50", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 80000, "flingPower": 0 }, { "name": "tm51", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm52", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm53", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm54", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm55", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm56", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm57", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm58", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm59", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm60", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm61", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm62", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm63", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm64", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm65", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm66", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm67", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm68", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 50000, "flingPower": 0 }, { "name": "tm69", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm70", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm71", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm72", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm73", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 5000, "flingPower": 0 }, { "name": "tm74", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm75", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm76", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm77", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm78", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm79", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm80", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm81", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm82", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm83", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm84", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm85", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm86", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm87", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm88", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm89", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm90", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm91", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm92", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm93", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 50000, "flingPower": 0 }, { "name": "tm94", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm95", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm96", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm97", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm98", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 30000, "flingPower": 0 }, { "name": "tm99", - "itemType": "technicalMachine", + "itemType": "TMHM", "flags": [], "price": 10000, "flingPower": 0 }, { "name": "tm_case", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "tmv_pass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "town_map", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "toxic_orb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 30 }, { "name": "toxic_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "travel_trunk", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "tri_pass", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "tropic_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "tunnel_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "twisted_spoon", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "tyranitarite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "ultra_ball", - "itemType": "pokeball", - "battleType":"Pokeball", + "itemType": "Pokeball", + "battleType": "Pokeball", "flags": [], "price": 800, "flingPower": 0 }, { "name": "unown_report", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "up_grade", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "venusaurite", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 80 }, { "name": "vs_recorder", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "vs_seeker", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "wacan_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "wailmer_pail", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "water_gem", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 200, "flingPower": 0 }, { "name": "water_memory", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 50 }, { "name": "water_stone", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 3000, "flingPower": 30 }, { "name": "waterium_z", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "watmel_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "wave_incense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 10 }, { "name": "wave_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "weakness_policy", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 80 }, { "name": "wepear_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "whipped_dream", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 80 }, { "name": "white_apricorn", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 20, "flingPower": 0 }, { "name": "white_flute", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 20, "flingPower": 30 }, { "name": "white_herb", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "wide_lens", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "wiki_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "wise_glasses", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "wood_mail", - "itemType": "mail", + "itemType": "Mail", "flags": [], "price": 50, "flingPower": 0 }, { "name": "works_key", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_accuracy", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "x_accuracy_2", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_accuracy_3", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_accuracy_6", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_attack", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "x_attack_2", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_attack_3", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_attack_6", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_defense", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "x_defense_2", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_defense_3", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_defense_6", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_sp_atk", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "x_sp_atk_2", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_sp_atk_3", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_sp_atk_6", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_sp_def", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 2000, "flingPower": 30 }, { "name": "x_sp_def_2", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_sp_def_3", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_sp_def_6", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_speed", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "x_speed_2", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_speed_3", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "x_speed_6", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "xtransceiver", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "yache_berry", - "itemType": "berry", + "itemType": "Berry", "flags": [], "price": 20, "flingPower": 10 }, { "name": "yellow_apricorn", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": 20, "flingPower": 0 }, { "name": "yellow_flute", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 20, "flingPower": 30 }, { "name": "yellow_nectar", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 300, "flingPower": 10 }, { "name": "yellow_scarf", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 100, "flingPower": 10 }, { "name": "yellow_shard", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 30 }, { "name": "z_ring", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 }, { "name": "zap_plate", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 1000, "flingPower": 90 }, { "name": "zinc", - "itemType": "medicine", + "itemType": "Medicine", "flags": [], "price": 10000, "flingPower": 30 }, { "name": "zoom_lens", - "itemType": "miscitem", + "itemType": "MiscItem", "flags": [], "price": 4000, "flingPower": 10 }, { "name": "zygarde_cube", - "itemType": "keyItem", + "itemType": "KeyItem", "flags": [], "price": -1, "flingPower": 0 diff --git a/tests/library_loader.rs b/tests/library_loader.rs deleted file mode 100644 index d32175a..0000000 --- a/tests/library_loader.rs +++ /dev/null @@ -1,136 +0,0 @@ -use hashbrown::HashSet; -use pkmn_lib::static_data::{DataLibrary, EffectParameter, MoveData, MoveLibrary, SecondaryEffect, TypeLibrary}; -use pkmn_lib::StringKey; -use project_root::get_project_root; -use serde_json::Value; -use std::fs::File; -use std::io::Read; - -pub fn load_types(path: &String) -> TypeLibrary { - let mut type_library = TypeLibrary::new(18); - - let mut reader = csv::ReaderBuilder::new() - .delimiter(b'|') - .from_path(path.to_string() + "Types.csv") - .unwrap(); - let headers = reader.headers().unwrap(); - for header in headers.iter().skip(1) { - type_library.register_type(&StringKey::new(header.clone())); - } - - for record in reader.records() { - let record = record.unwrap(); - let offensive_type = record.get(0).unwrap(); - let offensive_type_id = type_library.get_type_id(&StringKey::new(offensive_type.clone())); - - for (i, v) in record.iter().skip(1).enumerate() { - let effectiveness = v.parse::().unwrap(); - type_library.set_effectiveness(offensive_type_id, i as u8, effectiveness); - } - } - - type_library -} - -pub fn load_moves(path: &String, type_library: &TypeLibrary) -> MoveLibrary { - let mut file = File::open(path.to_string() + "Moves.json").unwrap(); - let mut data = String::new(); - file.read_to_string(&mut data).unwrap(); - let json: Value = serde_json::from_str(&data).unwrap(); - let data = json.as_object().unwrap().get("data").unwrap().as_array().unwrap(); - let mut move_library = MoveLibrary::new(data.len()); - for move_data in data { - let move_data = move_data.as_object().unwrap(); - let move_name = StringKey::new(move_data["name"].as_str().unwrap().clone()); - let move_type = StringKey::new(move_data["type"].as_str().unwrap()); - let move_type_id = type_library.get_type_id(&move_type); - let move_category = serde_json::from_value(move_data["category"].clone()).unwrap(); - let base_power = move_data["power"].as_i64().unwrap() as u8; - let accuracy = move_data["accuracy"].as_i64().unwrap() as u8; - let pp = move_data["pp"].as_i64().unwrap() as u8; - let target = serde_json::from_value(move_data["target"].clone()).unwrap(); - let priority = move_data["priority"].as_i64().unwrap() as i8; - let secondary_effect = if let Some(v) = move_data.get("effect") { - let mut chance = -1.0; - if let Some(chance_value) = v.get("chance") { - chance = chance_value.as_f64().unwrap() as f32; - } - let mut parameters = Vec::new(); - if let Some(pars) = v.get("parameters") { - let pars = pars.as_array().unwrap(); - for par in pars { - match par { - Value::Null => { - panic!("Unexpected type") - } - Value::Bool(b) => { - parameters.push(EffectParameter::Bool(*b)); - } - Value::Number(n) => { - if n.is_f64() { - parameters.push(EffectParameter::Float(n.as_f64().unwrap() as f32)); - } else { - parameters.push(EffectParameter::Int(n.as_i64().unwrap())); - } - } - Value::String(s) => { - parameters.push(EffectParameter::String(s.clone())); - } - Value::Array(_) => { - panic!("Unexpected type") - } - Value::Object(_) => { - panic!("Unexpected type") - } - } - } - } - - SecondaryEffect::new(chance, StringKey::new(v["name"].as_str().unwrap().clone()), parameters) - } else { - SecondaryEffect::empty() - }; - - let mut flags = HashSet::new(); - if let Some(f) = move_data.get("flags") { - let f = f.as_array().unwrap(); - for flag in f { - flags.insert(StringKey::new(flag.as_str().unwrap())); - } - } - - move_library.add( - &move_name, - MoveData::new( - &move_name.clone(), - move_type_id, - move_category, - base_power, - accuracy, - pp, - target, - priority, - secondary_effect, - flags, - ), - ); - } - - move_library -} - -#[test] -#[cfg_attr(miri, ignore)] -fn test_type_library_loaded() { - let mut path = get_project_root().unwrap(); - path.push("tests/data/"); - let lib = load_types(&path.to_str().unwrap().to_string()); - - assert_eq!( - lib.get_effectiveness( - lib.get_type_id(&StringKey::new("fire")), - &vec![lib.get_type_id(&StringKey::new("grass")),] - ), - 2.0 - ); -} diff --git a/tests/main.rs b/tests/main.rs new file mode 100644 index 0000000..94a8a6f --- /dev/null +++ b/tests/main.rs @@ -0,0 +1,38 @@ +#![feature(custom_test_frameworks)] +#![feature(once_cell)] +#![test_runner(datatest::runner)] + +use crate::common::{library_loader, TestCase}; +use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary; +use std::fs::File; +use std::io::Read; +use std::lazy::SyncLazy; +use std::path::Path; + +pub mod common; + +static LIBRARY: SyncLazy = SyncLazy::new(|| { + let start_time = chrono::Utc::now(); + let lib = library_loader::load_library(); + let end_time = chrono::Utc::now(); + println!("Built library in {} ms", (end_time - start_time).num_milliseconds()); + lib +}); + +#[test] +#[cfg_attr(miri, ignore)] +fn validate_library_load() { + SyncLazy::force(&LIBRARY); +} + +#[datatest::files("tests/test_cases", { +input in r"^(.*)\.yaml" +})] +fn integration_tests(input: &Path) { + let mut str: String = "".to_string(); + let mut file = File::open(input).unwrap(); + file.read_to_string(&mut str).unwrap(); + let test_case = serde_yaml::from_str::(&*str).unwrap(); + println!("\tRunning integration test {}", test_case.name); + test_case.run_test(&LIBRARY); +} diff --git a/tests/test_cases/basic_single_turn.yaml b/tests/test_cases/basic_single_turn.yaml new file mode 100644 index 0000000..a7f794b --- /dev/null +++ b/tests/test_cases/basic_single_turn.yaml @@ -0,0 +1,44 @@ +name: basic_single_turn +battle_setup: + seed: 10 + can_flee: false + number_of_sides: 2 + pokemon_per_side: 1 + parties: + - indices: + - [ 0, 0 ] + pokemon: + - species: charizard + level: 50 + moves: + - ember + - indices: + - [ 1, 0 ] + pokemon: + - species: venusaur + level: 50 + moves: + - vine_whip +actions: + - set_pokemon: + place: [ 0, 0 ] + from_party: [ 0 ,0 ] + - set_pokemon: + place: [ 1, 0 ] + from_party: [ 1 ,0 ] + - assert: + value: + pokemon_health: + index: [ 1, 0 ] + expected: 140 + - set_move_choice: + for: [ 0, 0 ] + move: ember + target: [ 1, 0 ] + - set_pass_choice: + for: [ 1, 0 ] + - assert: + value: + pokemon_health: + index: [ 1, 0 ] + expected: 78 \ No newline at end of file diff --git a/tests/tests.rs b/tests/tests.rs deleted file mode 100644 index ef95611..0000000 --- a/tests/tests.rs +++ /dev/null @@ -1,13 +0,0 @@ -use project_root::get_project_root; - -pub mod library_loader; - -#[test] -#[cfg_attr(miri, ignore)] -fn run_integration_tests() { - let mut path = get_project_root().unwrap(); - path.push("tests/data/"); - let path = path.to_str().unwrap().to_string(); - let type_library = library_loader::load_types(&path); - let move_library = library_loader::load_moves(&path, &type_library); -}