Energy recovery stat functional.

This commit is contained in:
Sam 2021-05-18 20:42:14 -05:00 committed by Marcel Märtens
parent 58bd51a9e8
commit 6790b71d53
10 changed files with 91 additions and 27 deletions

View File

@ -7,6 +7,10 @@ ItemDef(
stats: (
protection: Invincible,
poise_resilience: Invincible,
energy_max: 9000,
energy_recovery: 9.0,
crit_chance: 1000.0,
stealth: 1000.0,
),
)
),

View File

@ -56,6 +56,7 @@ pub struct AttackerInfo<'a> {
pub uid: Uid,
pub energy: Option<&'a Energy>,
pub combo: Option<&'a Combo>,
pub inventory: Option<&'a Inventory>,
}
#[cfg(not(target_arch = "wasm32"))]
@ -213,11 +214,13 @@ impl Attack {
}
},
CombatEffect::EnergyReward(ec) => {
if let Some(attacker_entity) = attacker.map(|a| a.entity) {
if let Some(attacker) = attacker {
emit(ServerEvent::EnergyChange {
entity: attacker_entity,
entity: attacker.entity,
change: EnergyChange {
amount: *ec as i32,
amount: (*ec
* Energy::compute_energy_reward_mod(attacker.inventory))
as i32,
source: EnergySource::HitEnemy,
},
});
@ -348,11 +351,13 @@ impl Attack {
}
},
CombatEffect::EnergyReward(ec) => {
if let Some(attacker_entity) = attacker.map(|a| a.entity) {
if let Some(attacker) = attacker {
emit(ServerEvent::EnergyChange {
entity: attacker_entity,
entity: attacker.entity,
change: EnergyChange {
amount: ec as i32,
amount: (ec
* Energy::compute_energy_reward_mod(attacker.inventory))
as i32,
source: EnergySource::HitEnemy,
},
});

View File

@ -1,4 +1,4 @@
use crate::comp::Body;
use crate::comp::{self, Body, Inventory};
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
@ -120,6 +120,24 @@ impl Energy {
self.base_max = amount;
self.current = self.current.min(self.maximum);
}
/// Computes the energy reward modifer from worn armor
pub fn compute_energy_reward_mod(inventory: Option<&Inventory>) -> f32 {
use comp::item::ItemKind;
// Starts with a value of 1.0 when summing the stats from each armor piece, and
// defaults to a value of 1.0 if no inventory is equipped
inventory.map_or(1.0, |inv| {
inv.equipped_items()
.filter_map(|item| {
if let ItemKind::Armor(armor) = &item.kind() {
Some(armor.get_energy_recovery())
} else {
None
}
})
.fold(1.0, |a, b| a + b)
})
}
}
pub struct EnergyChange {

View File

@ -28,23 +28,52 @@ impl Armor {
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct Stats {
#[serde(default)]
protection: Protection,
#[serde(default)]
poise_resilience: Protection,
#[serde(default)]
energy_max: u32,
#[serde(default)]
energy_recovery: f32,
#[serde(default)]
crit_chance: f32,
#[serde(default)]
stealth: f32,
}
impl Stats {
// DO NOT USE UNLESS YOU KNOW WHAT YOU ARE DOING
// Added for csv import of stats
pub fn new(protection: Protection, poise_resilience: Protection) -> Self {
pub fn new(
protection: Protection,
poise_resilience: Protection,
energy_max: u32,
energy_recovery: f32,
crit_chance: f32,
stealth: f32,
) -> Self {
Self {
protection,
poise_resilience,
energy_max,
energy_recovery,
crit_chance,
stealth,
}
}
pub fn get_protection(&self) -> Protection { self.protection }
pub fn get_poise_resilience(&self) -> Protection { self.poise_resilience }
pub fn get_energy_max(&self) -> u32 { self.energy_max }
pub fn get_energy_recovery(&self) -> f32 { self.energy_recovery }
pub fn get_crit_chance(&self) -> f32 { self.crit_chance }
pub fn get_stealth(&self) -> f32 { self.stealth }
}
impl Sub<Stats> for Stats {
@ -54,6 +83,10 @@ impl Sub<Stats> for Stats {
Self {
protection: self.protection - other.protection,
poise_resilience: self.poise_resilience - other.poise_resilience,
energy_max: self.energy_max.saturating_sub(other.energy_max),
energy_recovery: self.energy_recovery - other.energy_recovery,
crit_chance: self.crit_chance - other.crit_chance,
stealth: self.stealth - other.stealth,
}
}
}
@ -64,6 +97,10 @@ pub enum Protection {
Normal(f32),
}
impl Default for Protection {
fn default() -> Self { Self::Normal(0.0) }
}
impl Sub for Protection {
type Output = Self;
@ -96,20 +133,20 @@ pub struct Armor {
}
impl Armor {
pub fn new(kind: ArmorKind, protection: Protection, poise_resilience: Protection) -> Self {
Self {
kind,
stats: Stats {
protection,
poise_resilience,
},
}
}
pub fn new(kind: ArmorKind, stats: Stats) -> Self { Self { kind, stats } }
pub fn get_protection(&self) -> Protection { self.stats.protection }
pub fn get_poise_resilience(&self) -> Protection { self.stats.poise_resilience }
pub fn get_energy_max(&self) -> u32 { self.stats.energy_max }
pub fn get_energy_recovery(&self) -> f32 { self.stats.energy_recovery }
pub fn get_crit_chance(&self) -> f32 { self.stats.crit_chance }
pub fn get_stealth(&self) -> f32 { self.stats.stealth }
#[cfg(test)]
pub fn test_armor(
kind: ArmorKind,

View File

@ -64,6 +64,8 @@ pub struct Stats {
pub power: f32,
pub poise_strength: f32,
pub speed: f32,
// Done for testing purposes, properly remove stat from weapons later
#[serde(skip)]
pub crit_chance: f32,
pub crit_mult: f32,
}

View File

@ -198,6 +198,7 @@ impl<'a> System<'a> for Sys {
uid,
energy: read_data.energies.get(entity),
combo: read_data.combos.get(entity),
inventory: read_data.inventories.get(entity),
});
let target_info = TargetInfo {

View File

@ -146,6 +146,7 @@ impl<'a> System<'a> for Sys {
uid: *uid,
energy: read_data.energies.get(attacker),
combo: read_data.combos.get(attacker),
inventory: read_data.inventories.get(attacker),
});
let target_info = TargetInfo {

View File

@ -135,6 +135,7 @@ impl<'a> System<'a> for Sys {
uid,
energy: read_data.energies.get(entity),
combo: read_data.combos.get(entity),
inventory: read_data.inventories.get(entity),
}
});

View File

@ -194,6 +194,7 @@ impl<'a> System<'a> for Sys {
uid,
energy: read_data.energies.get(entity),
combo: read_data.combos.get(entity),
inventory: read_data.inventories.get(entity),
});
let target_info = TargetInfo {

View File

@ -705,25 +705,18 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
RadiusEffect::Attack(attack) => {
let energies = &ecs.read_storage::<comp::Energy>();
let combos = &ecs.read_storage::<comp::Combo>();
let inventories = &ecs.read_storage::<comp::Inventory>();
for (
entity_b,
pos_b,
health_b,
(
body_b_maybe,
inventory_b_maybe,
stats_b_maybe,
ori_b_maybe,
char_state_b_maybe,
uid_b,
),
(body_b_maybe, stats_b_maybe, ori_b_maybe, char_state_b_maybe, uid_b),
) in (
&ecs.entities(),
&ecs.read_storage::<comp::Pos>(),
&ecs.read_storage::<comp::Health>(),
(
ecs.read_storage::<comp::Body>().maybe(),
ecs.read_storage::<comp::Inventory>().maybe(),
ecs.read_storage::<comp::Stats>().maybe(),
ecs.read_storage::<comp::Ori>().maybe(),
ecs.read_storage::<comp::CharacterState>().maybe(),
@ -767,12 +760,13 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
uid,
energy: energies.get(entity),
combo: combos.get(entity),
inventory: inventories.get(entity),
});
let target_info = combat::TargetInfo {
entity: entity_b,
uid: *uid_b,
inventory: inventory_b_maybe,
inventory: inventories.get(entity_b),
stats: stats_b_maybe,
health: Some(health_b),
pos: pos_b.0,