diff --git a/src/jsonmanager/json_manager.rs b/src/jsonmanager/json_manager.rs index cf2a906..2cbfa89 100644 --- a/src/jsonmanager/json_manager.rs +++ b/src/jsonmanager/json_manager.rs @@ -4,9 +4,15 @@ use std::collections::{HashMap, BTreeMap}; use serde::Deserialize; use serde::de::DeserializeOwned; + +use rand::{seq::IteratorRandom, thread_rng}; + use crate::jsonmanager::gather::Gather; +use crate::jsonmanager::material::Material; +use crate::jsonmanager::reliquary::{Reliquary, ReliquaryAffix, ReliquaryMainProp}; use crate::jsonmanager::shop_goods::ShopGoods; use crate::jsonmanager::shop_rotate::ShopRotate; +use crate::jsonmanager::weapon::Weapon; use super::avatar_skill_depot::AvatarSkillDepot; use super::entity_curve::EntityCurve; @@ -41,6 +47,13 @@ pub struct JsonManager { pub gathers: HashMap, pub shop_goods: HashMap>, pub shop_rotate: HashMap>, + pub weapons: HashMap, + pub reliquaries: HashMap, + + pub reliquary_main_prop_depot: HashMap>, + pub reliquary_affixes: HashMap>, + + pub materials: HashMap, } impl std::fmt::Debug for JsonManager { // TODO: fucking hack! @@ -62,6 +75,14 @@ impl JsonManager { let gathers: Vec = reader.read_json_list("Gather"); let shop_goods: Vec = reader.read_json_list("ShopGoods"); let shop_rotate: Vec = reader.read_json_list("ShopRotate"); + let weapons: Vec = reader.read_json_list("Weapon"); + + let reliquaries: Vec = reader.read_json_list("Reliquary"); + + let reliquary_main_prop_depot : Vec = reader.read_json_list("ReliquaryMainProp"); + let reliquary_affixes : Vec = reader.read_json_list("ReliquaryAffix"); + + let materials: Vec = reader.read_json_list("Material"); return JsonManager { reader: reader, @@ -76,8 +97,52 @@ impl JsonManager { .collect(), shop_rotate: group_nonconsec_by(shop_rotate, |sr| sr.rotate_id).into_iter() // TODO: we're grouping by rotate_id, not by ID! .collect(), + weapons: weapons.into_iter().map(|w| (w.id, w)).collect(), + reliquaries: reliquaries.into_iter().map(|r| (r.id, r)).collect(), + + reliquary_main_prop_depot: group_nonconsec_by(reliquary_main_prop_depot, |mp| mp.prop_depot_id).into_iter() + .collect(), // TODO: we're grouping by depot_id! + reliquary_affixes: group_nonconsec_by(reliquary_affixes, |a| a.depot_id).into_iter() + .collect(), // TODO: we're grouping by depot_id! + + materials: materials.into_iter().map(|m| (m.id, m)).collect(), }; } + + pub fn is_item_weapon(&self, item_id: u32) -> bool { + return self.weapons.contains_key(&item_id) + } + + pub fn is_item_reliquary(&self, item_id: u32) -> bool { + return self.reliquaries.contains_key(&item_id) + } + + pub fn is_item_material(&self, item_id: u32) -> bool { + return self.materials.contains_key(&item_id) + } + + // TODO: I'm not sure those two methods should belongs here! + pub fn roll_reliquary_stats_by_item_id(&self, item_id: u32) -> (u32, Vec) { + let reliquary = match self.reliquaries.get(&item_id) { + None => panic!("Rolling for stats of item {} which is not in reliquary dict!", item_id), + Some(reliquary) => reliquary, + }; + + return self.roll_reliquary_stats(reliquary.main_prop_depot_id, reliquary.append_prop_depot_id, reliquary.append_prop_num); + } + + pub fn roll_reliquary_stats(&self, main_depot_id: u32, affix_depot_id: u32, num_affices: usize) -> (u32, Vec) { + let mut rng = rand::thread_rng(); + + let main_depot = &self.reliquary_main_prop_depot[&main_depot_id]; + let affix_depot = &self.reliquary_affixes[&affix_depot_id]; + + let main_stat = main_depot.iter().choose(&mut rng).unwrap().id; + + let sub_stats: Vec = affix_depot.iter().choose_multiple(&mut rng, num_affices).iter().map(|a| a.id).collect(); // TODO: roll without weights! + + return (main_stat, sub_stats); + } } impl JsonReader { diff --git a/src/jsonmanager/material.rs b/src/jsonmanager/material.rs index e69de29..3eae5ed 100644 --- a/src/jsonmanager/material.rs +++ b/src/jsonmanager/material.rs @@ -0,0 +1,30 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Deserialize, Clone)] +#[serde(rename_all="PascalCase")] +pub struct MaterialUseParam { + pub use_op: Option, // TODO: that's an enum! + pub use_param: Vec, // Most of the time they are integers tho +} + +#[derive(Deserialize, Clone)] +#[serde(rename_all="PascalCase")] +pub struct Material { + pub id: u32, + #[serde(default)] + pub no_first_get_hint: bool, + pub rank: Option, + pub rank_level: Option, + pub stack_limit: Option, + pub max_use_count: Option, + pub gadget_id: Option, + + #[serde(default)] + pub use_on_gain: bool, + pub item_use: Vec, + pub use_target: Option, // TODO: that's an enum! + + /* + Misc fields omitted + */ +} \ No newline at end of file diff --git a/src/jsonmanager/mod.rs b/src/jsonmanager/mod.rs index b4f9b01..e0ac2c3 100644 --- a/src/jsonmanager/mod.rs +++ b/src/jsonmanager/mod.rs @@ -10,6 +10,9 @@ mod gadget_prop; mod gather; mod shop_goods; mod shop_rotate; +mod weapon; +mod reliquary; +mod material; pub use entity_curve::{CurveInfo,EntityCurve}; pub use shop_goods::ShopGoods; \ No newline at end of file diff --git a/src/jsonmanager/reliquary.rs b/src/jsonmanager/reliquary.rs new file mode 100644 index 0000000..bb95683 --- /dev/null +++ b/src/jsonmanager/reliquary.rs @@ -0,0 +1,37 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Deserialize, Clone)] +#[serde(rename_all="PascalCase")] +pub struct Reliquary { + pub id: u32, + pub main_prop_depot_id: u32, + pub append_prop_depot_id: u32, + #[serde(default)] + pub append_prop_num: usize, + pub set_id: Option, + /* + Other fields omitted + */ +} + +#[derive(Deserialize, Clone)] +#[serde(rename_all="PascalCase")] +pub struct ReliquaryMainProp { + pub id: u32, + pub prop_depot_id: u32, + pub prop_type: proto::FightPropType, + pub affix_name: String, + //pub weight: u32, // TODO: removed in 2.5.0! +} + +#[derive(Deserialize, Clone)] +#[serde(rename_all="PascalCase")] +pub struct ReliquaryAffix { + pub id: u32, + pub depot_id: u32, + pub group_id: u32, + pub prop_type: proto::FightPropType, + pub prop_value: f32, + //pub weight: u32, // TODO: removed in 2.5.0! + //pub upgrade_weight: u32, // TODO: removed in 2.5.0! +} \ No newline at end of file diff --git a/src/jsonmanager/weapon.rs b/src/jsonmanager/weapon.rs new file mode 100644 index 0000000..a43ab34 --- /dev/null +++ b/src/jsonmanager/weapon.rs @@ -0,0 +1,32 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Deserialize, Clone)] +#[serde(rename_all="PascalCase")] +pub struct WeaponProp { + pub r#type: proto::GrowCurveType, + // These two fields is missing sometimes + #[serde(default)] + pub init_value: f32, + #[serde(default)] + pub prop_type: proto::FightPropType, +} + +#[derive(Deserialize, Clone)] +#[serde(rename_all="PascalCase")] +pub struct Weapon { + pub id: u32, + + pub weapon_type: String, // TODO: that's an enum! + pub rank_level: u32, + pub skill_affix: Vec, + pub weapon_prop: Vec, + pub weapon_promote_id: u32, + pub story_id: Option, + pub awaken_costs: Vec, + #[serde(default)] + pub destroy_rule: String, // TODO: that's an enum! + pub destroy_return_material: Vec, + pub destroy_return_material_count: Vec, + pub weight: u32, + pub gadget_id: u32, +} \ No newline at end of file