started implementing iv-peeker
parent
920cff3bbe
commit
635e67d6c7
|
|
@ -3286,7 +3286,7 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "smart-iv-calculator"
|
||||
name = "smart_iv_calculator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "smart-iv-calculator"
|
||||
name = "smart_iv_calculator"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
"name": "Hardy",
|
||||
"alias": "hardy",
|
||||
"id": 1,
|
||||
"pid": 0,
|
||||
"increased": null,
|
||||
"decreased": null
|
||||
},
|
||||
|
|
@ -9,6 +10,7 @@
|
|||
"name": "Bold",
|
||||
"alias": "bold",
|
||||
"id": 2,
|
||||
"pid": 5,
|
||||
"increased": "defense",
|
||||
"decreased": "attack"
|
||||
},
|
||||
|
|
@ -16,6 +18,7 @@
|
|||
"name": "Modest",
|
||||
"alias": "modest",
|
||||
"id": 3,
|
||||
"pid": 15,
|
||||
"increased": "special_attack",
|
||||
"decreased": "attack"
|
||||
},
|
||||
|
|
@ -23,6 +26,7 @@
|
|||
"name": "Calm",
|
||||
"alias": "calm",
|
||||
"id": 4,
|
||||
"pid": 20,
|
||||
"increased": "special_defense",
|
||||
"decreased": "attack"
|
||||
},
|
||||
|
|
@ -30,6 +34,7 @@
|
|||
"name": "Timid",
|
||||
"alias": "timid",
|
||||
"id": 5,
|
||||
"pid": 10,
|
||||
"increased": "speed",
|
||||
"decreased": "attack"
|
||||
},
|
||||
|
|
@ -37,6 +42,7 @@
|
|||
"name": "Lonely",
|
||||
"alias": "lonely",
|
||||
"id": 6,
|
||||
"pid": 1,
|
||||
"increased": "attack",
|
||||
"decreased": "defense"
|
||||
},
|
||||
|
|
@ -44,6 +50,7 @@
|
|||
"name": "Docile",
|
||||
"alias": "docile",
|
||||
"id": 7,
|
||||
"pid": 6,
|
||||
"increased": null,
|
||||
"decreased": null
|
||||
},
|
||||
|
|
@ -51,6 +58,7 @@
|
|||
"name": "Mild",
|
||||
"alias": "mild",
|
||||
"id": 8,
|
||||
"pid": 16,
|
||||
"increased": "special_attack",
|
||||
"decreased": "defense"
|
||||
},
|
||||
|
|
@ -58,6 +66,7 @@
|
|||
"name": "Gentle",
|
||||
"alias": "gentle",
|
||||
"id": 9,
|
||||
"pid": 21,
|
||||
"increased": "special_defense",
|
||||
"decreased": "defense"
|
||||
},
|
||||
|
|
@ -65,6 +74,7 @@
|
|||
"name": "Hasty",
|
||||
"alias": "hasty",
|
||||
"id": 10,
|
||||
"pid": 11,
|
||||
"increased": "speed",
|
||||
"decreased": "defense"
|
||||
},
|
||||
|
|
@ -72,6 +82,7 @@
|
|||
"name": "Adamant",
|
||||
"alias": "adamant",
|
||||
"id": 11,
|
||||
"pid": 3,
|
||||
"increased": "attack",
|
||||
"decreased": "special_attack"
|
||||
},
|
||||
|
|
@ -79,6 +90,7 @@
|
|||
"name": "Impish",
|
||||
"alias": "impish",
|
||||
"id": 12,
|
||||
"pid": 8,
|
||||
"increased": "defense",
|
||||
"decreased": "special_attack"
|
||||
},
|
||||
|
|
@ -86,6 +98,7 @@
|
|||
"name": "Bashful",
|
||||
"alias": "bashful",
|
||||
"id": 13,
|
||||
"pid": 18,
|
||||
"increased": null,
|
||||
"decreased": null
|
||||
},
|
||||
|
|
@ -93,6 +106,7 @@
|
|||
"name": "Careful",
|
||||
"alias": "careful",
|
||||
"id": 14,
|
||||
"pid": 23,
|
||||
"increased": "special_defense",
|
||||
"decreased": "special_attack"
|
||||
},
|
||||
|
|
@ -100,6 +114,7 @@
|
|||
"name": "Rash",
|
||||
"alias": "rash",
|
||||
"id": 15,
|
||||
"pid": 19,
|
||||
"increased": "special_attack",
|
||||
"decreased": "special_defense"
|
||||
},
|
||||
|
|
@ -107,6 +122,7 @@
|
|||
"name": "Jolly",
|
||||
"alias": "jolly",
|
||||
"id": 16,
|
||||
"pid": 13,
|
||||
"increased": "speed",
|
||||
"decreased": "special_attack"
|
||||
},
|
||||
|
|
@ -114,6 +130,7 @@
|
|||
"name": "Naughty",
|
||||
"alias": "naughty",
|
||||
"id": 17,
|
||||
"pid": 4,
|
||||
"increased": "attack",
|
||||
"decreased": "special_defense"
|
||||
},
|
||||
|
|
@ -121,6 +138,7 @@
|
|||
"name": "Lax",
|
||||
"alias": "lax",
|
||||
"id": 18,
|
||||
"pid": 9,
|
||||
"increased": "defense",
|
||||
"decreased": "special_defense"
|
||||
},
|
||||
|
|
@ -128,6 +146,7 @@
|
|||
"name": "Quirky",
|
||||
"alias": "quirky",
|
||||
"id": 19,
|
||||
"pid": 24,
|
||||
"increased": null,
|
||||
"decreased": null
|
||||
},
|
||||
|
|
@ -135,6 +154,7 @@
|
|||
"name": "Naive",
|
||||
"alias": "naive",
|
||||
"id": 20,
|
||||
"pid": 14,
|
||||
"increased": "speed",
|
||||
"decreased": "special_defense"
|
||||
},
|
||||
|
|
@ -142,6 +162,7 @@
|
|||
"name": "Brave",
|
||||
"alias": "brave",
|
||||
"id": 21,
|
||||
"pid": 2,
|
||||
"increased": "attack",
|
||||
"decreased": "speed"
|
||||
},
|
||||
|
|
@ -149,6 +170,7 @@
|
|||
"name": "Relaxed",
|
||||
"alias": "relaxed",
|
||||
"id": 22,
|
||||
"pid": 7,
|
||||
"increased": "defense",
|
||||
"decreased": "speed"
|
||||
},
|
||||
|
|
@ -156,6 +178,7 @@
|
|||
"name": "Quiet",
|
||||
"alias": "quiet",
|
||||
"id": 23,
|
||||
"pid": 17,
|
||||
"increased": "special_attack",
|
||||
"decreased": "speed"
|
||||
},
|
||||
|
|
@ -163,6 +186,7 @@
|
|||
"name": "Sassy",
|
||||
"alias": "sassy",
|
||||
"id": 24,
|
||||
"pid": 22,
|
||||
"increased": "special_defense",
|
||||
"decreased": "speed"
|
||||
},
|
||||
|
|
@ -170,6 +194,7 @@
|
|||
"name": "Serious",
|
||||
"alias": "serious",
|
||||
"id": 25,
|
||||
"pid": 12,
|
||||
"increased": 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 json::JsonValue;
|
||||
use lazy_static::lazy_static;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
|
||||
use crate::{
|
||||
json::{read_characteristics, read_natures, read_pokedex},
|
||||
pokemon::*,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
impl Plugin for DatabasePlugin {
|
||||
|
|
@ -60,28 +45,7 @@ fn database_setup(
|
|||
mut nature_database: ResMut<Database<Nature>>,
|
||||
mut characteristic_database: ResMut<Database<Characteristic>>,
|
||||
) {
|
||||
let natures = parse_json_file(DATA_DIR.join("natures.json"));
|
||||
nature_database.populate_from_json(&natures);
|
||||
let pokedex = parse_json_file(DATA_DIR.join("pokedex.json"));
|
||||
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))
|
||||
nature_database.populate_from_json(&read_natures());
|
||||
pokemon_database.populate_from_json(&read_pokedex());
|
||||
characteristic_database.populate_from_json(&read_characteristics());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
use bevy::{prelude::*, window::WindowResolution};
|
||||
|
||||
pub mod database;
|
||||
pub mod inspector;
|
||||
pub mod pokemon;
|
||||
pub mod server;
|
||||
pub mod ui;
|
||||
mod calculator;
|
||||
mod server;
|
||||
mod ui;
|
||||
|
||||
fn main() {
|
||||
pub fn run() {
|
||||
App::new()
|
||||
.add_plugins(
|
||||
DefaultPlugins
|
||||
|
|
@ -21,8 +19,8 @@ fn main() {
|
|||
})
|
||||
.set(ImagePlugin::default_nearest()),
|
||||
)
|
||||
.add_plugin(database::DatabasePlugin)
|
||||
.add_plugin(inspector::InspectorPlugin)
|
||||
.add_plugin(crate::database::DatabasePlugin)
|
||||
.add_plugin(calculator::CalculatorPlugin)
|
||||
.add_plugin(ui::UiPlugin)
|
||||
.add_plugin(server::ServerPlugin)
|
||||
.run();
|
||||
|
|
@ -1,19 +1,25 @@
|
|||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_egui::EguiContexts;
|
||||
|
||||
use crate::{
|
||||
database::{load_url_asset, Database},
|
||||
pokemon::*,
|
||||
use crate::database::*;
|
||||
use crate::pokemon::*;
|
||||
|
||||
use super::{
|
||||
server::Request,
|
||||
ui::{UiAssets, UiState},
|
||||
};
|
||||
|
||||
pub struct InspectorPlugin;
|
||||
pub struct CalculatorPlugin;
|
||||
|
||||
impl Plugin for InspectorPlugin {
|
||||
impl Plugin for CalculatorPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<Inspector>()
|
||||
.insert_resource(Inspector::default())
|
||||
app.register_type::<Calculator>()
|
||||
.insert_resource(Calculator::default())
|
||||
.add_system(state_changed)
|
||||
.add_system(request_handler.in_base_set(CoreSet::PreUpdate));
|
||||
}
|
||||
|
|
@ -21,7 +27,7 @@ impl Plugin for InspectorPlugin {
|
|||
|
||||
#[derive(Reflect, Resource, Default, Debug, Clone)]
|
||||
#[reflect(Resource)]
|
||||
pub struct Inspector {
|
||||
pub struct Calculator {
|
||||
pub pokemon: Option<Pokemon>,
|
||||
pub nature: Option<Nature>,
|
||||
pub characteristic: Option<Characteristic>,
|
||||
|
|
@ -29,15 +35,15 @@ pub struct Inspector {
|
|||
}
|
||||
|
||||
fn state_changed(
|
||||
inspector: Res<Inspector>,
|
||||
calculator: Res<Calculator>,
|
||||
assets: Res<AssetServer>,
|
||||
mut ui_assets: ResMut<UiAssets>,
|
||||
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()) {
|
||||
let handle = load_url_asset(
|
||||
pokemon.get_url(),
|
||||
pokemon.sprite_url(),
|
||||
format!("cache/{name}.png", name = pokemon.key()).into(),
|
||||
&assets,
|
||||
);
|
||||
|
|
@ -53,7 +59,7 @@ fn state_changed(
|
|||
|
||||
fn request_handler(
|
||||
mut request_events: EventReader<Request>,
|
||||
mut inspector: ResMut<Inspector>,
|
||||
mut calculator: ResMut<Calculator>,
|
||||
mut ui: ResMut<UiState>,
|
||||
characteristics: Res<Database<Characteristic>>,
|
||||
natures: Res<Database<Nature>>,
|
||||
|
|
@ -62,10 +68,10 @@ fn request_handler(
|
|||
info!("{:#}", request);
|
||||
match request.urn.as_str() {
|
||||
"clear" => {
|
||||
inspector.pokemon = None;
|
||||
inspector.nature = None;
|
||||
inspector.characteristic = None;
|
||||
inspector.derived_stats = DerivedStats::default();
|
||||
calculator.pokemon = None;
|
||||
calculator.nature = None;
|
||||
calculator.characteristic = None;
|
||||
calculator.derived_stats = DerivedStats::default();
|
||||
ui.name = String::from("");
|
||||
ui.level = String::from("");
|
||||
ui.derived_stats.clear();
|
||||
|
|
@ -77,11 +83,11 @@ fn request_handler(
|
|||
}
|
||||
if let Some(level) = data["level"].as_i32() {
|
||||
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) = natures.map.get(&nature.to_lowercase()).cloned() {
|
||||
inspector.nature = Some(nature);
|
||||
calculator.nature = Some(nature);
|
||||
}
|
||||
}
|
||||
if let Some(characteristic) = data["characteristic"].as_str() {
|
||||
|
|
@ -90,13 +96,13 @@ fn request_handler(
|
|||
.get(&characteristic.to_lowercase())
|
||||
.cloned()
|
||||
{
|
||||
inspector.characteristic = Some(characteristic);
|
||||
calculator.characteristic = Some(characteristic);
|
||||
}
|
||||
}
|
||||
for stat in BaseStat::all() {
|
||||
if let Some(value) = data[stat.key()].as_i32() {
|
||||
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 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_TEXT_WIDTH: f32 = 150.0;
|
||||
|
|
@ -69,18 +72,18 @@ fn load_assets(mut ui_assets: ResMut<UiAssets>, assets: Res<AssetServer>) {
|
|||
fn handle_state(
|
||||
ui_state: Res<UiState>,
|
||||
pokemon: Res<Database<Pokemon>>,
|
||||
mut inspector: ResMut<Inspector>,
|
||||
mut calculator: ResMut<Calculator>,
|
||||
) {
|
||||
if ui_state.is_changed() {
|
||||
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(
|
||||
mut contexts: EguiContexts,
|
||||
mut inspector: ResMut<Inspector>,
|
||||
mut calculator: ResMut<Calculator>,
|
||||
ui_assets: Res<UiAssets>,
|
||||
mut ui_state: ResMut<UiState>,
|
||||
mut rendered_texture_id: Local<egui::TextureId>,
|
||||
|
|
@ -96,11 +99,11 @@ fn ui_system(
|
|||
egui::CentralPanel::default().show(contexts.ctx_mut(), |ui| {
|
||||
let sprite_size = egui::Vec2::new(128., 128.);
|
||||
|
||||
let pokemon = inspector.pokemon.clone();
|
||||
let pokemon = calculator.pokemon.clone();
|
||||
let pokemon = pokemon.as_ref();
|
||||
let nature = inspector.nature.clone();
|
||||
let nature = calculator.nature.clone();
|
||||
let nature = nature.as_ref();
|
||||
let characteristic = inspector.characteristic.clone();
|
||||
let characteristic = calculator.characteristic.clone();
|
||||
let characteristic = characteristic.as_ref();
|
||||
|
||||
// Pokemon
|
||||
|
|
@ -128,11 +131,11 @@ fn ui_system(
|
|||
egui::ComboBox::new("nature", "")
|
||||
.selected_text(format!("{}", nature.map_or("-", |c| &c.name)))
|
||||
.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();
|
||||
chars.sort_by_key(|c| c.name.clone());
|
||||
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", "")
|
||||
.selected_text(format!("{}", characteristic.map_or("-", |c| &c.name)))
|
||||
.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();
|
||||
chars.sort_by_key(|c| c.name.clone());
|
||||
for char in chars {
|
||||
ui.selectable_value(
|
||||
&mut inspector.characteristic,
|
||||
&mut calculator.characteristic,
|
||||
Some(char.clone()),
|
||||
&char.name,
|
||||
);
|
||||
|
|
@ -212,7 +215,7 @@ fn ui_system(
|
|||
if input.changed() {
|
||||
*value = digit_filter(value);
|
||||
if let Ok(value) = value.parse::<StatValue>() {
|
||||
inspector.derived_stats.level = Some(value);
|
||||
calculator.derived_stats.level = Some(value);
|
||||
}
|
||||
}
|
||||
if input.gained_focus() {
|
||||
|
|
@ -318,7 +321,7 @@ fn ui_system(
|
|||
*value = digit_filter(value);
|
||||
if let (Ok(value), derived) = (
|
||||
value.parse::<StatValue>(),
|
||||
inspector.derived_stats.value_mut(stat),
|
||||
calculator.derived_stats.value_mut(stat),
|
||||
) {
|
||||
*derived = Some(value);
|
||||
}
|
||||
|
|
@ -330,8 +333,8 @@ fn ui_system(
|
|||
|
||||
let possible_ivs = if let (Some(pokemon), Some(level), Some(derived_stat)) = (
|
||||
pokemon,
|
||||
inspector.derived_stats.level,
|
||||
inspector.derived_stats.value(stat),
|
||||
calculator.derived_stats.level,
|
||||
calculator.derived_stats.value(stat),
|
||||
) {
|
||||
calculate_possible_ivs(
|
||||
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 std::{collections::HashMap, fmt};
|
||||
|
||||
use crate::database::TYPE_MAP;
|
||||
use crate::json::TYPE_MAP;
|
||||
|
||||
pub type BaseValue = u8;
|
||||
pub type StatValue = i32;
|
||||
|
|
@ -103,7 +103,7 @@ impl Pokemon {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_url(&self) -> String {
|
||||
pub fn sprite_url(&self) -> String {
|
||||
format!(
|
||||
"https://img.pokemondb.net/sprites/{gen}/normal/{name}.png",
|
||||
gen = self.get_sprite_gen(),
|
||||
|
|
@ -183,6 +183,18 @@ impl BaseStat {
|
|||
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 {
|
||||
|
|
@ -238,6 +250,7 @@ impl GetKey for Type {
|
|||
#[derive(Default, Debug, Clone, Reflect, FromReflect, PartialEq)]
|
||||
pub struct Nature {
|
||||
pub id: u8,
|
||||
pub pid: u8,
|
||||
pub name: String,
|
||||
pub alias: String,
|
||||
pub increased: Option<BaseStat>,
|
||||
|
|
@ -260,6 +273,7 @@ impl FromJson for Nature {
|
|||
fn from_json(json: &json::JsonValue) -> Option<Self> {
|
||||
Some(Self {
|
||||
id: json["id"].as_u8()?,
|
||||
pid: json["pid"].as_u8()?,
|
||||
name: json["name"].as_str()?.to_string(),
|
||||
alias: json["alias"].as_str()?.to_string(),
|
||||
increased: json["increased"]
|
||||
|
|
|
|||
Loading…
Reference in New Issue