use paste::paste; use std::collections::{BTreeMap, HashMap}; use data::{ElementType, FightPropType}; pub type FightPropValue = f32; #[derive(Default)] pub struct FightPropComp { pub fight_cur_prop_map: BTreeMap, pub fight_cal_prop_map: BTreeMap, } macro_rules! impl_get_cur { ($($ty: ident;)*) => { paste! { $(pub fn [](&self) -> FightPropValue { let percent = self.get_prop_value(FightPropType::[<$ty Percent>]) + 1.0; let percent = FightPropValue::max(percent, 0.0); let base = percent * self.get_prop_value(FightPropType::[]); base + self.get_prop_value(FightPropType::$ty) })* } }; } impl FightPropComp { pub fn get_fight_prop_value_map(&self) -> HashMap { let mut all_map: HashMap = self .fight_cur_prop_map .iter() .map(|(t, v)| (*t as u32, *v)) .collect(); all_map.extend( self.fight_cal_prop_map .iter() .map(|(t, v)| (*t as u32, *v)) .collect::>(), ); all_map } pub fn get_prop_value(&self, ty: FightPropType) -> FightPropValue { match ty { FightPropType::CurAttack => self.get_cur_attack(), FightPropType::CurDefense => self.get_cur_defense(), FightPropType::CurSpeed => self.get_cur_speed(), ty if Self::is_cur_prop_type(ty) => self .fight_cur_prop_map .get(&ty) .cloned() .unwrap_or_default(), ty => self.find_cal_prop_value(ty), } } impl_get_cur! { Attack; Defense; } pub fn get_cur_speed(&self) -> FightPropValue { let percent = self.get_prop_value(FightPropType::SpeedPercent) + 1.0; let percent = FightPropValue::max(percent, 0.0); percent * self.get_prop_value(FightPropType::BaseSpeed) } pub fn set_cur_hp(&mut self, hp: FightPropValue) { self.fight_cur_prop_map.insert(FightPropType::CurHp, hp); } pub fn set_max_energy(&mut self, elem_type: ElementType, max_energy: f32) { self.fight_cal_prop_map .insert(Self::get_max_energy_type(elem_type), max_energy); } pub fn set_cur_energy(&mut self, elem_type: ElementType, energy: f32) { self.fight_cur_prop_map .insert(Self::get_cur_energy_type(elem_type), energy); } fn find_cal_prop_value(&self, ty: FightPropType) -> FightPropValue { self.fight_cal_prop_map .get(&ty) .cloned() .unwrap_or_default() } fn is_cur_prop_type(ty: FightPropType) -> bool { ty >= FightPropType::CurFireEnergy && ty <= FightPropType::CurSpeed && ty != FightPropType::MaxHp } fn get_cur_energy_type(elem_type: ElementType) -> FightPropType { match elem_type { ElementType::Fire => FightPropType::CurFireEnergy, ElementType::Water => FightPropType::CurWaterEnergy, ElementType::Grass => FightPropType::CurGrassEnergy, ElementType::Electric => FightPropType::CurElecEnergy, ElementType::Ice => FightPropType::CurIceEnergy, ElementType::Wind => FightPropType::CurWindEnergy, ElementType::Rock => FightPropType::CurRockEnergy, _ => FightPropType::None, } } fn get_max_energy_type(elem_type: ElementType) -> FightPropType { match elem_type { ElementType::Fire => FightPropType::MaxFireEnergy, ElementType::Water => FightPropType::MaxWaterEnergy, ElementType::Grass => FightPropType::MaxGrassEnergy, ElementType::Electric => FightPropType::MaxElecEnergy, ElementType::Ice => FightPropType::MaxIceEnergy, ElementType::Wind => FightPropType::MaxWindEnergy, ElementType::Rock => FightPropType::MaxRockEnergy, _ => FightPropType::None, } } }