mod drop_table; mod rare_drop_table; mod generic_weapon; mod generic_armor; mod generic_shield; mod generic_unit; mod tool_table; mod tech_table; use std::collections::HashMap; use std::fs::File; use std::path::PathBuf; use std::io::Read; use serde::{Serialize, Deserialize}; use rand::{Rng, SeedableRng}; use crate::entity::item::ItemDetail; 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::generic_weapon::GenericWeaponTable; use crate::ship::drops::generic_armor::GenericArmorTable; use crate::ship::drops::generic_shield::GenericShieldTable; use crate::ship::drops::generic_unit::GenericUnitTable; use crate::ship::drops::tool_table::ToolTable; use crate::ship::drops::rare_drop_table::RareDropTable; 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)] pub enum MonsterDropType { #[serde(rename = "weapon")] Weapon, #[serde(rename = "armor")] Armor, #[serde(rename = "shield")] Shield, #[serde(rename = "unit")] Unit, #[serde(rename = "none")] None, } #[derive(Debug, Serialize, Deserialize, Copy, Clone)] pub struct MonsterDropStats { pub dar: u32, pub drop_type: MonsterDropType, pub min_meseta: u32, pub max_meseta: u32, } enum ItemDropItem { Weapon, } struct ItemDrop { x: f32, y: f32, z: f32, item: ItemDropItem, } impl ItemDropItem { pub fn as_client_bytes(&self) -> u8 { 0 } } struct DropTable { monster_stats: HashMap, rare_table: RareDropTable, weapon_table: GenericWeaponTable, armor_table: GenericArmorTable, shield_table: GenericShieldTable, unit_table: GenericUnitTable, tool_table: ToolTable, rng: R, } impl DropTable { fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> DropTable { 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("grind_rate.toml"); let mut f = File::open(path).unwrap(); let mut s = String::new(); f.read_to_string(&mut s); let monster_stats = toml::from_str(&s).unwrap(); DropTable { monster_stats: monster_stats, rare_table: RareDropTable::new(episode, difficulty, section_id), weapon_table: GenericWeaponTable::new(episode, difficulty, section_id), armor_table: GenericArmorTable::new(episode, difficulty, section_id), shield_table: GenericShieldTable::new(episode, difficulty, section_id), unit_table: GenericUnitTable::new(episode, difficulty, section_id), tool_table: ToolTable::new(episode, difficulty, section_id), rng: R::from_entropy(), } } fn generate_meseta(&self, monster: &MonsterDropStats) -> Option { None } 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.armor_table.get_drop(map_area, &mut self.rng), MonsterDropType::Shield => self.shield_table.get_drop(map_area, &mut self.rng), MonsterDropType::Unit => self.unit_table.get_drop(map_area, &mut self.rng), MonsterDropType::None => None, } } fn get_drop(&mut self, map_area: &MapVariantType, monster: &MonsterType) -> Option { let monster_stat = *self.monster_stats.get(monster)?; let drop_anything = self.rng.gen_range(0, 100); if drop_anything > monster_stat.dar { return None; } if let Some(item) = self.rare_table.get_drop(map_area, &monster, &mut self.rng) { return Some(item); } let drop_type = self.rng.gen_range(0, 3); match drop_type { 0 => { self.generate_meseta(&monster_stat) }, 1 => { self.tool_table.get_drop(map_area, &mut self.rng) }, 2 => { self.generate_typed_drop(map_area, &monster_stat) }, _ => panic!() } } }