mod drop_table; mod rare_drop_table; mod generic_weapon; mod generic_armor; mod generic_shield; 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 rand::distributions::{WeightedIndex, Distribution}; use crate::ship::monster::MonsterType; use crate::ship::room::{Difficulty, Episode}; use crate::entity::item::ItemDetail; use crate::entity::item::weapon::{WeaponType, Attribute, WeaponAttribute, WeaponSpecial}; use crate::entity::item::armor::ArmorType; use crate::entity::item::shield::ShieldType; 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::*; #[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 RareDropItem { Weapon(WeaponType), Armor(ArmorType), Shield(ShieldType), Unit(UnitType), Tool(ToolType), } struct RareDrop { rate: f32, item: RareDropItem } #[derive(Debug, Serialize, Deserialize)] pub struct RareDropConfigEntity { pub rate: f32, pub item: String, } /*#[derive(Serialize, Deserialize)] pub struct MonsterDar(pub HashMap); /*impl MonsterDar { fn from_f }*/*/ struct RareDropTable { } impl RareDropTable { fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> RareDropTable { RareDropTable { } } fn get_drop(&self, monster: &MonsterType) -> Option { None } } struct DropTable { rare_table: RareDropTable, monster_stats: HashMap, weapon_table: GenericWeaponTable, 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 { rare_table: RareDropTable::new(episode, difficulty, section_id), monster_stats: monster_stats, weapon_table: GenericWeaponTable::new(episode, difficulty, section_id), rng: R::from_entropy(), } } fn generate_meseta(&self, monster: &MonsterDropStats) -> Option { None } fn generate_tool(&self, map_area: &MapVariantType, monster: &MonsterDropStats) -> Option { None } fn generate_armor(&self) -> Option { None } fn generate_shield(&self) -> Option { None } fn generate_unit(&self) -> 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.generate_armor(), MonsterDropType::Shield => self.generate_shield(), 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(); 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(&monster) { return Some(item); } let drop_type = self.rng.gen_range(0, 3); match drop_type { 0 => { self.generate_meseta(&monster_stat) }, 1 => { self.generate_tool(map_area, &monster_stat) }, 2 => { self.generate_typed_drop(map_area, &monster_stat) }, _ => panic!() } } }