jake
5 years ago
5 changed files with 140 additions and 14 deletions
-
2src/entity/item/unit.rs
-
4src/ship/drops/generic_shield.rs
-
129src/ship/drops/generic_unit.rs
-
1src/ship/drops/mod.rs
-
18src/ship/item_stats.rs
@ -0,0 +1,129 @@ |
|||||
|
use std::collections::BTreeMap;
|
||||
|
use serde::{Serialize, Deserialize};
|
||||
|
use rand::{Rng, SeedableRng};
|
||||
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||
|
use rand::seq::IteratorRandom;
|
||||
|
|
||||
|
use crate::entity::item::{ItemDetail, Unit as UnitDetail};
|
||||
|
use crate::entity::item::unit::{UnitType, Unit, UnitModifier};
|
||||
|
use crate::ship::room::{Difficulty, Episode};
|
||||
|
use crate::ship::map::MapVariantType;
|
||||
|
use crate::entity::character::SectionID;
|
||||
|
use crate::ship::drops::load_data_file;
|
||||
|
use crate::ship::item_stats::{unit_stats, UnitStats};
|
||||
|
|
||||
|
|
||||
|
|
||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
struct UnitLevels {
|
||||
|
area1: u32,
|
||||
|
area2: u32,
|
||||
|
area3: u32,
|
||||
|
area4: u32,
|
||||
|
area5: u32,
|
||||
|
area6: u32,
|
||||
|
area7: u32,
|
||||
|
area8: u32,
|
||||
|
area9: u32,
|
||||
|
area10: u32,
|
||||
|
}
|
||||
|
|
||||
|
impl UnitLevels {
|
||||
|
fn level_by_area(&self, map_area: &MapVariantType) -> u32 {
|
||||
|
match map_area.area_value().unwrap() {
|
||||
|
0 => self.area1,
|
||||
|
1 => self.area2,
|
||||
|
2 => self.area3,
|
||||
|
3 => self.area1,
|
||||
|
4 => self.area1,
|
||||
|
5 => self.area6,
|
||||
|
6 => self.area7,
|
||||
|
7 => self.area8,
|
||||
|
8 => self.area9,
|
||||
|
9 => self.area10,
|
||||
|
_ => panic!()
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
pub struct GenericUnitTable {
|
||||
|
unit_levels: UnitLevels,
|
||||
|
unit_stats: BTreeMap<UnitType, UnitStats>,
|
||||
|
}
|
||||
|
|
||||
|
|
||||
|
|
||||
|
impl GenericUnitTable {
|
||||
|
pub fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> GenericUnitTable {
|
||||
|
GenericUnitTable {
|
||||
|
unit_levels: load_data_file(episode, difficulty, section_id, "unit_rate.toml"),
|
||||
|
unit_stats: unit_stats(),
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
fn unit_type_and_modifier<R: Rng>(&self, area_map: &MapVariantType, rng: &mut R) -> Option<(UnitType, Option<UnitModifier>)> {
|
||||
|
let level = self.unit_levels.level_by_area(area_map) as i32;
|
||||
|
if level == 0 {
|
||||
|
return None;
|
||||
|
}
|
||||
|
let units = self.unit_stats
|
||||
|
.iter()
|
||||
|
.filter(|(_, stats)| {
|
||||
|
stats.stars < 9
|
||||
|
})
|
||||
|
.filter_map(|(utype, stats)| {
|
||||
|
match level - stats.stars as i32 {
|
||||
|
-1 if stats.modifier != 0 => Some(vec![(*utype, Some(UnitModifier::Minus)), (*utype, Some(UnitModifier::MinusMinus))]),
|
||||
|
0 => Some(vec![(*utype, None)]),
|
||||
|
1 if stats.modifier != 0 => Some(vec![(*utype, Some(UnitModifier::Plus)), (*utype, Some(UnitModifier::PlusPlus))]),
|
||||
|
_ => None,
|
||||
|
}
|
||||
|
})
|
||||
|
.flatten();
|
||||
|
|
||||
|
Some(units.choose(rng).unwrap())
|
||||
|
}
|
||||
|
|
||||
|
pub fn get_drop<R: Rng>(&self, area_map: &MapVariantType, rng: &mut R) -> Option<ItemDetail> {
|
||||
|
let unit_type_modifier = self.unit_type_and_modifier(area_map, rng);
|
||||
|
|
||||
|
unit_type_modifier.map(|(unit_type, unit_modifier)| {
|
||||
|
ItemDetail::Unit(UnitDetail {
|
||||
|
equipped: false,
|
||||
|
unit: Unit {
|
||||
|
unit: unit_type,
|
||||
|
modifier: unit_modifier,
|
||||
|
}
|
||||
|
})
|
||||
|
})
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
|
||||
|
#[cfg(test)]
|
||||
|
mod test {
|
||||
|
use super::*;
|
||||
|
#[test]
|
||||
|
fn test_unit_drops() {
|
||||
|
let mut rng = rand_chacha::ChaCha20Rng::from_seed([23;32]);
|
||||
|
|
||||
|
let gut = GenericUnitTable::new(Episode::One, Difficulty::Normal, SectionID::Skyly);
|
||||
|
assert!(gut.get_drop(&MapVariantType::Forest1, &mut rng) == None);
|
||||
|
|
||||
|
let gut = GenericUnitTable::new(Episode::One, Difficulty::Hard, SectionID::Skyly);
|
||||
|
|
||||
|
let unit_tests = vec![(MapVariantType::Forest1, UnitType::ResistFreeze, Some(UnitModifier::PlusPlus)),
|
||||
|
(MapVariantType::Caves3, UnitType::GeneralTP, None),
|
||||
|
(MapVariantType::Mines2, UnitType::ResistEvil, Some(UnitModifier::PlusPlus)),
|
||||
|
(MapVariantType::DarkFalz, UnitType::DragonHP, Some(UnitModifier::Minus))];
|
||||
|
for (area, unit, umod) in unit_tests {
|
||||
|
assert!(gut.get_drop(&area, &mut rng) == Some(ItemDetail::Unit(UnitDetail {
|
||||
|
equipped: false,
|
||||
|
unit: Unit {
|
||||
|
unit: unit,
|
||||
|
modifier: umod,
|
||||
|
}
|
||||
|
})));
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue