jake
5 years ago
5 changed files with 204 additions and 77 deletions
-
8src/ship/drops/generic_armor.rs
-
6src/ship/drops/generic_shield.rs
-
43src/ship/drops/generic_weapon.rs
-
69src/ship/drops/mod.rs
-
155src/ship/drops/rare_drop_table.rs
@ -0,0 +1,155 @@ |
|||
use std::collections::HashMap;
|
|||
use rand::Rng;
|
|||
use serde::{Serialize, Deserialize};
|
|||
use crate::entity::item::ItemDetail;
|
|||
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};
|
|||
use crate::entity::character::SectionID;
|
|||
use crate::ship::monster::MonsterType;
|
|||
use crate::ship::room::{Difficulty, Episode};
|
|||
use crate::ship::map::MapVariantType;
|
|||
use crate::ship::drops::load_data_file;
|
|||
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)]
|
|||
enum RareDropItem {
|
|||
Weapon(WeaponType),
|
|||
Armor(ArmorType),
|
|||
Shield(ShieldType),
|
|||
Unit(UnitType),
|
|||
Tool(ToolType),
|
|||
}
|
|||
|
|||
impl RareDropItem {
|
|||
fn from_string(name: String) -> RareDropItem {
|
|||
let parse_funcs: [Box<dyn Fn(&String) -> Option<RareDropItem>>; 5] = [
|
|||
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()?))),
|
|||
Box::new(|i| Some(RareDropItem::Tool(str::parse::<ToolType>(&i).ok()?)))];
|
|||
|
|||
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),
|
|||
}
|
|||
}
|
|||
|
|||
fn apply_item_stats<R: Rng>(&self, map_area: &MapVariantType, item: RareDropItem, rng: &mut R) -> ItemDetail {
|
|||
match item {
|
|||
RareDropItem::Weapon(weapon) => {
|
|||
ItemDetail::Weapon(Weapon {
|
|||
weapon: weapon,
|
|||
special: None,
|
|||
grind: 0,
|
|||
attrs: self.attribute_table.generate_rare_attributes(map_area, rng),
|
|||
equipped: false,
|
|||
tekked: false,
|
|||
})
|
|||
|
|||
},
|
|||
RareDropItem::Armor(armor) => {
|
|||
ItemDetail::Armor(Armor {
|
|||
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,
|
|||
equipped: false,
|
|||
})
|
|||
},
|
|||
RareDropItem::Shield(shield) => {
|
|||
ItemDetail::Shield(Shield {
|
|||
shield: shield,
|
|||
dfp: self.shield_stats.dfp_modifier(&shield, rng) as u8,
|
|||
evp: self.shield_stats.evp_modifier(&shield, rng) as u8,
|
|||
equipped: false,
|
|||
})
|
|||
},
|
|||
RareDropItem::Unit(unit) => {
|
|||
ItemDetail::Unit(Unit {
|
|||
unit: unit,
|
|||
modifier: None,
|
|||
equipped: false,
|
|||
})
|
|||
},
|
|||
RareDropItem::Tool(tool) => {
|
|||
ItemDetail::Tool(Tool {
|
|||
tool: tool,
|
|||
})
|
|||
}
|
|||
}
|
|||
}
|
|||
|
|||
pub fn get_drop<R: Rng>(&self, map_area: &MapVariantType, monster: &MonsterType, rng: &mut R) -> Option<ItemDetail> {
|
|||
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)
|
|||
})
|
|||
}
|
|||
}
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue