elseware/src/ship/drops/rare_drop_table.rs

158 lines
5.4 KiB
Rust
Raw Normal View History

2020-03-26 00:06:28 -07:00
use std::collections::HashMap;
use rand::Rng;
use serde::{Serialize, Deserialize};
use crate::entity::item::weapon::{Weapon, WeaponType};
use crate::entity::item::armor::{Armor, ArmorType};
use crate::entity::item::shield::{Shield, ShieldType};
use crate::entity::item::unit::{Unit, UnitType};
use crate::entity::item::tool::{Tool, ToolType};
2020-03-28 12:06:24 -07:00
use crate::entity::item::mag::{Mag, MagType};
2020-03-26 00:06:28 -07:00
use crate::entity::character::SectionID;
use crate::ship::monster::MonsterType;
use crate::ship::room::{Difficulty, Episode};
2020-04-03 22:51:55 -07:00
use crate::ship::map::MapArea;
2020-03-29 11:54:58 -07:00
use crate::ship::drops::{ItemDropType, load_data_file};
2020-03-26 00:06:28 -07:00
use crate::ship::drops::generic_weapon::AttributeTable;
use crate::ship::drops::generic_armor::GenericArmorTable;
use crate::ship::drops::generic_shield::GenericShieldTable;
#[derive(Debug, Copy, Clone)]
2020-03-28 12:06:24 -07:00
pub enum RareDropItem {
2020-03-26 00:06:28 -07:00
Weapon(WeaponType),
Armor(ArmorType),
Shield(ShieldType),
Unit(UnitType),
Tool(ToolType),
2020-03-28 12:06:24 -07:00
Mag(MagType)
2020-03-26 00:06:28 -07:00
}
impl RareDropItem {
2020-03-28 12:06:24 -07:00
pub fn from_string(name: String) -> RareDropItem {
let parse_funcs: [Box<dyn Fn(&String) -> Option<RareDropItem>>; 6] = [
2020-03-26 00:06:28 -07:00
Box::new(|i| Some(RareDropItem::Weapon(str::parse::<WeaponType>(&i).ok()?))),
Box::new(|i| Some(RareDropItem::Armor(str::parse::<ArmorType>(&i).ok()?))),
Box::new(|i| Some(RareDropItem::Shield(str::parse::<ShieldType>(&i).ok()?))),
Box::new(|i| Some(RareDropItem::Unit(str::parse::<UnitType>(&i).ok()?))),
2020-03-28 12:06:24 -07:00
Box::new(|i| Some(RareDropItem::Tool(str::parse::<ToolType>(&i).ok()?))),
Box::new(|i| Some(RareDropItem::Mag(str::parse::<MagType>(&i).ok()?))),
];
2020-03-26 00:06:28 -07:00
for parse in parse_funcs.iter() {
match parse(&name) {
Some(k) => return k,
None => {},
}
}
panic!()
}
}
struct RareDropRate {
rate: f32,
item: RareDropItem
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RareDropConfigEntity {
pub rate: f32,
pub item: String,
}
pub struct RareDropTable {
rates: HashMap<MonsterType, Vec<RareDropRate>>,
attribute_table: AttributeTable,
armor_stats: GenericArmorTable,
shield_stats: GenericShieldTable,
}
impl RareDropTable {
pub fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> RareDropTable {
let cfg: HashMap<String, Vec<RareDropConfigEntity>> = load_data_file(episode, difficulty, section_id, "rare_rate.toml");
let rates = cfg.into_iter()
.map(|(monster, drops)| {
let monster = monster.parse().unwrap();
let drops = drops.into_iter().map(|drop| {
RareDropRate {
rate: drop.rate,
item: RareDropItem::from_string(drop.item),
}
}).collect();
(monster, drops)
}).collect();
RareDropTable {
rates: rates,
attribute_table: AttributeTable::new(episode, difficulty, section_id),
armor_stats: GenericArmorTable::new(episode, difficulty, section_id),
shield_stats: GenericShieldTable::new(episode, difficulty, section_id),
}
}
2020-04-03 22:51:55 -07:00
pub fn apply_item_stats<R: Rng>(&self, map_area: &MapArea, item: RareDropItem, rng: &mut R) -> ItemDropType {
2020-03-26 00:06:28 -07:00
match item {
RareDropItem::Weapon(weapon) => {
2020-03-29 11:54:58 -07:00
ItemDropType::Weapon(Weapon {
2020-03-26 00:06:28 -07:00
weapon: weapon,
special: None,
grind: 0,
attrs: self.attribute_table.generate_rare_attributes(map_area, rng),
tekked: false,
})
},
RareDropItem::Armor(armor) => {
2020-03-29 11:54:58 -07:00
ItemDropType::Armor(Armor {
2020-03-26 00:06:28 -07:00
armor: armor,
dfp: self.armor_stats.dfp_modifier(&armor, rng) as u8,
evp: self.armor_stats.evp_modifier(&armor, rng) as u8,
slots: self.armor_stats.slots(map_area, rng) as u8,
})
},
RareDropItem::Shield(shield) => {
2020-03-29 11:54:58 -07:00
ItemDropType::Shield(Shield {
2020-03-26 00:06:28 -07:00
shield: shield,
dfp: self.shield_stats.dfp_modifier(&shield, rng) as u8,
evp: self.shield_stats.evp_modifier(&shield, rng) as u8,
})
},
RareDropItem::Unit(unit) => {
2020-03-29 11:54:58 -07:00
ItemDropType::Unit(Unit {
2020-03-26 00:06:28 -07:00
unit: unit,
modifier: None,
})
},
RareDropItem::Tool(tool) => {
2020-03-29 11:54:58 -07:00
ItemDropType::Tool(Tool {
2020-03-26 00:06:28 -07:00
tool: tool,
})
2020-03-28 12:06:24 -07:00
},
2020-10-26 00:02:48 -06:00
RareDropItem::Mag(_mag) => {
2020-08-20 22:59:40 -06:00
ItemDropType::Mag(Mag::baby_mag(rng.gen_range(0, 18)))
2020-03-26 00:06:28 -07:00
}
}
}
2020-04-03 22:51:55 -07:00
pub fn get_drop<R: Rng>(&self, map_area: &MapArea, monster: &MonsterType, rng: &mut R) -> Option<ItemDropType> {
2020-03-26 00:06:28 -07:00
self.rates.get(monster)
.and_then(|drop_rates| {
drop_rates.iter()
.filter_map(|drop_rate| {
let rand: f32 = rng.gen();
if rand < drop_rate.rate {
Some(self.apply_item_stats(map_area, drop_rate.item, rng))
}
else {
None
}
}).nth(0)
})
}
}