cool unique server features
This commit is contained in:
		
							parent
							
								
									52e2b555b0
								
							
						
					
					
						commit
						4fb78048e5
					
				@ -1,7 +1,7 @@
 | 
			
		||||
use serde::{Serialize, Deserialize};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
 | 
			
		||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
 | 
			
		||||
pub enum UnitType {
 | 
			
		||||
    KnightPower,
 | 
			
		||||
    GeneralPower,
 | 
			
		||||
 | 
			
		||||
@ -105,10 +105,6 @@ mod test {
 | 
			
		||||
        let mut rng = rand_chacha::ChaCha20Rng::from_seed([23;32]);
 | 
			
		||||
 | 
			
		||||
        let gst = GenericShieldTable::new(Episode::One, Difficulty::Ultimate, SectionID::Skyly);
 | 
			
		||||
        //println!("{:?}", gst.get_drop(&MapVariantType::Forest1, &mut rng));
 | 
			
		||||
        //println!("{:?}", gst.get_drop(&MapVariantType::Caves3, &mut rng));
 | 
			
		||||
        //println!("{:?}", gst.get_drop(&MapVariantType::Mines2, &mut rng));
 | 
			
		||||
        //println!("{:?}", gst.get_drop(&MapVariantType::DarkFalz, &mut rng));
 | 
			
		||||
 | 
			
		||||
        assert!(gst.get_drop(&MapVariantType::Forest1, &mut rng) == Some(ItemDetail::Shield(ShieldDetail {
 | 
			
		||||
            equipped: false,
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
                }
 | 
			
		||||
            })));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -3,6 +3,7 @@ mod rare_drop_table;
 | 
			
		||||
mod generic_weapon;
 | 
			
		||||
mod generic_armor;
 | 
			
		||||
mod generic_shield;
 | 
			
		||||
mod generic_unit;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use std::collections::{HashMap, BTreeMap};
 | 
			
		||||
use serde::{Serialize, Deserialize};
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::Read;
 | 
			
		||||
@ -54,12 +54,12 @@ pub struct ShieldStats {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct UnitStats {
 | 
			
		||||
    stars: u32,
 | 
			
		||||
    stat: u32,
 | 
			
		||||
    amount: u32,
 | 
			
		||||
    team_points: u32,
 | 
			
		||||
    modifier: u32,
 | 
			
		||||
pub struct UnitStats {
 | 
			
		||||
    pub stars: u32,
 | 
			
		||||
    pub stat: u32,
 | 
			
		||||
    pub amount: u32,
 | 
			
		||||
    pub team_points: u32,
 | 
			
		||||
    pub modifier: u32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -79,8 +79,8 @@ pub fn shield_stats() -> HashMap<ShieldType, ShieldStats> {
 | 
			
		||||
        }).collect()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn unit_stats() -> HashMap<UnitType, UnitStats> {
 | 
			
		||||
    let unit_stats: HashMap<String, UnitStats> = load_data_file("data/item_stats/unit_stats.toml");
 | 
			
		||||
pub fn unit_stats() -> BTreeMap<UnitType, UnitStats> {
 | 
			
		||||
    let unit_stats: BTreeMap<String, UnitStats> = load_data_file("data/item_stats/unit_stats.toml");
 | 
			
		||||
    unit_stats.iter()
 | 
			
		||||
        .map(|(name, stats)| {
 | 
			
		||||
            (name.parse().unwrap(), *stats)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user