diff --git a/src/ship/drops/generic_armor.rs b/src/ship/drops/generic_armor.rs index 4562400..96ab323 100644 --- a/src/ship/drops/generic_armor.rs +++ b/src/ship/drops/generic_armor.rs @@ -10,17 +10,6 @@ use crate::entity::character::SectionID; use crate::ship::drops::load_data_file; - - - - - - - - - - - #[derive(Debug, Serialize, Deserialize)] struct ArmorRankRates { rank0: u32, @@ -39,8 +28,6 @@ struct ArmorSlotRanks { slot4: u32, } - - #[derive(Debug, Serialize, Deserialize)] pub struct GenericArmorTable { rank_rates: ArmorRankRates, @@ -48,7 +35,6 @@ pub struct GenericArmorTable { 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") diff --git a/src/ship/drops/generic_shield.rs b/src/ship/drops/generic_shield.rs index e69de29..a9851c7 100644 --- a/src/ship/drops/generic_shield.rs +++ b/src/ship/drops/generic_shield.rs @@ -0,0 +1,90 @@ + +use serde::{Serialize, Deserialize}; +use rand::{Rng, SeedableRng}; +use rand::distributions::{WeightedIndex, Distribution}; + +use crate::entity::item::{ItemDetail, Shield as ShieldDetail}; +use crate::entity::item::shield::{ShieldType, Shield}; +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 ShieldRankRates { + rank0: u32, + rank1: u32, + rank2: u32, + rank3: u32, + rank4: u32, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct GenericShieldTable { + rank_rates: ShieldRankRates, + shield_set: u32, +} + +impl GenericShieldTable { + pub fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> GenericShieldTable { + load_data_file(episode, difficulty, section_id, "shield_rate.toml") + } + + fn shield_type(&self, area_map: &MapVariantType, rng: &mut R) -> ShieldType { + 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 shield_level = std::cmp::max(0i32, self.shield_set as i32 - 3i32 + rank + area_map.area_value().unwrap_or(0) as i32); + match shield_level { + 0x00 => ShieldType::Barrier, + 0x01 => ShieldType::Shield, + 0x02 => ShieldType::CoreShield, + 0x03 => ShieldType::GigaShield, + 0x04 => ShieldType::SoulBarrier, + 0x05 => ShieldType::HardShield, + 0x06 => ShieldType::BraveBarrier, + 0x07 => ShieldType::SolidShield, + 0x08 => ShieldType::FlameBarrier, + 0x09 => ShieldType::PlasmaBarrier, + 0x0A => ShieldType::FreezeBarrier, + 0x0B => ShieldType::PsychicBarrier, + 0x0C => ShieldType::GeneralShield, + 0x0D => ShieldType::ProtectBarrier, + 0x0E => ShieldType::GloriousShield, + 0x0F => ShieldType::ImperialBarrier, + 0x10 => ShieldType::GuardianShield, + 0x11 => ShieldType::DivinityBarrier, + 0x12 => ShieldType::UltimateShield, + 0x13 => ShieldType::SpiritualShield, + 0x14 => ShieldType::CelestialShield, + _ => panic!(), + } + } + + // TODO: this needs the pmt file + fn dfp_modifier(&self, shield_type: &ShieldType, rng: &mut R) -> usize { + 0 + } + + // TODO: this needs the pmt file + fn evp_modifier(&self, shield_type: &ShieldType, rng: &mut R) -> usize { + 0 + } + + pub fn get_drop(&self, area_map: &MapVariantType, rng: &mut R) -> Option { + let shield_type = self.shield_type(area_map, rng); + let dfp_modifier = self.dfp_modifier(&shield_type, rng); + let evp_modifier = self.dfp_modifier(&shield_type, rng); + + + Some(ItemDetail::Shield(ShieldDetail { + equipped: false, + shield: Shield { + shield: shield_type, + dfp: dfp_modifier as u8, + evp: evp_modifier as u8, + } + })) + } +} diff --git a/src/ship/drops/mod.rs b/src/ship/drops/mod.rs index 6a006aa..ed6c3a6 100644 --- a/src/ship/drops/mod.rs +++ b/src/ship/drops/mod.rs @@ -25,6 +25,7 @@ use crate::ship::map::MapVariantType; use crate::entity::character::SectionID; use crate::ship::drops::generic_weapon::GenericWeaponTable; use crate::ship::drops::generic_armor::GenericArmorTable; +use crate::ship::drops::generic_shield::GenericShieldTable; fn data_file_path(episode: Episode, difficulty: Difficulty, section_id: SectionID, filename: &str) -> PathBuf { @@ -124,6 +125,7 @@ struct DropTable { monster_stats: HashMap, weapon_table: GenericWeaponTable, armor_table: GenericArmorTable, + shield_table: GenericShieldTable, rng: R, } @@ -145,6 +147,7 @@ impl DropTable { monster_stats: monster_stats, weapon_table: GenericWeaponTable::new(episode, difficulty, section_id), armor_table: GenericArmorTable::new(episode, difficulty, section_id), + shield_table: GenericShieldTable::new(episode, difficulty, section_id), rng: R::from_entropy(), } } @@ -172,13 +175,12 @@ impl DropTable { fn generate_typed_drop(&mut self, map_area: &MapVariantType, monster: &MonsterDropStats) -> Option { match monster.drop_type { MonsterDropType::Weapon => self.weapon_table.get_drop(map_area, &mut self.rng), - MonsterDropType::Armor => self.generate_armor(), - MonsterDropType::Shield => self.generate_shield(), + MonsterDropType::Armor => self.armor_table.get_drop(map_area, &mut self.rng), + MonsterDropType::Shield => self.shield_table.get_drop(map_area, &mut self.rng), MonsterDropType::Unit => self.generate_unit(), MonsterDropType::None => None, } } - fn get_drop(&mut self, map_area: &MapVariantType, monster: &MonsterType) -> Option { //let mut rng = rand::thread_rng();