diff --git a/src/ship/drops/generic_armor.rs b/src/ship/drops/generic_armor.rs index e69de29..4562400 100644 --- a/src/ship/drops/generic_armor.rs +++ b/src/ship/drops/generic_armor.rs @@ -0,0 +1,125 @@ +use serde::{Serialize, Deserialize}; +use rand::{Rng, SeedableRng}; +use rand::distributions::{WeightedIndex, Distribution}; + +use crate::entity::item::{ItemDetail, Armor as ArmorDetail}; +use crate::entity::item::armor::{ArmorType, Armor}; +use crate::ship::room::{Difficulty, Episode}; +use crate::ship::map::MapVariantType; +use crate::entity::character::SectionID; +use crate::ship::drops::load_data_file; + + + + + + + + + + + + + +#[derive(Debug, Serialize, Deserialize)] +struct ArmorRankRates { + rank0: u32, + rank1: u32, + rank2: u32, + rank3: u32, + rank4: u32, +} + +#[derive(Debug, Serialize, Deserialize)] +struct ArmorSlotRanks { + slot0: u32, + slot1: u32, + slot2: u32, + slot3: u32, + slot4: u32, +} + + + +#[derive(Debug, Serialize, Deserialize)] +pub struct GenericArmorTable { + rank_rates: ArmorRankRates, + slot_rates: ArmorSlotRanks, + armor_set: u32, +} + + +impl GenericArmorTable { + pub fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> GenericArmorTable { + load_data_file(episode, difficulty, section_id, "armor_rate.toml") + } + + fn armor_type(&self, area_map: &MapVariantType, rng: &mut R) -> ArmorType { + let rank_weights = WeightedIndex::new(&[self.rank_rates.rank0, self.rank_rates.rank1, self.rank_rates.rank2, + self.rank_rates.rank3, self.rank_rates.rank4]).unwrap(); + let rank = rank_weights.sample(rng) as i32; + let armor_level = std::cmp::max(0i32, self.armor_set as i32 - 3i32 + rank + area_map.area_value().unwrap_or(0) as i32); + match armor_level { + 0x00 => ArmorType::Frame, + 0x01 => ArmorType::Armor, + 0x02 => ArmorType::PsyArmor, + 0x03 => ArmorType::GigaFrame, + 0x04 => ArmorType::SoulFrame, + 0x05 => ArmorType::CrossArmor, + 0x06 => ArmorType::SolidFrame, + 0x07 => ArmorType::BraveArmor, + 0x08 => ArmorType::HyperFrame, + 0x09 => ArmorType::GrandArmor, + 0x0A => ArmorType::ShockFrame, + 0x0B => ArmorType::KingsFrame, + 0x0C => ArmorType::DragonFrame, + 0x0D => ArmorType::AbsorbArmor, + 0x0E => ArmorType::ProtectFrame, + 0x0F => ArmorType::GeneralArmor, + 0x10 => ArmorType::PerfectFrame, + 0x11 => ArmorType::ValiantFrame, + 0x12 => ArmorType::ImperialArmor, + 0x13 => ArmorType::HolinessArmor, + 0x14 => ArmorType::GuardianArmor, + 0x15 => ArmorType::DivinityArmor, + 0x16 => ArmorType::UltimateFrame, + 0x17 => ArmorType::CelestialArmor, + _ => panic!() + } + } + + fn slots(&self, area_map: &MapVariantType, rng: &mut R) -> usize { + let slot_weights = WeightedIndex::new(&[self.slot_rates.slot0, self.slot_rates.slot1, self.slot_rates.slot2, + self.slot_rates.slot3, self.slot_rates.slot4]).unwrap(); + slot_weights.sample(rng) + } + + // TODO: this needs the pmt file + fn dfp_modifier(&self, armor_type: &ArmorType, rng: &mut R) -> usize { + 0 + } + + // TODO: this needs the pmt file + fn evp_modifier(&self, armor_type: &ArmorType, rng: &mut R) -> usize { + 0 + } + + pub fn get_drop(&self, area_map: &MapVariantType, rng: &mut R) -> Option { + let armor_type = self.armor_type(area_map, rng); + let slots = self.slots(area_map, rng); + let dfp_modifier = self.dfp_modifier(&armor_type, rng); + let evp_modifier = self.dfp_modifier(&armor_type, rng); + + + Some(ItemDetail::Armor(ArmorDetail { + equipped: false, + armor: Armor { + armor: armor_type, + dfp: dfp_modifier as u8, + evp: evp_modifier as u8, + slots: slots as u8 + } + })) + } +} + diff --git a/src/ship/drops/generic_weapon.rs b/src/ship/drops/generic_weapon.rs index 42db571..4bfff93 100644 --- a/src/ship/drops/generic_weapon.rs +++ b/src/ship/drops/generic_weapon.rs @@ -1,6 +1,4 @@ use std::collections::{HashMap, BTreeMap}; -use std::path::PathBuf; -use std::fs::File; use std::io::Read; use serde::{Serialize, Deserialize}; use rand::{Rng, SeedableRng}; @@ -13,25 +11,9 @@ use crate::ship::monster::MonsterType; use crate::ship::room::{Difficulty, Episode}; use crate::ship::map::MapVariantType; use crate::entity::character::SectionID; +use crate::ship::drops::load_data_file; -fn data_file_path(episode: Episode, difficulty: Difficulty, section_id: SectionID, filename: &str) -> PathBuf { - let mut path = PathBuf::from("data/drops/"); - path.push(episode.to_string()); - path.push(difficulty.to_string().to_lowercase()); - path.push(section_id.to_string().to_lowercase()); - path.push(filename); - path -} - -fn load_data_file(episode: Episode, difficulty: Difficulty, section_id: SectionID, filename: &str) -> T { - let path = data_file_path(episode, difficulty, section_id, filename); - let mut f = File::open(path).unwrap(); - let mut s = String::new(); - f.read_to_string(&mut s); - - toml::from_str::(s.as_str()).unwrap() -} #[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Hash, Copy, Clone, Ord, PartialOrd)] pub enum WeaponDropType { @@ -56,7 +38,6 @@ pub struct WeaponRatio { inc: u32, } - #[derive(Debug, Serialize, Deserialize, Default, Clone)] pub struct WeaponRatios { saber: WeaponRatio, diff --git a/src/ship/drops/mod.rs b/src/ship/drops/mod.rs index 5a571a8..6a006aa 100644 --- a/src/ship/drops/mod.rs +++ b/src/ship/drops/mod.rs @@ -23,7 +23,27 @@ use crate::entity::item::unit::UnitType; use crate::entity::item::tool::ToolType; use crate::ship::map::MapVariantType; use crate::entity::character::SectionID; -pub use crate::ship::drops::generic_weapon::*; +use crate::ship::drops::generic_weapon::GenericWeaponTable; +use crate::ship::drops::generic_armor::GenericArmorTable; + + +fn data_file_path(episode: Episode, difficulty: Difficulty, section_id: SectionID, filename: &str) -> PathBuf { + let mut path = PathBuf::from("data/drops/"); + path.push(episode.to_string()); + path.push(difficulty.to_string().to_lowercase()); + path.push(section_id.to_string().to_lowercase()); + path.push(filename); + path +} + +pub fn load_data_file(episode: Episode, difficulty: Difficulty, section_id: SectionID, filename: &str) -> T { + let path = data_file_path(episode, difficulty, section_id, filename); + let mut f = File::open(path).unwrap(); + let mut s = String::new(); + f.read_to_string(&mut s); + + toml::from_str::(s.as_str()).unwrap() +} #[derive(Debug, Serialize, Deserialize, Copy, Clone)] @@ -72,7 +92,6 @@ pub struct RareDropConfigEntity { - /*#[derive(Serialize, Deserialize)] pub struct MonsterDar(pub HashMap); @@ -104,6 +123,7 @@ struct DropTable { rare_table: RareDropTable, monster_stats: HashMap, weapon_table: GenericWeaponTable, + armor_table: GenericArmorTable, rng: R, } @@ -124,6 +144,7 @@ impl DropTable { rare_table: RareDropTable::new(episode, difficulty, section_id), monster_stats: monster_stats, weapon_table: GenericWeaponTable::new(episode, difficulty, section_id), + armor_table: GenericArmorTable::new(episode, difficulty, section_id), rng: R::from_entropy(), } }