started implementing iv-peeker
parent
920cff3bbe
commit
635e67d6c7
|
|
@ -3286,7 +3286,7 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smart-iv-calculator"
|
name = "smart_iv_calculator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "smart-iv-calculator"
|
name = "smart_iv_calculator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
"name": "Hardy",
|
"name": "Hardy",
|
||||||
"alias": "hardy",
|
"alias": "hardy",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
|
"pid": 0,
|
||||||
"increased": null,
|
"increased": null,
|
||||||
"decreased": null
|
"decreased": null
|
||||||
},
|
},
|
||||||
|
|
@ -9,6 +10,7 @@
|
||||||
"name": "Bold",
|
"name": "Bold",
|
||||||
"alias": "bold",
|
"alias": "bold",
|
||||||
"id": 2,
|
"id": 2,
|
||||||
|
"pid": 5,
|
||||||
"increased": "defense",
|
"increased": "defense",
|
||||||
"decreased": "attack"
|
"decreased": "attack"
|
||||||
},
|
},
|
||||||
|
|
@ -16,6 +18,7 @@
|
||||||
"name": "Modest",
|
"name": "Modest",
|
||||||
"alias": "modest",
|
"alias": "modest",
|
||||||
"id": 3,
|
"id": 3,
|
||||||
|
"pid": 15,
|
||||||
"increased": "special_attack",
|
"increased": "special_attack",
|
||||||
"decreased": "attack"
|
"decreased": "attack"
|
||||||
},
|
},
|
||||||
|
|
@ -23,6 +26,7 @@
|
||||||
"name": "Calm",
|
"name": "Calm",
|
||||||
"alias": "calm",
|
"alias": "calm",
|
||||||
"id": 4,
|
"id": 4,
|
||||||
|
"pid": 20,
|
||||||
"increased": "special_defense",
|
"increased": "special_defense",
|
||||||
"decreased": "attack"
|
"decreased": "attack"
|
||||||
},
|
},
|
||||||
|
|
@ -30,6 +34,7 @@
|
||||||
"name": "Timid",
|
"name": "Timid",
|
||||||
"alias": "timid",
|
"alias": "timid",
|
||||||
"id": 5,
|
"id": 5,
|
||||||
|
"pid": 10,
|
||||||
"increased": "speed",
|
"increased": "speed",
|
||||||
"decreased": "attack"
|
"decreased": "attack"
|
||||||
},
|
},
|
||||||
|
|
@ -37,6 +42,7 @@
|
||||||
"name": "Lonely",
|
"name": "Lonely",
|
||||||
"alias": "lonely",
|
"alias": "lonely",
|
||||||
"id": 6,
|
"id": 6,
|
||||||
|
"pid": 1,
|
||||||
"increased": "attack",
|
"increased": "attack",
|
||||||
"decreased": "defense"
|
"decreased": "defense"
|
||||||
},
|
},
|
||||||
|
|
@ -44,6 +50,7 @@
|
||||||
"name": "Docile",
|
"name": "Docile",
|
||||||
"alias": "docile",
|
"alias": "docile",
|
||||||
"id": 7,
|
"id": 7,
|
||||||
|
"pid": 6,
|
||||||
"increased": null,
|
"increased": null,
|
||||||
"decreased": null
|
"decreased": null
|
||||||
},
|
},
|
||||||
|
|
@ -51,6 +58,7 @@
|
||||||
"name": "Mild",
|
"name": "Mild",
|
||||||
"alias": "mild",
|
"alias": "mild",
|
||||||
"id": 8,
|
"id": 8,
|
||||||
|
"pid": 16,
|
||||||
"increased": "special_attack",
|
"increased": "special_attack",
|
||||||
"decreased": "defense"
|
"decreased": "defense"
|
||||||
},
|
},
|
||||||
|
|
@ -58,6 +66,7 @@
|
||||||
"name": "Gentle",
|
"name": "Gentle",
|
||||||
"alias": "gentle",
|
"alias": "gentle",
|
||||||
"id": 9,
|
"id": 9,
|
||||||
|
"pid": 21,
|
||||||
"increased": "special_defense",
|
"increased": "special_defense",
|
||||||
"decreased": "defense"
|
"decreased": "defense"
|
||||||
},
|
},
|
||||||
|
|
@ -65,6 +74,7 @@
|
||||||
"name": "Hasty",
|
"name": "Hasty",
|
||||||
"alias": "hasty",
|
"alias": "hasty",
|
||||||
"id": 10,
|
"id": 10,
|
||||||
|
"pid": 11,
|
||||||
"increased": "speed",
|
"increased": "speed",
|
||||||
"decreased": "defense"
|
"decreased": "defense"
|
||||||
},
|
},
|
||||||
|
|
@ -72,6 +82,7 @@
|
||||||
"name": "Adamant",
|
"name": "Adamant",
|
||||||
"alias": "adamant",
|
"alias": "adamant",
|
||||||
"id": 11,
|
"id": 11,
|
||||||
|
"pid": 3,
|
||||||
"increased": "attack",
|
"increased": "attack",
|
||||||
"decreased": "special_attack"
|
"decreased": "special_attack"
|
||||||
},
|
},
|
||||||
|
|
@ -79,6 +90,7 @@
|
||||||
"name": "Impish",
|
"name": "Impish",
|
||||||
"alias": "impish",
|
"alias": "impish",
|
||||||
"id": 12,
|
"id": 12,
|
||||||
|
"pid": 8,
|
||||||
"increased": "defense",
|
"increased": "defense",
|
||||||
"decreased": "special_attack"
|
"decreased": "special_attack"
|
||||||
},
|
},
|
||||||
|
|
@ -86,6 +98,7 @@
|
||||||
"name": "Bashful",
|
"name": "Bashful",
|
||||||
"alias": "bashful",
|
"alias": "bashful",
|
||||||
"id": 13,
|
"id": 13,
|
||||||
|
"pid": 18,
|
||||||
"increased": null,
|
"increased": null,
|
||||||
"decreased": null
|
"decreased": null
|
||||||
},
|
},
|
||||||
|
|
@ -93,6 +106,7 @@
|
||||||
"name": "Careful",
|
"name": "Careful",
|
||||||
"alias": "careful",
|
"alias": "careful",
|
||||||
"id": 14,
|
"id": 14,
|
||||||
|
"pid": 23,
|
||||||
"increased": "special_defense",
|
"increased": "special_defense",
|
||||||
"decreased": "special_attack"
|
"decreased": "special_attack"
|
||||||
},
|
},
|
||||||
|
|
@ -100,6 +114,7 @@
|
||||||
"name": "Rash",
|
"name": "Rash",
|
||||||
"alias": "rash",
|
"alias": "rash",
|
||||||
"id": 15,
|
"id": 15,
|
||||||
|
"pid": 19,
|
||||||
"increased": "special_attack",
|
"increased": "special_attack",
|
||||||
"decreased": "special_defense"
|
"decreased": "special_defense"
|
||||||
},
|
},
|
||||||
|
|
@ -107,6 +122,7 @@
|
||||||
"name": "Jolly",
|
"name": "Jolly",
|
||||||
"alias": "jolly",
|
"alias": "jolly",
|
||||||
"id": 16,
|
"id": 16,
|
||||||
|
"pid": 13,
|
||||||
"increased": "speed",
|
"increased": "speed",
|
||||||
"decreased": "special_attack"
|
"decreased": "special_attack"
|
||||||
},
|
},
|
||||||
|
|
@ -114,6 +130,7 @@
|
||||||
"name": "Naughty",
|
"name": "Naughty",
|
||||||
"alias": "naughty",
|
"alias": "naughty",
|
||||||
"id": 17,
|
"id": 17,
|
||||||
|
"pid": 4,
|
||||||
"increased": "attack",
|
"increased": "attack",
|
||||||
"decreased": "special_defense"
|
"decreased": "special_defense"
|
||||||
},
|
},
|
||||||
|
|
@ -121,6 +138,7 @@
|
||||||
"name": "Lax",
|
"name": "Lax",
|
||||||
"alias": "lax",
|
"alias": "lax",
|
||||||
"id": 18,
|
"id": 18,
|
||||||
|
"pid": 9,
|
||||||
"increased": "defense",
|
"increased": "defense",
|
||||||
"decreased": "special_defense"
|
"decreased": "special_defense"
|
||||||
},
|
},
|
||||||
|
|
@ -128,6 +146,7 @@
|
||||||
"name": "Quirky",
|
"name": "Quirky",
|
||||||
"alias": "quirky",
|
"alias": "quirky",
|
||||||
"id": 19,
|
"id": 19,
|
||||||
|
"pid": 24,
|
||||||
"increased": null,
|
"increased": null,
|
||||||
"decreased": null
|
"decreased": null
|
||||||
},
|
},
|
||||||
|
|
@ -135,6 +154,7 @@
|
||||||
"name": "Naive",
|
"name": "Naive",
|
||||||
"alias": "naive",
|
"alias": "naive",
|
||||||
"id": 20,
|
"id": 20,
|
||||||
|
"pid": 14,
|
||||||
"increased": "speed",
|
"increased": "speed",
|
||||||
"decreased": "special_defense"
|
"decreased": "special_defense"
|
||||||
},
|
},
|
||||||
|
|
@ -142,6 +162,7 @@
|
||||||
"name": "Brave",
|
"name": "Brave",
|
||||||
"alias": "brave",
|
"alias": "brave",
|
||||||
"id": 21,
|
"id": 21,
|
||||||
|
"pid": 2,
|
||||||
"increased": "attack",
|
"increased": "attack",
|
||||||
"decreased": "speed"
|
"decreased": "speed"
|
||||||
},
|
},
|
||||||
|
|
@ -149,6 +170,7 @@
|
||||||
"name": "Relaxed",
|
"name": "Relaxed",
|
||||||
"alias": "relaxed",
|
"alias": "relaxed",
|
||||||
"id": 22,
|
"id": 22,
|
||||||
|
"pid": 7,
|
||||||
"increased": "defense",
|
"increased": "defense",
|
||||||
"decreased": "speed"
|
"decreased": "speed"
|
||||||
},
|
},
|
||||||
|
|
@ -156,6 +178,7 @@
|
||||||
"name": "Quiet",
|
"name": "Quiet",
|
||||||
"alias": "quiet",
|
"alias": "quiet",
|
||||||
"id": 23,
|
"id": 23,
|
||||||
|
"pid": 17,
|
||||||
"increased": "special_attack",
|
"increased": "special_attack",
|
||||||
"decreased": "speed"
|
"decreased": "speed"
|
||||||
},
|
},
|
||||||
|
|
@ -163,6 +186,7 @@
|
||||||
"name": "Sassy",
|
"name": "Sassy",
|
||||||
"alias": "sassy",
|
"alias": "sassy",
|
||||||
"id": 24,
|
"id": 24,
|
||||||
|
"pid": 22,
|
||||||
"increased": "special_defense",
|
"increased": "special_defense",
|
||||||
"decreased": "speed"
|
"decreased": "speed"
|
||||||
},
|
},
|
||||||
|
|
@ -170,6 +194,7 @@
|
||||||
"name": "Serious",
|
"name": "Serious",
|
||||||
"alias": "serious",
|
"alias": "serious",
|
||||||
"id": 25,
|
"id": 25,
|
||||||
|
"pid": 12,
|
||||||
"increased": null,
|
"increased": null,
|
||||||
"decreased": null
|
"decreased": null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
use smart_iv_calculator::ivcalc;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
ivcalc::run()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
use smart_iv_calculator::ivpeek;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
ivpeek::run()
|
||||||
|
}
|
||||||
|
|
@ -1,28 +1,13 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use std::{
|
use crate::{
|
||||||
collections::HashMap,
|
json::{read_characteristics, read_natures, read_pokedex},
|
||||||
fs,
|
pokemon::*,
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::pokemon::*;
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref DATA_DIR: PathBuf = "./data".into();
|
|
||||||
pub static ref TYPE_MAP: HashMap<u8, Type> = {
|
|
||||||
let types = parse_json_file(DATA_DIR.join("types.json"));
|
|
||||||
let mut map = HashMap::new();
|
|
||||||
for type_data in types.members() {
|
|
||||||
if let Some(type_data) = Type::from_json(type_data) {
|
|
||||||
map.insert(type_data.id, type_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
map
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DatabasePlugin;
|
pub struct DatabasePlugin;
|
||||||
|
|
||||||
impl Plugin for DatabasePlugin {
|
impl Plugin for DatabasePlugin {
|
||||||
|
|
@ -60,28 +45,7 @@ fn database_setup(
|
||||||
mut nature_database: ResMut<Database<Nature>>,
|
mut nature_database: ResMut<Database<Nature>>,
|
||||||
mut characteristic_database: ResMut<Database<Characteristic>>,
|
mut characteristic_database: ResMut<Database<Characteristic>>,
|
||||||
) {
|
) {
|
||||||
let natures = parse_json_file(DATA_DIR.join("natures.json"));
|
nature_database.populate_from_json(&read_natures());
|
||||||
nature_database.populate_from_json(&natures);
|
pokemon_database.populate_from_json(&read_pokedex());
|
||||||
let pokedex = parse_json_file(DATA_DIR.join("pokedex.json"));
|
characteristic_database.populate_from_json(&read_characteristics());
|
||||||
pokemon_database.populate_from_json(&pokedex);
|
|
||||||
let characteristics = parse_json_file(DATA_DIR.join("characteristics.json"));
|
|
||||||
characteristic_database.populate_from_json(&characteristics);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_json_file<P: AsRef<Path>>(path: P) -> JsonValue {
|
|
||||||
json::parse(fs::read_to_string(path).unwrap().as_ref()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_url_asset(
|
|
||||||
url: String,
|
|
||||||
path: PathBuf,
|
|
||||||
assets: &Res<AssetServer>,
|
|
||||||
) -> Result<Handle<Image>, Box<dyn std::error::Error>> {
|
|
||||||
let system_path = Path::new("assets").join(&path);
|
|
||||||
if Path::exists(&path) {
|
|
||||||
return Ok(assets.load(path));
|
|
||||||
}
|
|
||||||
let data = reqwest::blocking::get(&url)?.bytes()?;
|
|
||||||
fs::write(&system_path, data).unwrap();
|
|
||||||
Ok(assets.load(path))
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
use bevy::{prelude::*, window::WindowResolution};
|
use bevy::{prelude::*, window::WindowResolution};
|
||||||
|
|
||||||
pub mod database;
|
mod calculator;
|
||||||
pub mod inspector;
|
mod server;
|
||||||
pub mod pokemon;
|
mod ui;
|
||||||
pub mod server;
|
|
||||||
pub mod ui;
|
|
||||||
|
|
||||||
fn main() {
|
pub fn run() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(
|
.add_plugins(
|
||||||
DefaultPlugins
|
DefaultPlugins
|
||||||
|
|
@ -21,8 +19,8 @@ fn main() {
|
||||||
})
|
})
|
||||||
.set(ImagePlugin::default_nearest()),
|
.set(ImagePlugin::default_nearest()),
|
||||||
)
|
)
|
||||||
.add_plugin(database::DatabasePlugin)
|
.add_plugin(crate::database::DatabasePlugin)
|
||||||
.add_plugin(inspector::InspectorPlugin)
|
.add_plugin(calculator::CalculatorPlugin)
|
||||||
.add_plugin(ui::UiPlugin)
|
.add_plugin(ui::UiPlugin)
|
||||||
.add_plugin(server::ServerPlugin)
|
.add_plugin(server::ServerPlugin)
|
||||||
.run();
|
.run();
|
||||||
|
|
@ -1,19 +1,25 @@
|
||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_egui::EguiContexts;
|
use bevy_egui::EguiContexts;
|
||||||
|
|
||||||
use crate::{
|
use crate::database::*;
|
||||||
database::{load_url_asset, Database},
|
use crate::pokemon::*;
|
||||||
pokemon::*,
|
|
||||||
|
use super::{
|
||||||
server::Request,
|
server::Request,
|
||||||
ui::{UiAssets, UiState},
|
ui::{UiAssets, UiState},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct InspectorPlugin;
|
pub struct CalculatorPlugin;
|
||||||
|
|
||||||
impl Plugin for InspectorPlugin {
|
impl Plugin for CalculatorPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.register_type::<Inspector>()
|
app.register_type::<Calculator>()
|
||||||
.insert_resource(Inspector::default())
|
.insert_resource(Calculator::default())
|
||||||
.add_system(state_changed)
|
.add_system(state_changed)
|
||||||
.add_system(request_handler.in_base_set(CoreSet::PreUpdate));
|
.add_system(request_handler.in_base_set(CoreSet::PreUpdate));
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +27,7 @@ impl Plugin for InspectorPlugin {
|
||||||
|
|
||||||
#[derive(Reflect, Resource, Default, Debug, Clone)]
|
#[derive(Reflect, Resource, Default, Debug, Clone)]
|
||||||
#[reflect(Resource)]
|
#[reflect(Resource)]
|
||||||
pub struct Inspector {
|
pub struct Calculator {
|
||||||
pub pokemon: Option<Pokemon>,
|
pub pokemon: Option<Pokemon>,
|
||||||
pub nature: Option<Nature>,
|
pub nature: Option<Nature>,
|
||||||
pub characteristic: Option<Characteristic>,
|
pub characteristic: Option<Characteristic>,
|
||||||
|
|
@ -29,15 +35,15 @@ pub struct Inspector {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state_changed(
|
fn state_changed(
|
||||||
inspector: Res<Inspector>,
|
calculator: Res<Calculator>,
|
||||||
assets: Res<AssetServer>,
|
assets: Res<AssetServer>,
|
||||||
mut ui_assets: ResMut<UiAssets>,
|
mut ui_assets: ResMut<UiAssets>,
|
||||||
mut contexts: EguiContexts,
|
mut contexts: EguiContexts,
|
||||||
) {
|
) {
|
||||||
if let (Some(pokemon), true) = (inspector.pokemon.as_ref(), inspector.is_changed()) {
|
if let (Some(pokemon), true) = (calculator.pokemon.as_ref(), calculator.is_changed()) {
|
||||||
if !ui_assets.sprite_map.contains_key(&pokemon.key()) {
|
if !ui_assets.sprite_map.contains_key(&pokemon.key()) {
|
||||||
let handle = load_url_asset(
|
let handle = load_url_asset(
|
||||||
pokemon.get_url(),
|
pokemon.sprite_url(),
|
||||||
format!("cache/{name}.png", name = pokemon.key()).into(),
|
format!("cache/{name}.png", name = pokemon.key()).into(),
|
||||||
&assets,
|
&assets,
|
||||||
);
|
);
|
||||||
|
|
@ -53,7 +59,7 @@ fn state_changed(
|
||||||
|
|
||||||
fn request_handler(
|
fn request_handler(
|
||||||
mut request_events: EventReader<Request>,
|
mut request_events: EventReader<Request>,
|
||||||
mut inspector: ResMut<Inspector>,
|
mut calculator: ResMut<Calculator>,
|
||||||
mut ui: ResMut<UiState>,
|
mut ui: ResMut<UiState>,
|
||||||
characteristics: Res<Database<Characteristic>>,
|
characteristics: Res<Database<Characteristic>>,
|
||||||
natures: Res<Database<Nature>>,
|
natures: Res<Database<Nature>>,
|
||||||
|
|
@ -62,10 +68,10 @@ fn request_handler(
|
||||||
info!("{:#}", request);
|
info!("{:#}", request);
|
||||||
match request.urn.as_str() {
|
match request.urn.as_str() {
|
||||||
"clear" => {
|
"clear" => {
|
||||||
inspector.pokemon = None;
|
calculator.pokemon = None;
|
||||||
inspector.nature = None;
|
calculator.nature = None;
|
||||||
inspector.characteristic = None;
|
calculator.characteristic = None;
|
||||||
inspector.derived_stats = DerivedStats::default();
|
calculator.derived_stats = DerivedStats::default();
|
||||||
ui.name = String::from("");
|
ui.name = String::from("");
|
||||||
ui.level = String::from("");
|
ui.level = String::from("");
|
||||||
ui.derived_stats.clear();
|
ui.derived_stats.clear();
|
||||||
|
|
@ -77,11 +83,11 @@ fn request_handler(
|
||||||
}
|
}
|
||||||
if let Some(level) = data["level"].as_i32() {
|
if let Some(level) = data["level"].as_i32() {
|
||||||
ui.level = level.to_string();
|
ui.level = level.to_string();
|
||||||
inspector.derived_stats.level = Some(level);
|
calculator.derived_stats.level = Some(level);
|
||||||
}
|
}
|
||||||
if let Some(nature) = data["nature"].as_str() {
|
if let Some(nature) = data["nature"].as_str() {
|
||||||
if let Some(nature) = natures.map.get(&nature.to_lowercase()).cloned() {
|
if let Some(nature) = natures.map.get(&nature.to_lowercase()).cloned() {
|
||||||
inspector.nature = Some(nature);
|
calculator.nature = Some(nature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(characteristic) = data["characteristic"].as_str() {
|
if let Some(characteristic) = data["characteristic"].as_str() {
|
||||||
|
|
@ -90,13 +96,13 @@ fn request_handler(
|
||||||
.get(&characteristic.to_lowercase())
|
.get(&characteristic.to_lowercase())
|
||||||
.cloned()
|
.cloned()
|
||||||
{
|
{
|
||||||
inspector.characteristic = Some(characteristic);
|
calculator.characteristic = Some(characteristic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for stat in BaseStat::all() {
|
for stat in BaseStat::all() {
|
||||||
if let Some(value) = data[stat.key()].as_i32() {
|
if let Some(value) = data[stat.key()].as_i32() {
|
||||||
ui.derived_stats.insert(stat, value.to_string());
|
ui.derived_stats.insert(stat, value.to_string());
|
||||||
inspector.derived_stats.set_stat_value(stat, Some(value));
|
calculator.derived_stats.set_stat_value(stat, Some(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -106,3 +112,17 @@ fn request_handler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_url_asset(
|
||||||
|
url: String,
|
||||||
|
path: PathBuf,
|
||||||
|
assets: &Res<AssetServer>,
|
||||||
|
) -> Result<Handle<Image>, Box<dyn std::error::Error>> {
|
||||||
|
let system_path = Path::new("assets").join(&path);
|
||||||
|
if Path::exists(&path) {
|
||||||
|
return Ok(assets.load(path));
|
||||||
|
}
|
||||||
|
let data = reqwest::blocking::get(&url)?.bytes()?;
|
||||||
|
fs::write(&system_path, data).unwrap();
|
||||||
|
Ok(assets.load(path))
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,10 @@ use bevy_egui::{egui, EguiContexts, EguiPlugin};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{database::Database, inspector::Inspector, pokemon::*};
|
use crate::database::Database;
|
||||||
|
use crate::pokemon::*;
|
||||||
|
|
||||||
|
use super::calculator::Calculator;
|
||||||
|
|
||||||
const INPUT_LABEL_WIDTH: f32 = 100.0;
|
const INPUT_LABEL_WIDTH: f32 = 100.0;
|
||||||
const INPUT_TEXT_WIDTH: f32 = 150.0;
|
const INPUT_TEXT_WIDTH: f32 = 150.0;
|
||||||
|
|
@ -69,18 +72,18 @@ fn load_assets(mut ui_assets: ResMut<UiAssets>, assets: Res<AssetServer>) {
|
||||||
fn handle_state(
|
fn handle_state(
|
||||||
ui_state: Res<UiState>,
|
ui_state: Res<UiState>,
|
||||||
pokemon: Res<Database<Pokemon>>,
|
pokemon: Res<Database<Pokemon>>,
|
||||||
mut inspector: ResMut<Inspector>,
|
mut calculator: ResMut<Calculator>,
|
||||||
) {
|
) {
|
||||||
if ui_state.is_changed() {
|
if ui_state.is_changed() {
|
||||||
if let Some(pokemon) = pokemon.map.get(ui_state.name.to_lowercase().as_str()) {
|
if let Some(pokemon) = pokemon.map.get(ui_state.name.to_lowercase().as_str()) {
|
||||||
inspector.pokemon = Some(pokemon.clone());
|
calculator.pokemon = Some(pokemon.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_system(
|
fn ui_system(
|
||||||
mut contexts: EguiContexts,
|
mut contexts: EguiContexts,
|
||||||
mut inspector: ResMut<Inspector>,
|
mut calculator: ResMut<Calculator>,
|
||||||
ui_assets: Res<UiAssets>,
|
ui_assets: Res<UiAssets>,
|
||||||
mut ui_state: ResMut<UiState>,
|
mut ui_state: ResMut<UiState>,
|
||||||
mut rendered_texture_id: Local<egui::TextureId>,
|
mut rendered_texture_id: Local<egui::TextureId>,
|
||||||
|
|
@ -96,11 +99,11 @@ fn ui_system(
|
||||||
egui::CentralPanel::default().show(contexts.ctx_mut(), |ui| {
|
egui::CentralPanel::default().show(contexts.ctx_mut(), |ui| {
|
||||||
let sprite_size = egui::Vec2::new(128., 128.);
|
let sprite_size = egui::Vec2::new(128., 128.);
|
||||||
|
|
||||||
let pokemon = inspector.pokemon.clone();
|
let pokemon = calculator.pokemon.clone();
|
||||||
let pokemon = pokemon.as_ref();
|
let pokemon = pokemon.as_ref();
|
||||||
let nature = inspector.nature.clone();
|
let nature = calculator.nature.clone();
|
||||||
let nature = nature.as_ref();
|
let nature = nature.as_ref();
|
||||||
let characteristic = inspector.characteristic.clone();
|
let characteristic = calculator.characteristic.clone();
|
||||||
let characteristic = characteristic.as_ref();
|
let characteristic = characteristic.as_ref();
|
||||||
|
|
||||||
// Pokemon
|
// Pokemon
|
||||||
|
|
@ -128,11 +131,11 @@ fn ui_system(
|
||||||
egui::ComboBox::new("nature", "")
|
egui::ComboBox::new("nature", "")
|
||||||
.selected_text(format!("{}", nature.map_or("-", |c| &c.name)))
|
.selected_text(format!("{}", nature.map_or("-", |c| &c.name)))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
ui.selectable_value(&mut inspector.nature, None, "-");
|
ui.selectable_value(&mut calculator.nature, None, "-");
|
||||||
let mut chars: Vec<_> = natures.map.values().collect();
|
let mut chars: Vec<_> = natures.map.values().collect();
|
||||||
chars.sort_by_key(|c| c.name.clone());
|
chars.sort_by_key(|c| c.name.clone());
|
||||||
for char in chars {
|
for char in chars {
|
||||||
ui.selectable_value(&mut inspector.nature, Some(char.clone()), &char.name);
|
ui.selectable_value(&mut calculator.nature, Some(char.clone()), &char.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -147,12 +150,12 @@ fn ui_system(
|
||||||
egui::ComboBox::new("characteristic", "")
|
egui::ComboBox::new("characteristic", "")
|
||||||
.selected_text(format!("{}", characteristic.map_or("-", |c| &c.name)))
|
.selected_text(format!("{}", characteristic.map_or("-", |c| &c.name)))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
ui.selectable_value(&mut inspector.characteristic, None, "-");
|
ui.selectable_value(&mut calculator.characteristic, None, "-");
|
||||||
let mut chars: Vec<_> = characteristics.map.values().collect();
|
let mut chars: Vec<_> = characteristics.map.values().collect();
|
||||||
chars.sort_by_key(|c| c.name.clone());
|
chars.sort_by_key(|c| c.name.clone());
|
||||||
for char in chars {
|
for char in chars {
|
||||||
ui.selectable_value(
|
ui.selectable_value(
|
||||||
&mut inspector.characteristic,
|
&mut calculator.characteristic,
|
||||||
Some(char.clone()),
|
Some(char.clone()),
|
||||||
&char.name,
|
&char.name,
|
||||||
);
|
);
|
||||||
|
|
@ -212,7 +215,7 @@ fn ui_system(
|
||||||
if input.changed() {
|
if input.changed() {
|
||||||
*value = digit_filter(value);
|
*value = digit_filter(value);
|
||||||
if let Ok(value) = value.parse::<StatValue>() {
|
if let Ok(value) = value.parse::<StatValue>() {
|
||||||
inspector.derived_stats.level = Some(value);
|
calculator.derived_stats.level = Some(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if input.gained_focus() {
|
if input.gained_focus() {
|
||||||
|
|
@ -318,7 +321,7 @@ fn ui_system(
|
||||||
*value = digit_filter(value);
|
*value = digit_filter(value);
|
||||||
if let (Ok(value), derived) = (
|
if let (Ok(value), derived) = (
|
||||||
value.parse::<StatValue>(),
|
value.parse::<StatValue>(),
|
||||||
inspector.derived_stats.value_mut(stat),
|
calculator.derived_stats.value_mut(stat),
|
||||||
) {
|
) {
|
||||||
*derived = Some(value);
|
*derived = Some(value);
|
||||||
}
|
}
|
||||||
|
|
@ -330,8 +333,8 @@ fn ui_system(
|
||||||
|
|
||||||
let possible_ivs = if let (Some(pokemon), Some(level), Some(derived_stat)) = (
|
let possible_ivs = if let (Some(pokemon), Some(level), Some(derived_stat)) = (
|
||||||
pokemon,
|
pokemon,
|
||||||
inspector.derived_stats.level,
|
calculator.derived_stats.level,
|
||||||
inspector.derived_stats.value(stat),
|
calculator.derived_stats.value(stat),
|
||||||
) {
|
) {
|
||||||
calculate_possible_ivs(
|
calculate_possible_ivs(
|
||||||
stat,
|
stat,
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
use bevy::{prelude::*, window::WindowResolution};
|
||||||
|
|
||||||
|
mod inspector;
|
||||||
|
mod ui;
|
||||||
|
|
||||||
|
pub fn run() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(
|
||||||
|
DefaultPlugins
|
||||||
|
.set(WindowPlugin {
|
||||||
|
primary_window: Some(Window {
|
||||||
|
resolution: WindowResolution::new(720., 540.),
|
||||||
|
resizable: false,
|
||||||
|
title: "Smart IV peeker".to_string(),
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.set(ImagePlugin::default_nearest()),
|
||||||
|
)
|
||||||
|
.add_plugin(crate::database::DatabasePlugin)
|
||||||
|
.add_plugin(ui::UiPlugin)
|
||||||
|
.run()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::pokemon::*;
|
||||||
|
|
||||||
|
pub struct InspectorPlugin;
|
||||||
|
|
||||||
|
impl Plugin for InspectorPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.insert_resource(Inspector::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
pub struct Inspector {
|
||||||
|
pub allies: Vec<PokemonInstance>,
|
||||||
|
pub enemies: Vec<PokemonInstance>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Inspector {
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.allies.clear();
|
||||||
|
self.enemies.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct PokemonInstance {
|
||||||
|
pub pokemon: Pokemon,
|
||||||
|
pub nature: Option<Nature>,
|
||||||
|
pub ivs: HashMap<BaseStat, u8>,
|
||||||
|
pub evs: HashMap<BaseStat, u8>,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_egui::{egui, EguiContexts, EguiPlugin};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::{database::Database, pokemon::*};
|
||||||
|
|
||||||
|
use super::inspector::{Inspector, PokemonInstance};
|
||||||
|
|
||||||
|
const BAR_HEIGHT: f32 = 12.0;
|
||||||
|
const BASE_STAT_WIDTH_MULT: f32 = 1.0;
|
||||||
|
const IV_WIDTH_MULT: f32 = 4.0;
|
||||||
|
const EV_WIDTH_MULT: f32 = 1.0;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref BASE_STAT_COLOR_RANGES: Vec<(u8, egui::Color32)> = vec![
|
||||||
|
(0, egui::Color32::from_rgb(255, 0, 0)),
|
||||||
|
(30, egui::Color32::from_rgb(255, 128, 0)),
|
||||||
|
(60, egui::Color32::from_rgb(255, 255, 0)),
|
||||||
|
(90, egui::Color32::from_rgb(128, 255, 0)),
|
||||||
|
(120, egui::Color32::from_rgb(0, 255, 0)),
|
||||||
|
(150, egui::Color32::from_rgb(0, 255, 128)),
|
||||||
|
(180, egui::Color32::from_rgb(0, 255, 255)),
|
||||||
|
];
|
||||||
|
static ref IV_COLOR_RANGES: Vec<(u8, egui::Color32)> = vec![
|
||||||
|
(0, egui::Color32::from_rgb(255, 0, 0)),
|
||||||
|
(16, egui::Color32::from_rgb(255, 128, 0)),
|
||||||
|
(22, egui::Color32::from_rgb(255, 255, 0)),
|
||||||
|
(27, egui::Color32::from_rgb(128, 255, 0)),
|
||||||
|
(30, egui::Color32::from_rgb(0, 255, 0)),
|
||||||
|
];
|
||||||
|
static ref COLUMNS: Vec<f32> = vec![
|
||||||
|
25.0, // Base stat
|
||||||
|
255.0 * BASE_STAT_WIDTH_MULT, // Base stat bar
|
||||||
|
60.0, // Stat name
|
||||||
|
40.0, // IV value
|
||||||
|
32.0 * IV_WIDTH_MULT, // IV bar
|
||||||
|
40.0, // EV value
|
||||||
|
255.0 * EV_WIDTH_MULT, // EV bar
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UiPlugin;
|
||||||
|
|
||||||
|
impl Plugin for UiPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_plugin(EguiPlugin)
|
||||||
|
.insert_resource(Inspector::default())
|
||||||
|
.insert_resource(UiAssets::default())
|
||||||
|
.add_startup_system(load_assets)
|
||||||
|
.add_system(ui_system)
|
||||||
|
.add_startup_system(test_init);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_init(mut inspector: ResMut<Inspector>, pokemon_database: Res<Database<Pokemon>>) {
|
||||||
|
inspector.enemies.push(PokemonInstance {
|
||||||
|
pokemon: pokemon_database.map.get("baltoy").unwrap().clone(),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
pub struct UiAssets {
|
||||||
|
pub bar_handle: Handle<Image>,
|
||||||
|
pub sprite_map: HashMap<String, (Handle<Image>, egui::TextureId)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_assets(mut ui_assets: ResMut<UiAssets>, assets: Res<AssetServer>) {
|
||||||
|
ui_assets.bar_handle = assets.load("ui/bar.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ui_system(
|
||||||
|
mut contexts: EguiContexts,
|
||||||
|
inspector: Res<Inspector>,
|
||||||
|
ui_assets: Res<UiAssets>,
|
||||||
|
mut rendered_texture_id: Local<egui::TextureId>,
|
||||||
|
mut is_initialized: Local<bool>,
|
||||||
|
) {
|
||||||
|
if !*is_initialized {
|
||||||
|
*is_initialized = true;
|
||||||
|
*rendered_texture_id = contexts.add_image(ui_assets.bar_handle.clone_weak());
|
||||||
|
}
|
||||||
|
|
||||||
|
egui::CentralPanel::default().show(contexts.ctx_mut(), |ui| {
|
||||||
|
let sprite_size = egui::Vec2::new(128., 128.);
|
||||||
|
for instance in inspector.enemies.iter().chain(inspector.allies.iter()) {
|
||||||
|
let pokemon = instance.pokemon.clone();
|
||||||
|
|
||||||
|
// Sprite
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.set_min_size(sprite_size);
|
||||||
|
if let Some((_, rendered_texture_id)) = ui_assets.sprite_map.get(&pokemon.key())
|
||||||
|
{
|
||||||
|
ui.add(egui::Image::new(*rendered_texture_id, sprite_size));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nature_color(stat: BaseStat, nature: Option<&Nature>) -> egui::Color32 {
|
||||||
|
if let Some(nature) = nature {
|
||||||
|
if nature.increased == Some(stat) {
|
||||||
|
egui::Color32::from_rgb(255, 64, 192)
|
||||||
|
} else if nature.decreased == Some(stat) {
|
||||||
|
egui::Color32::from_rgb(64, 192, 255)
|
||||||
|
} else {
|
||||||
|
egui::Color32::LIGHT_GRAY
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
egui::Color32::LIGHT_GRAY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iv_color(iv: u8) -> egui::Color32 {
|
||||||
|
for (treshold, color) in IV_COLOR_RANGES.iter().rev() {
|
||||||
|
if iv >= *treshold {
|
||||||
|
return color.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IV_COLOR_RANGES
|
||||||
|
.first()
|
||||||
|
.map_or(egui::Color32::LIGHT_GRAY, |(_, color)| color.clone())
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
use json::JsonValue;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::pokemon::*;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref DATA_DIR: PathBuf = "./data".into();
|
||||||
|
pub static ref TYPE_MAP: HashMap<u8, Type> = {
|
||||||
|
let types = read_pokedex();
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
for type_data in types.members() {
|
||||||
|
if let Some(type_data) = Type::from_json(type_data) {
|
||||||
|
map.insert(type_data.id, type_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_json_file<P: AsRef<Path>>(path: P) -> JsonValue {
|
||||||
|
json::parse(fs::read_to_string(path).unwrap().as_ref()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_natures() -> JsonValue {
|
||||||
|
parse_json_file(DATA_DIR.join("natures.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_pokedex() -> JsonValue {
|
||||||
|
parse_json_file(DATA_DIR.join("pokedex.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_types() -> JsonValue {
|
||||||
|
parse_json_file(DATA_DIR.join("types.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_characteristics() -> JsonValue {
|
||||||
|
parse_json_file(DATA_DIR.join("characteristics.json"))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
pub mod database;
|
||||||
|
pub mod ivcalc;
|
||||||
|
pub mod ivpeek;
|
||||||
|
pub mod json;
|
||||||
|
pub mod pokemon;
|
||||||
|
|
@ -2,7 +2,7 @@ use bevy::reflect::{FromReflect, Reflect};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::{collections::HashMap, fmt};
|
use std::{collections::HashMap, fmt};
|
||||||
|
|
||||||
use crate::database::TYPE_MAP;
|
use crate::json::TYPE_MAP;
|
||||||
|
|
||||||
pub type BaseValue = u8;
|
pub type BaseValue = u8;
|
||||||
pub type StatValue = i32;
|
pub type StatValue = i32;
|
||||||
|
|
@ -103,7 +103,7 @@ impl Pokemon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_url(&self) -> String {
|
pub fn sprite_url(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"https://img.pokemondb.net/sprites/{gen}/normal/{name}.png",
|
"https://img.pokemondb.net/sprites/{gen}/normal/{name}.png",
|
||||||
gen = self.get_sprite_gen(),
|
gen = self.get_sprite_gen(),
|
||||||
|
|
@ -183,6 +183,18 @@ impl BaseStat {
|
||||||
BaseStat::Speed,
|
BaseStat::Speed,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_str(str: &str) -> Option<Self> {
|
||||||
|
match str {
|
||||||
|
"hp" => Some(BaseStat::Hp),
|
||||||
|
"attack" => Some(BaseStat::Attack),
|
||||||
|
"defense" => Some(BaseStat::Defense),
|
||||||
|
"special_attack" => Some(BaseStat::SpecialAttack),
|
||||||
|
"special_defense" => Some(BaseStat::SpecialDefense),
|
||||||
|
"speed" => Some(BaseStat::Speed),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetKey for BaseStat {
|
impl GetKey for BaseStat {
|
||||||
|
|
@ -238,6 +250,7 @@ impl GetKey for Type {
|
||||||
#[derive(Default, Debug, Clone, Reflect, FromReflect, PartialEq)]
|
#[derive(Default, Debug, Clone, Reflect, FromReflect, PartialEq)]
|
||||||
pub struct Nature {
|
pub struct Nature {
|
||||||
pub id: u8,
|
pub id: u8,
|
||||||
|
pub pid: u8,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub alias: String,
|
pub alias: String,
|
||||||
pub increased: Option<BaseStat>,
|
pub increased: Option<BaseStat>,
|
||||||
|
|
@ -260,6 +273,7 @@ impl FromJson for Nature {
|
||||||
fn from_json(json: &json::JsonValue) -> Option<Self> {
|
fn from_json(json: &json::JsonValue) -> Option<Self> {
|
||||||
Some(Self {
|
Some(Self {
|
||||||
id: json["id"].as_u8()?,
|
id: json["id"].as_u8()?,
|
||||||
|
pid: json["pid"].as_u8()?,
|
||||||
name: json["name"].as_str()?.to_string(),
|
name: json["name"].as_str()?.to_string(),
|
||||||
alias: json["alias"].as_str()?.to_string(),
|
alias: json["alias"].as_str()?.to_string(),
|
||||||
increased: json["increased"]
|
increased: json["increased"]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue