266 lines
8.2 KiB
Rust
266 lines
8.2 KiB
Rust
|
use engine::prelude::*;
|
||
|
|
||
|
use crate::{
|
||
|
config::{
|
||
|
attributes::{AgilitySettings, AttributeSettings, IntelligenceSettings, StrengthSettings},
|
||
|
items::ItemSettings,
|
||
|
},
|
||
|
damage_type::DamageType,
|
||
|
};
|
||
|
|
||
|
use super::{
|
||
|
attributes::{Agility, Attributes, Intelligence, Strength},
|
||
|
item_slots::ItemSlotContainer,
|
||
|
macros::AttributeAssociation,
|
||
|
statistic_types::StatisticType,
|
||
|
};
|
||
|
|
||
|
// --------------- elements ---------------
|
||
|
|
||
|
// Air
|
||
|
generate_stat!(AirResistance, u32, "Air Resistance");
|
||
|
associate_strength!(AirResistance);
|
||
|
|
||
|
generate_stat!(AirDamage, u32, "Air Damage");
|
||
|
associate_intelligence!(AirDamage);
|
||
|
|
||
|
// fire
|
||
|
generate_stat!(FireResistance, u32, "Fire Resistance");
|
||
|
associate_strength!(FireResistance);
|
||
|
|
||
|
generate_stat!(FireDamage, u32, "Fire Damage");
|
||
|
associate_intelligence!(FireDamage);
|
||
|
|
||
|
// water
|
||
|
generate_stat!(WaterResistance, u32, "Water Resistance");
|
||
|
associate_strength!(WaterResistance);
|
||
|
|
||
|
generate_stat!(WaterDamage, u32, "Water Damage");
|
||
|
associate_intelligence!(WaterDamage);
|
||
|
|
||
|
// physical
|
||
|
generate_stat!(Armor, u32, "Armor");
|
||
|
associate_agility!(Armor);
|
||
|
|
||
|
generate_stat!(PhysicalDamage, u32, "Physical Damage");
|
||
|
associate_strength!(PhysicalDamage);
|
||
|
|
||
|
// ---------------- special ---------------
|
||
|
|
||
|
// crit
|
||
|
generate_stat!(CriticalHitChance, f32, "Crit Chance");
|
||
|
associate_agility!(CriticalHitChance);
|
||
|
|
||
|
generate_stat!(CriticalHitDamage, f32, "Crit Damage");
|
||
|
associate_agility!(CriticalHitDamage);
|
||
|
|
||
|
// ----------------- base -----------------
|
||
|
|
||
|
// health
|
||
|
generate_stat!(Health, f32, "Health");
|
||
|
associate_strength!(Health);
|
||
|
|
||
|
impl std::ops::Add<HealthRegeneration> for Health {
|
||
|
type Output = Self;
|
||
|
|
||
|
fn add(self, other: HealthRegeneration) -> Self {
|
||
|
Health(self.0 + other.0)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl std::ops::AddAssign<HealthRegeneration> for Health {
|
||
|
fn add_assign(&mut self, other: HealthRegeneration) {
|
||
|
self.0 += other.0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
generate_stat!(HealthRegeneration, f32, "Health Regeneration");
|
||
|
associate_strength!(HealthRegeneration);
|
||
|
|
||
|
// mana
|
||
|
generate_stat!(Mana, f32, "Mana");
|
||
|
associate_intelligence!(Mana);
|
||
|
|
||
|
impl std::ops::Add<ManaRegeneration> for Mana {
|
||
|
type Output = Self;
|
||
|
|
||
|
fn add(self, other: ManaRegeneration) -> Self {
|
||
|
Mana(self.0 + other.0)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl std::ops::AddAssign<ManaRegeneration> for Mana {
|
||
|
fn add_assign(&mut self, other: ManaRegeneration) {
|
||
|
self.0 += other.0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
generate_stat!(ManaRegeneration, f32, "Mana Regeneration");
|
||
|
associate_intelligence!(ManaRegeneration);
|
||
|
|
||
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||
|
pub struct Statistics {
|
||
|
// air
|
||
|
pub air_resistance: AirResistance,
|
||
|
pub air_damage: AirDamage,
|
||
|
|
||
|
// fire
|
||
|
pub fire_resistance: FireResistance,
|
||
|
pub fire_damage: FireDamage,
|
||
|
|
||
|
// water
|
||
|
pub water_resistance: WaterResistance,
|
||
|
pub water_damage: WaterDamage,
|
||
|
|
||
|
// physical
|
||
|
pub armor: Armor,
|
||
|
pub physical_damage: PhysicalDamage,
|
||
|
|
||
|
// crit
|
||
|
pub critical_hit_chance: CriticalHitChance,
|
||
|
pub critical_hit_damage: CriticalHitDamage,
|
||
|
|
||
|
// health
|
||
|
pub health: Health,
|
||
|
pub health_regeneration: HealthRegeneration,
|
||
|
|
||
|
// mana
|
||
|
pub mana: Mana,
|
||
|
pub mana_regeneration: ManaRegeneration,
|
||
|
}
|
||
|
|
||
|
impl Statistics {
|
||
|
pub fn update<'a, 'b>(
|
||
|
&mut self,
|
||
|
attributes: &mut Attributes,
|
||
|
attribute_settings: &AttributeSettings,
|
||
|
|
||
|
items: impl Into<Option<(&'a ItemSlotContainer, &'a ItemSettings)>>,
|
||
|
) {
|
||
|
*self = Self::default();
|
||
|
let items = items.into();
|
||
|
|
||
|
if let Some((items, item_settings)) = items {
|
||
|
let (agility, strength, intelligence) = items.collect_attribute_bonuses(item_settings);
|
||
|
|
||
|
attributes.bonus_agility = strength;
|
||
|
attributes.bonus_strength = agility;
|
||
|
attributes.bonus_intelligence = intelligence;
|
||
|
}
|
||
|
|
||
|
// agility
|
||
|
self.apply_agility(&attributes.agility(), &attribute_settings.agility_settings);
|
||
|
|
||
|
// strength
|
||
|
self.apply_strength(
|
||
|
&attributes.strength(),
|
||
|
&attribute_settings.strength_settings,
|
||
|
);
|
||
|
|
||
|
// intelligence
|
||
|
self.apply_intelligence(
|
||
|
&attributes.intelligence(),
|
||
|
&attribute_settings.intelligence_settings,
|
||
|
);
|
||
|
|
||
|
// apply items
|
||
|
if let Some((items, _)) = items {
|
||
|
let item_bonuses = items.collect_stat_bonuses();
|
||
|
|
||
|
for item_bonus in item_bonuses.into_iter() {
|
||
|
self.apply_bonus(item_bonus);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn calculate_resistance(&self, damage_type: DamageType) -> u32 {
|
||
|
match damage_type {
|
||
|
DamageType::Air => self.air_resistance.raw(),
|
||
|
DamageType::Fire => self.fire_resistance.raw(),
|
||
|
DamageType::Water => self.water_resistance.raw(),
|
||
|
DamageType::Physical => self.armor.raw(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn apply_agility(&mut self, agility: &Agility, agility_settings: &AgilitySettings) {
|
||
|
self.armor += Armor(agility.raw() * agility_settings.armor);
|
||
|
self.critical_hit_chance +=
|
||
|
CriticalHitChance(agility.raw() as f32 * agility_settings.crit_chance);
|
||
|
self.critical_hit_damage +=
|
||
|
CriticalHitDamage(agility.raw() as f32 * agility_settings.crit_damage);
|
||
|
}
|
||
|
|
||
|
fn apply_strength(&mut self, strength: &Strength, strength_settings: &StrengthSettings) {
|
||
|
self.health += Health(strength.raw() as f32 * strength_settings.health);
|
||
|
self.health_regeneration +=
|
||
|
HealthRegeneration(strength.raw() as f32 * strength_settings.health_regen);
|
||
|
self.physical_damage += PhysicalDamage(strength.raw() * strength_settings.physical_damage);
|
||
|
self.air_resistance += AirResistance(strength.raw() * strength_settings.air_resistance);
|
||
|
self.fire_resistance += FireResistance(strength.raw() * strength_settings.fire_resistance);
|
||
|
self.water_resistance +=
|
||
|
WaterResistance(strength.raw() * strength_settings.water_resistance);
|
||
|
}
|
||
|
|
||
|
fn apply_intelligence(
|
||
|
&mut self,
|
||
|
intelligence: &Intelligence,
|
||
|
intelligence_settings: &IntelligenceSettings,
|
||
|
) {
|
||
|
self.mana += Mana(intelligence.raw() as f32 * intelligence_settings.mana);
|
||
|
self.mana_regeneration +=
|
||
|
ManaRegeneration(intelligence.raw() as f32 * intelligence_settings.mana_regen);
|
||
|
self.air_damage += AirDamage(intelligence.raw() * intelligence_settings.air_damage);
|
||
|
self.fire_damage += FireDamage(intelligence.raw() * intelligence_settings.fire_damage);
|
||
|
self.water_damage += WaterDamage(intelligence.raw() * intelligence_settings.water_damage);
|
||
|
}
|
||
|
|
||
|
fn apply_bonus(&mut self, stat_type: StatisticType) {
|
||
|
match stat_type {
|
||
|
StatisticType::AirResistance(air_resistance) => self.air_resistance += air_resistance,
|
||
|
StatisticType::AirDamage(air_damage) => self.air_damage += air_damage,
|
||
|
|
||
|
StatisticType::FireResistance(fire_resistance) => {
|
||
|
self.fire_resistance += fire_resistance
|
||
|
}
|
||
|
StatisticType::FireDamage(fire_damage) => self.fire_damage += fire_damage,
|
||
|
|
||
|
StatisticType::WaterResistance(water_resistance) => {
|
||
|
self.water_resistance += water_resistance
|
||
|
}
|
||
|
StatisticType::WaterDamage(water_damage) => self.water_damage += water_damage,
|
||
|
|
||
|
StatisticType::Armor(armor) => self.armor += armor,
|
||
|
StatisticType::PhysicalDamage(physical_damage) => {
|
||
|
self.physical_damage += physical_damage
|
||
|
}
|
||
|
|
||
|
StatisticType::CriticalHitChance(crit_chance) => {
|
||
|
self.critical_hit_chance += crit_chance
|
||
|
}
|
||
|
StatisticType::CriticalHitDamage(crit_damage) => {
|
||
|
self.critical_hit_damage += crit_damage
|
||
|
}
|
||
|
|
||
|
StatisticType::Health(health) => self.health += health,
|
||
|
StatisticType::HealthRegeneration(health_regen) => {
|
||
|
self.health_regeneration += health_regen
|
||
|
}
|
||
|
|
||
|
StatisticType::Mana(mana) => self.mana += mana,
|
||
|
StatisticType::ManaRegeneration(mana_regen) => self.mana_regeneration += mana_regen,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl EntityComponent for Statistics {
|
||
|
fn name(&self) -> &str {
|
||
|
Self::debug_name()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ComponentDebug for Statistics {
|
||
|
fn debug_name() -> &'static str {
|
||
|
"Statistics"
|
||
|
}
|
||
|
}
|