mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Made poise a float at interface of module.
This commit is contained in:
parent
0af6969d19
commit
942376f88c
@ -10,7 +10,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
slot::EquipSlot,
|
slot::EquipSlot,
|
||||||
},
|
},
|
||||||
poise::PoiseChange,
|
|
||||||
skills::SkillGroupKind,
|
skills::SkillGroupKind,
|
||||||
Alignment, Body, CharacterState, Combo, Energy, Health, HealthChange, Inventory, Ori,
|
Alignment, Body, CharacterState, Combo, Energy, Health, HealthChange, Inventory, Ori,
|
||||||
Player, Poise, SkillSet, Stats,
|
Player, Poise, SkillSet, Stats,
|
||||||
@ -281,8 +280,8 @@ impl Attack {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
CombatEffect::Poise(p) => {
|
CombatEffect::Poise(p) => {
|
||||||
let change = PoiseChange::from_value(*p, target.inventory);
|
let change = -Poise::apply_poise_reduction(*p, target.inventory);
|
||||||
if change.amount != 0 {
|
if change.abs() > Poise::POISE_EPSILON {
|
||||||
emit(ServerEvent::PoiseChange {
|
emit(ServerEvent::PoiseChange {
|
||||||
entity: target.entity,
|
entity: target.entity,
|
||||||
change,
|
change,
|
||||||
@ -409,8 +408,8 @@ impl Attack {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
CombatEffect::Poise(p) => {
|
CombatEffect::Poise(p) => {
|
||||||
let change = PoiseChange::from_value(p, target.inventory);
|
let change = -Poise::apply_poise_reduction(p, target.inventory);
|
||||||
if change.amount != 0 {
|
if change.abs() > Poise::POISE_EPSILON {
|
||||||
emit(ServerEvent::PoiseChange {
|
emit(ServerEvent::PoiseChange {
|
||||||
entity: target.entity,
|
entity: target.entity,
|
||||||
change,
|
change,
|
||||||
|
@ -774,7 +774,7 @@ impl Body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn base_poise(&self) -> u32 {
|
pub fn base_poise(&self) -> u16 {
|
||||||
match self {
|
match self {
|
||||||
Body::Humanoid(_) => 100,
|
Body::Humanoid(_) => 100,
|
||||||
Body::BipedLarge(biped_large) => match biped_large.species {
|
Body::BipedLarge(biped_large) => match biped_large.species {
|
||||||
|
@ -91,7 +91,7 @@ pub use self::{
|
|||||||
},
|
},
|
||||||
player::DisconnectReason,
|
player::DisconnectReason,
|
||||||
player::Player,
|
player::Player,
|
||||||
poise::{Poise, PoiseChange, PoiseSource, PoiseState},
|
poise::{Poise, PoiseState},
|
||||||
projectile::{Projectile, ProjectileConstructor},
|
projectile::{Projectile, ProjectileConstructor},
|
||||||
shockwave::{Shockwave, ShockwaveHitEntities},
|
shockwave::{Shockwave, ShockwaveHitEntities},
|
||||||
skills::{Skill, SkillGroup, SkillGroupKind, SkillSet},
|
skills::{Skill, SkillGroup, SkillGroupKind, SkillSet},
|
||||||
|
@ -1,94 +1,42 @@
|
|||||||
use crate::comp::{
|
use crate::{
|
||||||
|
comp::{
|
||||||
|
self,
|
||||||
inventory::item::{armor::Protection, ItemKind},
|
inventory::item::{armor::Protection, ItemKind},
|
||||||
Body, Inventory,
|
Inventory,
|
||||||
|
},
|
||||||
|
util::Dir,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, DerefFlaggedStorage};
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
|
use std::ops::Mul;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
/// A change in the poise component. Stores the amount as a signed
|
|
||||||
/// integer to allow for added or removed poise. Also has a field to
|
|
||||||
/// label where the poise change came from.
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct PoiseChange {
|
|
||||||
/// Value of the change in poise
|
|
||||||
pub amount: i32,
|
|
||||||
/// Source of change in poise
|
|
||||||
pub source: PoiseSource,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PoiseChange {
|
|
||||||
/// Alters poise damage as a result of armor poise damage reduction
|
|
||||||
pub fn modify_poise_damage(self, inventory: Option<&Inventory>) -> PoiseChange {
|
|
||||||
let poise_damage_reduction = inventory.map_or(0.0, Poise::compute_poise_damage_reduction);
|
|
||||||
let poise_damage = self.amount as f32 * (1.0 - poise_damage_reduction);
|
|
||||||
// Add match on poise source when different calculations per source
|
|
||||||
// are needed/wanted
|
|
||||||
PoiseChange {
|
|
||||||
amount: poise_damage as i32,
|
|
||||||
source: self.source,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a poise change from a float
|
|
||||||
pub fn from_value(poise_damage: f32, inventory: Option<&Inventory>) -> Self {
|
|
||||||
let poise_damage_reduction = inventory.map_or(0.0, Poise::compute_poise_damage_reduction);
|
|
||||||
let poise_change = -poise_damage * (1.0 - poise_damage_reduction);
|
|
||||||
Self {
|
|
||||||
amount: poise_change as i32,
|
|
||||||
source: PoiseSource::Attack,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sources of poise change
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub enum PoiseSource {
|
|
||||||
LevelUp,
|
|
||||||
Attack,
|
|
||||||
Explosion,
|
|
||||||
Falling,
|
|
||||||
Revive,
|
|
||||||
Regen,
|
|
||||||
Other,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Poise component
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
/// Poise is represented by u32s within the module, but treated as a float by
|
||||||
|
/// the rest of the game.
|
||||||
|
// As a general rule, all input and output values to public functions should be
|
||||||
|
// floats rather than integers.
|
||||||
pub struct Poise {
|
pub struct Poise {
|
||||||
/// Base poise amount for this entity
|
// Current and base_max are scaled by 256 within this module compared to what is visible to
|
||||||
base_max: u32,
|
// outside this module. The scaling is done to allow poise to function as a fixed point while
|
||||||
/// Poise of entity at any given moment
|
// still having the advantages of being an integer. The scaling of 256 was chosen so that max
|
||||||
|
// poise could be u16::MAX - 1, and then the scaled poise could fit inside an f32 with no
|
||||||
|
// precision loss
|
||||||
|
/// Current poise is how much poise the entity currently has
|
||||||
current: u32,
|
current: u32,
|
||||||
/// Maximum poise of entity at a given time
|
/// Base max is the amount of poise the entity has without considering
|
||||||
|
/// temporary modifiers such as buffs
|
||||||
|
base_max: u32,
|
||||||
|
/// Maximum is the amount of poise the entity has after temporary modifiers
|
||||||
|
/// are considered
|
||||||
maximum: u32,
|
maximum: u32,
|
||||||
/// Last poise change, storing time since last change, the change itself,
|
/// Direction that the last poise change came from
|
||||||
/// and the knockback direction vector
|
pub last_change: Dir,
|
||||||
pub last_change: (f64, PoiseChange, Vec3<f32>),
|
|
||||||
/// Rate of poise regeneration per tick. Starts at zero and accelerates.
|
/// Rate of poise regeneration per tick. Starts at zero and accelerates.
|
||||||
pub regen_rate: f32,
|
pub regen_rate: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Poise {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
current: 0,
|
|
||||||
maximum: 0,
|
|
||||||
base_max: 0,
|
|
||||||
last_change: (
|
|
||||||
0.0,
|
|
||||||
PoiseChange {
|
|
||||||
amount: 0,
|
|
||||||
source: PoiseSource::Revive,
|
|
||||||
},
|
|
||||||
Vec3::zero(),
|
|
||||||
),
|
|
||||||
regen_rate: 0.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// States to define effects of a poise change
|
/// States to define effects of a poise change
|
||||||
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize, Eq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize, Eq, Hash)]
|
||||||
pub enum PoiseState {
|
pub enum PoiseState {
|
||||||
@ -105,95 +53,77 @@ pub enum PoiseState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Poise {
|
impl Poise {
|
||||||
/// Creates a new poise struct based on the body it is being assigned to
|
/// Maximum value allowed for poise before scaling
|
||||||
pub fn new(body: Body) -> Self {
|
const MAX_POISE: u16 = u16::MAX - 1;
|
||||||
let mut poise = Poise::default();
|
/// The maximum value allowed for current and maximum poise
|
||||||
poise.update_base_max(Some(body));
|
/// Maximum value is (u16:MAX - 1) * 256, which only requires 24 bits. This
|
||||||
poise.set_maximum(poise.base_max);
|
/// can fit into an f32 with no loss to precision
|
||||||
poise.set_to(poise.maximum, PoiseSource::Revive);
|
// Cast to u32 done as u32::from cannot be called inside constant
|
||||||
|
const MAX_SCALED_POISE: u32 = Self::MAX_POISE as u32 * Self::SCALING_FACTOR_INT;
|
||||||
|
/// Used when comparisons to poise are needed outside this module.
|
||||||
|
// This value is chosen as anything smaller than this is more precise than our
|
||||||
|
// units of poise.
|
||||||
|
pub const POISE_EPSILON: f32 = 0.5 / Self::MAX_SCALED_POISE as f32;
|
||||||
|
/// The amount poise is scaled by within this module
|
||||||
|
const SCALING_FACTOR_FLOAT: f32 = 256.;
|
||||||
|
const SCALING_FACTOR_INT: u32 = Self::SCALING_FACTOR_FLOAT as u32;
|
||||||
|
|
||||||
poise
|
/// Returns the current value of poise casted to a float
|
||||||
|
pub fn current(&self) -> f32 { self.current as f32 / Self::SCALING_FACTOR_FLOAT }
|
||||||
|
|
||||||
|
/// Returns the base maximum value of poise casted to a float
|
||||||
|
pub fn base_max(&self) -> f32 { self.base_max as f32 / Self::SCALING_FACTOR_FLOAT }
|
||||||
|
|
||||||
|
/// Returns the maximum value of poise casted to a float
|
||||||
|
pub fn maximum(&self) -> f32 { self.maximum as f32 / Self::SCALING_FACTOR_FLOAT }
|
||||||
|
|
||||||
|
/// Returns the fraction of poise an entity has remaining
|
||||||
|
pub fn fraction(&self) -> f32 { self.current() / self.maximum().max(1.0) }
|
||||||
|
|
||||||
|
/// Updates the maximum value for poise
|
||||||
|
pub fn update_maximum(&mut self, modifiers: comp::stats::StatsModifier) {
|
||||||
|
let maximum = modifiers
|
||||||
|
.compute_maximum(self.base_max())
|
||||||
|
.mul(Self::SCALING_FACTOR_FLOAT)
|
||||||
|
// NaN does not need to be handled here as rust will automatically change to 0 when casting to u32
|
||||||
|
.clamp(0.0, Self::MAX_SCALED_POISE as f32) as u32;
|
||||||
|
self.maximum = maximum;
|
||||||
|
self.current = self.current.min(self.maximum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns knockback as a Vec3
|
pub fn new(body: comp::Body) -> Self {
|
||||||
pub fn knockback(&self) -> Vec3<f32> { self.last_change.2 }
|
let poise = u32::from(body.base_poise()) * Self::SCALING_FACTOR_INT;
|
||||||
|
Poise {
|
||||||
/// Defines the poise states based on fraction of maximum poise
|
current: poise,
|
||||||
pub fn poise_state(&self) -> PoiseState {
|
base_max: poise,
|
||||||
if self.current >= 7 * self.maximum / 10 {
|
maximum: poise,
|
||||||
PoiseState::Normal
|
last_change: Dir::default(),
|
||||||
} else if self.current >= 5 * self.maximum / 10 {
|
regen_rate: 0.0,
|
||||||
PoiseState::Interrupted
|
|
||||||
} else if self.current >= 4 * self.maximum / 10 {
|
|
||||||
PoiseState::Stunned
|
|
||||||
} else if self.current >= 2 * self.maximum / 10 {
|
|
||||||
PoiseState::Dazed
|
|
||||||
} else {
|
|
||||||
PoiseState::KnockedDown
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the current poise value
|
pub fn change_by(&mut self, change: f32, impulse: Vec3<f32>) {
|
||||||
pub fn current(&self) -> u32 { self.current }
|
self.current = (((self.current() + change).clamp(0.0, f32::from(Self::MAX_POISE))
|
||||||
|
* Self::SCALING_FACTOR_FLOAT) as u32)
|
||||||
/// Gets the maximum poise value
|
.min(self.maximum);
|
||||||
pub fn maximum(&self) -> u32 { self.maximum }
|
self.last_change = Dir::from_unnormalized(impulse).unwrap_or_default();
|
||||||
|
|
||||||
/// Gets the base_max value
|
|
||||||
pub fn base_max(&self) -> u32 { self.base_max }
|
|
||||||
|
|
||||||
/// Sets the poise value to a provided value. First cuts off the value
|
|
||||||
/// at the maximum. In most cases change_by() should be used.
|
|
||||||
pub fn set_to(&mut self, amount: u32, cause: PoiseSource) {
|
|
||||||
let amount = amount.min(self.maximum);
|
|
||||||
self.last_change = (
|
|
||||||
0.0,
|
|
||||||
PoiseChange {
|
|
||||||
amount: amount as i32 - self.current as i32,
|
|
||||||
source: cause,
|
|
||||||
},
|
|
||||||
Vec3::zero(),
|
|
||||||
);
|
|
||||||
self.current = amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the current poise due to an in-game effect.
|
|
||||||
pub fn change_by(&mut self, change: PoiseChange, impulse: Vec3<f32>) {
|
|
||||||
self.current = ((self.current as i32 + change.amount).max(0) as u32).min(self.maximum);
|
|
||||||
self.last_change = (
|
|
||||||
0.0,
|
|
||||||
PoiseChange {
|
|
||||||
amount: change.amount,
|
|
||||||
source: change.source,
|
|
||||||
},
|
|
||||||
impulse,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resets current value to maximum
|
|
||||||
pub fn reset(&mut self) { self.current = self.maximum; }
|
pub fn reset(&mut self) { self.current = self.maximum; }
|
||||||
|
|
||||||
/// Sets the maximum and updates the current value to max out at the new
|
/// Returns knockback as a Dir
|
||||||
/// maximum
|
/// Kept as helper function should additional fields ever be added to last
|
||||||
pub fn set_maximum(&mut self, amount: u32) {
|
/// change
|
||||||
self.maximum = amount;
|
pub fn knockback(&self) -> Dir { self.last_change }
|
||||||
self.current = self.current.min(self.maximum);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the `Poise` base_max
|
/// Defines the poise states based on current poise value
|
||||||
fn set_base_max(&mut self, amount: u32) {
|
pub fn poise_state(&self) -> PoiseState {
|
||||||
self.base_max = amount;
|
match self.current() {
|
||||||
self.current = self.current.min(self.maximum);
|
x if x > 70.0 => PoiseState::Normal,
|
||||||
}
|
x if x > 50.0 => PoiseState::Interrupted,
|
||||||
|
x if x > 40.0 => PoiseState::Stunned,
|
||||||
/// Resets the maximum to the base_max. Example use would be a potion
|
x if x > 20.0 => PoiseState::Dazed,
|
||||||
/// wearing off
|
_ => PoiseState::KnockedDown,
|
||||||
pub fn reset_max(&mut self) { self.maximum = self.base_max; }
|
|
||||||
|
|
||||||
/// Sets the base_max based on the entity `Body`
|
|
||||||
pub fn update_base_max(&mut self, body: Option<Body>) {
|
|
||||||
if let Some(body) = body {
|
|
||||||
self.set_base_max(body.base_poise());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,6 +148,14 @@ impl Poise {
|
|||||||
None => 1.0,
|
None => 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Modifies a poise change when optionally given an inventory to aid in
|
||||||
|
/// calculation of poise damage reduction
|
||||||
|
pub fn apply_poise_reduction(value: f32, inventory: Option<&Inventory>) -> f32 {
|
||||||
|
inventory.map_or(value, |inv| {
|
||||||
|
value * (1.0 - Poise::compute_poise_damage_reduction(inv))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Poise {
|
impl Component for Poise {
|
||||||
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Effect {
|
pub enum Effect {
|
||||||
Health(comp::HealthChange),
|
Health(comp::HealthChange),
|
||||||
PoiseChange(comp::PoiseChange),
|
Poise(f32),
|
||||||
Damage(combat::Damage),
|
Damage(combat::Damage),
|
||||||
Buff(BuffEffect),
|
Buff(BuffEffect),
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ impl Effect {
|
|||||||
pub fn info(&self) -> String {
|
pub fn info(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Effect::Health(c) => format!("{:+} health", c.amount),
|
Effect::Health(c) => format!("{:+} health", c.amount),
|
||||||
Effect::PoiseChange(c) => format!("{:+} poise", c.amount),
|
Effect::Poise(p) => format!("{:+} poise", p),
|
||||||
Effect::Damage(d) => format!("{:+}", d.value),
|
Effect::Damage(d) => format!("{:+}", d.value),
|
||||||
Effect::Buff(e) => format!("{:?} buff", e),
|
Effect::Buff(e) => format!("{:?} buff", e),
|
||||||
}
|
}
|
||||||
@ -31,7 +31,7 @@ impl Effect {
|
|||||||
pub fn is_harm(&self) -> bool {
|
pub fn is_harm(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Effect::Health(c) => c.amount < 0.0,
|
Effect::Health(c) => c.amount < 0.0,
|
||||||
Effect::PoiseChange(c) => c.amount < 0,
|
Effect::Poise(p) => *p < 0.0,
|
||||||
Effect::Damage(_) => true,
|
Effect::Damage(_) => true,
|
||||||
Effect::Buff(e) => !e.kind.is_buff(),
|
Effect::Buff(e) => !e.kind.is_buff(),
|
||||||
}
|
}
|
||||||
@ -42,8 +42,8 @@ impl Effect {
|
|||||||
Effect::Health(change) => {
|
Effect::Health(change) => {
|
||||||
change.amount *= modifier;
|
change.amount *= modifier;
|
||||||
},
|
},
|
||||||
Effect::PoiseChange(change) => {
|
Effect::Poise(poise) => {
|
||||||
change.amount = (change.amount as f32 * modifier) as i32;
|
*poise *= modifier;
|
||||||
},
|
},
|
||||||
Effect::Damage(damage) => {
|
Effect::Damage(damage) => {
|
||||||
damage.interpolate_damage(modifier, 0.0);
|
damage.interpolate_damage(modifier, 0.0);
|
||||||
|
@ -53,7 +53,7 @@ pub enum ServerEvent {
|
|||||||
},
|
},
|
||||||
PoiseChange {
|
PoiseChange {
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
change: comp::PoiseChange,
|
change: f32,
|
||||||
kb_dir: Vec3<f32>,
|
kb_dir: Vec3<f32>,
|
||||||
},
|
},
|
||||||
Delete(EcsEntity),
|
Delete(EcsEntity),
|
||||||
|
@ -173,7 +173,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
});
|
});
|
||||||
server_emitter.emit(ServerEvent::Knockback {
|
server_emitter.emit(ServerEvent::Knockback {
|
||||||
entity,
|
entity,
|
||||||
impulse: 5.0 * poise.knockback(),
|
impulse: 5.0 * *poise.knockback(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
PoiseState::Dazed => {
|
PoiseState::Dazed => {
|
||||||
@ -195,7 +195,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
});
|
});
|
||||||
server_emitter.emit(ServerEvent::Knockback {
|
server_emitter.emit(ServerEvent::Knockback {
|
||||||
entity,
|
entity,
|
||||||
impulse: 10.0 * poise.knockback(),
|
impulse: 10.0 * *poise.knockback(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
PoiseState::KnockedDown => {
|
PoiseState::KnockedDown => {
|
||||||
@ -217,7 +217,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
});
|
});
|
||||||
server_emitter.emit(ServerEvent::Knockback {
|
server_emitter.emit(ServerEvent::Knockback {
|
||||||
entity,
|
entity,
|
||||||
impulse: 10.0 * poise.knockback(),
|
impulse: 10.0 * *poise.knockback(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ use common::{
|
|||||||
comp::{
|
comp::{
|
||||||
self,
|
self,
|
||||||
skills::{GeneralSkill, Skill},
|
skills::{GeneralSkill, Skill},
|
||||||
Body, CharacterState, Combo, Energy, Health, Inventory, Poise, PoiseChange, PoiseSource,
|
Body, CharacterState, Combo, Energy, Health, Inventory, Poise, Pos, SkillSet, Stats,
|
||||||
Pos, SkillSet, Stats, StatsModifier,
|
StatsModifier,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -75,15 +75,10 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
// Increment last change timer
|
// Increment last change timer
|
||||||
healths.set_event_emission(false); // avoid unnecessary syncing
|
healths.set_event_emission(false); // avoid unnecessary syncing
|
||||||
poises.set_event_emission(false); // avoid unnecessary syncing
|
|
||||||
for mut health in (&mut healths).join() {
|
for mut health in (&mut healths).join() {
|
||||||
health.last_change.0 += f64::from(dt);
|
health.last_change.0 += f64::from(dt);
|
||||||
}
|
}
|
||||||
for mut poise in (&mut poises).join() {
|
|
||||||
poise.last_change.0 += f64::from(dt);
|
|
||||||
}
|
|
||||||
healths.set_event_emission(true);
|
healths.set_event_emission(true);
|
||||||
poises.set_event_emission(true);
|
|
||||||
|
|
||||||
// Update stats
|
// Update stats
|
||||||
for (entity, uid, stats, mut skill_set, mut health, pos, mut energy, inventory) in (
|
for (entity, uid, stats, mut skill_set, mut health, pos, mut energy, inventory) in (
|
||||||
@ -217,15 +212,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
if res_poise {
|
if res_poise {
|
||||||
let poise = &mut *poise;
|
let poise = &mut *poise;
|
||||||
poise.change_by(
|
poise.change_by(poise.regen_rate * dt, Vec3::zero());
|
||||||
PoiseChange {
|
|
||||||
amount: (poise.regen_rate * dt
|
|
||||||
+ POISE_REGEN_ACCEL * dt.powi(2) / 2.0)
|
|
||||||
as i32,
|
|
||||||
source: PoiseSource::Regen,
|
|
||||||
},
|
|
||||||
Vec3::zero(),
|
|
||||||
);
|
|
||||||
poise.regen_rate = (poise.regen_rate + POISE_REGEN_ACCEL * dt).min(10.0);
|
poise.regen_rate = (poise.regen_rate + POISE_REGEN_ACCEL * dt).min(10.0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@ use common::{
|
|||||||
chat::{KillSource, KillType},
|
chat::{KillSource, KillType},
|
||||||
inventory::item::MaterialStatManifest,
|
inventory::item::MaterialStatManifest,
|
||||||
object, Alignment, Auras, Body, CharacterState, Energy, Group, Health, HealthChange,
|
object, Alignment, Auras, Body, CharacterState, Energy, Group, Health, HealthChange,
|
||||||
Inventory, Player, Poise, PoiseChange, PoiseSource, Pos, SkillSet, Stats,
|
Inventory, Player, Poise, Pos, SkillSet, Stats,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
lottery::{LootSpec, Lottery},
|
lottery::{LootSpec, Lottery},
|
||||||
@ -40,12 +40,7 @@ use specs::{join::Join, saveload::MarkerAllocator, Builder, Entity as EcsEntity,
|
|||||||
use tracing::error;
|
use tracing::error;
|
||||||
use vek::{Vec2, Vec3};
|
use vek::{Vec2, Vec3};
|
||||||
|
|
||||||
pub fn handle_poise(
|
pub fn handle_poise(server: &Server, entity: EcsEntity, change: f32, knockback_dir: Vec3<f32>) {
|
||||||
server: &Server,
|
|
||||||
entity: EcsEntity,
|
|
||||||
change: PoiseChange,
|
|
||||||
knockback_dir: Vec3<f32>,
|
|
||||||
) {
|
|
||||||
let ecs = &server.state.ecs();
|
let ecs = &server.state.ecs();
|
||||||
if let Some(character_state) = ecs.read_storage::<CharacterState>().get(entity) {
|
if let Some(character_state) = ecs.read_storage::<CharacterState>().get(entity) {
|
||||||
// Entity is invincible to poise change during stunned/staggered character state
|
// Entity is invincible to poise change during stunned/staggered character state
|
||||||
@ -620,11 +615,8 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3<f32>)
|
|||||||
}
|
}
|
||||||
// Handle poise change
|
// Handle poise change
|
||||||
if let Some(mut poise) = ecs.write_storage::<comp::Poise>().get_mut(entity) {
|
if let Some(mut poise) = ecs.write_storage::<comp::Poise>().get_mut(entity) {
|
||||||
let poise_damage = PoiseChange {
|
let poise_damage = -(mass.0 * vel.magnitude_squared() / 1500.0);
|
||||||
amount: -(mass.0 * vel.magnitude_squared() / 1500.0) as i32,
|
let poise_change = Poise::apply_poise_reduction(poise_damage, inventories.get(entity));
|
||||||
source: PoiseSource::Falling,
|
|
||||||
};
|
|
||||||
let poise_change = poise_damage.modify_poise_damage(inventories.get(entity));
|
|
||||||
poise.change_by(poise_change, Vec3::unit_z());
|
poise.change_by(poise_change, Vec3::unit_z());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,9 +142,9 @@ impl StateExt for State {
|
|||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.map(|mut health| health.change_by(change));
|
.map(|mut health| health.change_by(change));
|
||||||
},
|
},
|
||||||
Effect::PoiseChange(poise_damage) => {
|
Effect::Poise(poise) => {
|
||||||
let inventories = self.ecs().read_storage::<Inventory>();
|
let inventories = self.ecs().read_storage::<Inventory>();
|
||||||
let change = poise_damage.modify_poise_damage(inventories.get(entity));
|
let change = Poise::apply_poise_reduction(poise, inventories.get(entity));
|
||||||
// Check to make sure the entity is not already stunned
|
// Check to make sure the entity is not already stunned
|
||||||
if let Some(character_state) = self
|
if let Some(character_state) = self
|
||||||
.ecs()
|
.ecs()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{Object, PhysicsState, PoiseChange, PoiseSource, Pos, Vel},
|
comp::{Object, PhysicsState, Pos, Vel},
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
@ -56,10 +56,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
kind: DamageKind::Energy,
|
kind: DamageKind::Energy,
|
||||||
value: 40.0,
|
value: 40.0,
|
||||||
})),
|
})),
|
||||||
RadiusEffect::Entity(Effect::PoiseChange(PoiseChange {
|
RadiusEffect::Entity(Effect::Poise(-100.0)),
|
||||||
source: PoiseSource::Explosion,
|
|
||||||
amount: -100,
|
|
||||||
})),
|
|
||||||
RadiusEffect::TerrainDestruction(4.0),
|
RadiusEffect::TerrainDestruction(4.0),
|
||||||
],
|
],
|
||||||
radius: 12.0,
|
radius: 12.0,
|
||||||
@ -151,10 +148,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
kind: DamageKind::Energy,
|
kind: DamageKind::Energy,
|
||||||
value: 5.0,
|
value: 5.0,
|
||||||
})),
|
})),
|
||||||
RadiusEffect::Entity(Effect::PoiseChange(PoiseChange {
|
RadiusEffect::Entity(Effect::Poise(-40.0)),
|
||||||
source: PoiseSource::Explosion,
|
|
||||||
amount: -40,
|
|
||||||
})),
|
|
||||||
RadiusEffect::TerrainDestruction(4.0),
|
RadiusEffect::TerrainDestruction(4.0),
|
||||||
],
|
],
|
||||||
radius: 12.0,
|
radius: 12.0,
|
||||||
|
@ -603,8 +603,8 @@ fn selected_entity_window(
|
|||||||
ui.label("State");
|
ui.label("State");
|
||||||
poise_state_label(ui, poise);
|
poise_state_label(ui, poise);
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
two_col_row(ui, "Current", format!("{}/{}", poise.current(), poise.maximum()));
|
two_col_row(ui, "Current", format!("{:.1}/{:.1}", poise.current(), poise.maximum()));
|
||||||
two_col_row(ui, "Base Max", poise.base_max().to_string());
|
two_col_row(ui, "Base Max", format!("{:.1}", poise.base_max()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user