mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'sam/armor-fixes' into 'master'
Armor fixes See merge request veloren/veloren!1222
This commit is contained in:
commit
9156dbadb8
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Chest(CultistBlue),
|
kind: Chest(CultistBlue),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(5.0),
|
protection: Normal(30.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Chest(CultistPurple),
|
kind: Chest(CultistPurple),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(5.0),
|
protection: Normal(30.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Foot(Cultist),
|
kind: Foot(Cultist),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(1.0),
|
protection: Normal(6.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Hand(CultistBlue),
|
kind: Hand(CultistBlue),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(2.0),
|
protection: Normal(12.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Hand(CultistPurple),
|
kind: Hand(CultistPurple),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(2.0),
|
protection: Normal(12.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Pants(CultistBlue),
|
kind: Pants(CultistBlue),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(3.0),
|
protection: Normal(24.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Pants(CultistPurple),
|
kind: Pants(CultistPurple),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(3.0),
|
protection: Normal(24.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Shoulder(CultistBlue),
|
kind: Shoulder(CultistBlue),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(3.0),
|
protection: Normal(18.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -5,7 +5,7 @@ Item(
|
|||||||
(
|
(
|
||||||
kind: Shoulder(CultistPurple),
|
kind: Shoulder(CultistPurple),
|
||||||
stats: (
|
stats: (
|
||||||
protection: Normal(3.0),
|
protection: Normal(18.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
77
common/src/comp/damage.rs
Normal file
77
common/src/comp/damage.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use crate::comp::Loadout;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub const BLOCK_EFFICIENCY: f32 = 0.9;
|
||||||
|
|
||||||
|
pub struct Damage {
|
||||||
|
pub healthchange: f32,
|
||||||
|
pub source: DamageSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
pub enum DamageSource {
|
||||||
|
Melee,
|
||||||
|
Healing,
|
||||||
|
Projectile,
|
||||||
|
Explosion,
|
||||||
|
Falling,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Damage {
|
||||||
|
pub fn modify_damage(&mut self, block: bool, loadout: &Loadout) {
|
||||||
|
match self.source {
|
||||||
|
DamageSource::Melee => {
|
||||||
|
// Critical hit
|
||||||
|
if rand::random() {
|
||||||
|
self.healthchange *= 1.2;
|
||||||
|
}
|
||||||
|
// Block
|
||||||
|
if block {
|
||||||
|
self.healthchange *= 1.0 - BLOCK_EFFICIENCY
|
||||||
|
}
|
||||||
|
// Armor
|
||||||
|
self.healthchange *= 1.0 - loadout.get_damage_reduction();
|
||||||
|
|
||||||
|
// Min damage
|
||||||
|
if self.healthchange > -1.0 {
|
||||||
|
self.healthchange = -1.0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DamageSource::Projectile => {
|
||||||
|
// Critical hit
|
||||||
|
if rand::random() {
|
||||||
|
self.healthchange *= 1.2;
|
||||||
|
}
|
||||||
|
// Block
|
||||||
|
if block {
|
||||||
|
self.healthchange *= 1.0 - BLOCK_EFFICIENCY
|
||||||
|
}
|
||||||
|
// Armor
|
||||||
|
self.healthchange *= 1.0 - loadout.get_damage_reduction();
|
||||||
|
|
||||||
|
// Min damage
|
||||||
|
if self.healthchange > -1.0 {
|
||||||
|
self.healthchange = -1.0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DamageSource::Explosion => {
|
||||||
|
// Critical hit
|
||||||
|
if rand::random() {
|
||||||
|
self.healthchange *= 1.2;
|
||||||
|
}
|
||||||
|
// Block
|
||||||
|
if block {
|
||||||
|
self.healthchange *= 1.0 - BLOCK_EFFICIENCY
|
||||||
|
}
|
||||||
|
// Armor
|
||||||
|
self.healthchange *= 1.0 - loadout.get_damage_reduction();
|
||||||
|
|
||||||
|
// Min damage
|
||||||
|
if self.healthchange > -1.0 {
|
||||||
|
self.healthchange = -1.0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,7 @@
|
|||||||
// version in voxygen\src\meta.rs in order to reset save files to being empty
|
// version in voxygen\src\meta.rs in order to reset save files to being empty
|
||||||
|
|
||||||
use crate::comp::{
|
use crate::comp::{
|
||||||
body::object, projectile, Body, CharacterAbility, Gravity, HealthChange, HealthSource,
|
body::object, projectile, Body, CharacterAbility, Gravity, LightEmitter, Projectile,
|
||||||
LightEmitter, Projectile,
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -262,11 +261,7 @@ impl Tool {
|
|||||||
projectile: Projectile {
|
projectile: Projectile {
|
||||||
hit_solid: vec![projectile::Effect::Stick],
|
hit_solid: vec![projectile::Effect::Stick],
|
||||||
hit_entity: vec![
|
hit_entity: vec![
|
||||||
projectile::Effect::Damage(HealthChange {
|
projectile::Effect::Damage(-3),
|
||||||
// TODO: This should not be fixed (?)
|
|
||||||
amount: -3,
|
|
||||||
cause: HealthSource::Projectile { owner: None },
|
|
||||||
}),
|
|
||||||
projectile::Effect::Knockback(10.0),
|
projectile::Effect::Knockback(10.0),
|
||||||
projectile::Effect::RewardEnergy(100),
|
projectile::Effect::RewardEnergy(100),
|
||||||
projectile::Effect::Vanish,
|
projectile::Effect::Vanish,
|
||||||
@ -286,11 +281,7 @@ impl Tool {
|
|||||||
projectile: Projectile {
|
projectile: Projectile {
|
||||||
hit_solid: vec![projectile::Effect::Stick],
|
hit_solid: vec![projectile::Effect::Stick],
|
||||||
hit_entity: vec![
|
hit_entity: vec![
|
||||||
projectile::Effect::Damage(HealthChange {
|
projectile::Effect::Damage(-9),
|
||||||
// TODO: This should not be fixed (?)
|
|
||||||
amount: -9,
|
|
||||||
cause: HealthSource::Projectile { owner: None },
|
|
||||||
}),
|
|
||||||
projectile::Effect::Knockback(15.0),
|
projectile::Effect::Knockback(15.0),
|
||||||
projectile::Effect::RewardEnergy(50),
|
projectile::Effect::RewardEnergy(50),
|
||||||
projectile::Effect::Vanish,
|
projectile::Effect::Vanish,
|
||||||
@ -336,11 +327,7 @@ impl Tool {
|
|||||||
projectile: Projectile {
|
projectile: Projectile {
|
||||||
hit_solid: vec![projectile::Effect::Vanish],
|
hit_solid: vec![projectile::Effect::Vanish],
|
||||||
hit_entity: vec![
|
hit_entity: vec![
|
||||||
projectile::Effect::Damage(HealthChange {
|
projectile::Effect::Damage(-3),
|
||||||
// TODO: This should not be fixed (?)
|
|
||||||
amount: -3,
|
|
||||||
cause: HealthSource::Projectile { owner: None },
|
|
||||||
}),
|
|
||||||
projectile::Effect::RewardEnergy(150),
|
projectile::Effect::RewardEnergy(150),
|
||||||
projectile::Effect::Vanish,
|
projectile::Effect::Vanish,
|
||||||
],
|
],
|
||||||
|
@ -5,6 +5,7 @@ mod body;
|
|||||||
mod character_state;
|
mod character_state;
|
||||||
mod chat;
|
mod chat;
|
||||||
mod controller;
|
mod controller;
|
||||||
|
mod damage;
|
||||||
mod energy;
|
mod energy;
|
||||||
mod inputs;
|
mod inputs;
|
||||||
mod inventory;
|
mod inventory;
|
||||||
@ -32,6 +33,7 @@ pub use controller::{
|
|||||||
Climb, ControlAction, ControlEvent, Controller, ControllerInputs, Input, InventoryManip,
|
Climb, ControlAction, ControlEvent, Controller, ControllerInputs, Input, InventoryManip,
|
||||||
MountState, Mounting,
|
MountState, Mounting,
|
||||||
};
|
};
|
||||||
|
pub use damage::{Damage, DamageSource};
|
||||||
pub use energy::{Energy, EnergySource};
|
pub use energy::{Energy, EnergySource};
|
||||||
pub use inputs::CanBuild;
|
pub use inputs::CanBuild;
|
||||||
pub use inventory::{
|
pub use inventory::{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{comp, sync::Uid};
|
use crate::sync::Uid;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, FlaggedStorage};
|
use specs::{Component, FlaggedStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
@ -6,7 +6,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Effect {
|
pub enum Effect {
|
||||||
Damage(comp::HealthChange),
|
Damage(i32),
|
||||||
Knockback(f32),
|
Knockback(f32),
|
||||||
RewardEnergy(u32),
|
RewardEnergy(u32),
|
||||||
Explode { power: f32 },
|
Explode { power: f32 },
|
||||||
@ -25,21 +25,6 @@ pub struct Projectile {
|
|||||||
pub owner: Option<Uid>,
|
pub owner: Option<Uid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Projectile {
|
|
||||||
pub fn set_owner(&mut self, new_owner: Uid) {
|
|
||||||
self.owner = Some(new_owner);
|
|
||||||
for e in self.hit_solid.iter_mut().chain(self.hit_entity.iter_mut()) {
|
|
||||||
if let Effect::Damage(comp::HealthChange {
|
|
||||||
cause: comp::HealthSource::Projectile { owner, .. },
|
|
||||||
..
|
|
||||||
}) = e
|
|
||||||
{
|
|
||||||
*owner = Some(new_owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Component for Projectile {
|
impl Component for Projectile {
|
||||||
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ impl CharacterBehavior for Data {
|
|||||||
} else if !self.exhausted {
|
} else if !self.exhausted {
|
||||||
// Fire
|
// Fire
|
||||||
let mut projectile = self.projectile.clone();
|
let mut projectile = self.projectile.clone();
|
||||||
projectile.set_owner(*data.uid);
|
projectile.owner = Some(*data.uid);
|
||||||
update.server_events.push_front(ServerEvent::Shoot {
|
update.server_events.push_front(ServerEvent::Shoot {
|
||||||
entity: data.entity,
|
entity: data.entity,
|
||||||
dir: data.inputs.look_dir,
|
dir: data.inputs.look_dir,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
Alignment, Attacking, Body, CharacterState, HealthChange, HealthSource, Loadout, Ori, Pos,
|
Alignment, Attacking, Body, CharacterState, Damage, DamageSource, HealthChange,
|
||||||
Scale, Stats,
|
HealthSource, Loadout, Ori, Pos, Scale, Stats,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
sync::Uid,
|
sync::Uid,
|
||||||
@ -112,7 +112,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
&& ori2.angle_between(pos_b2 - pos2) < attack.max_angle + (rad_b / pos2.distance(pos_b2)).atan()
|
&& ori2.angle_between(pos_b2 - pos2) < attack.max_angle + (rad_b / pos2.distance(pos_b2)).atan()
|
||||||
{
|
{
|
||||||
// Weapon gives base damage
|
// Weapon gives base damage
|
||||||
let mut healthchange = attack.base_healthchange as f32;
|
let source = if attack.base_healthchange > 0 {
|
||||||
|
DamageSource::Healing
|
||||||
|
} else {
|
||||||
|
DamageSource::Melee
|
||||||
|
};
|
||||||
|
let mut damage = Damage {
|
||||||
|
healthchange: attack.base_healthchange as f32,
|
||||||
|
source,
|
||||||
|
};
|
||||||
let mut knockback = attack.knockback;
|
let mut knockback = attack.knockback;
|
||||||
|
|
||||||
// TODO: remove this, either it will remain unused or be used as a temporary
|
// TODO: remove this, either it will remain unused or be used as a temporary
|
||||||
@ -124,40 +132,30 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
// TODO: remove this when there is a better way to deal with alignment
|
// TODO: remove this when there is a better way to deal with alignment
|
||||||
// Don't heal NPCs
|
// Don't heal NPCs
|
||||||
if (healthchange > 0.0 && alignment_b_maybe
|
if (damage.healthchange > 0.0 && alignment_b_maybe
|
||||||
.map(|a| !a.is_friendly_to_players())
|
.map(|a| !a.is_friendly_to_players())
|
||||||
.unwrap_or(true))
|
.unwrap_or(true))
|
||||||
// Don't hurt pets
|
// Don't hurt pets
|
||||||
|| (healthchange < 0.0 && alignment_b_maybe
|
|| (damage.healthchange < 0.0 && alignment_b_maybe
|
||||||
.map(|b| Alignment::Owned(*uid).passive_towards(*b))
|
.map(|b| Alignment::Owned(*uid).passive_towards(*b))
|
||||||
.unwrap_or(false))
|
.unwrap_or(false))
|
||||||
{
|
{
|
||||||
healthchange = 0.0;
|
damage.healthchange = 0.0;
|
||||||
knockback = 0.0;
|
knockback = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if rand::random() {
|
let block = character_b.map(|c_b| c_b.is_block()).unwrap_or(false)
|
||||||
healthchange *= 1.2;
|
&& ori_b.0.angle_between(pos.0 - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0;
|
||||||
}
|
|
||||||
|
|
||||||
// Block
|
|
||||||
if character_b.map(|c_b| c_b.is_block()).unwrap_or(false)
|
|
||||||
&& ori_b.0.angle_between(pos.0 - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0
|
|
||||||
{
|
|
||||||
healthchange *= 1.0 - BLOCK_EFFICIENCY
|
|
||||||
}
|
|
||||||
|
|
||||||
// Armor
|
|
||||||
if let Some(loadout) = loadouts.get(b) {
|
if let Some(loadout) = loadouts.get(b) {
|
||||||
let damage_reduction = loadout.get_damage_reduction();
|
damage.modify_damage(block, loadout);
|
||||||
healthchange *= 1.0 - damage_reduction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if healthchange != 0.0 {
|
if damage.healthchange != 0.0 {
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
server_emitter.emit(ServerEvent::Damage {
|
||||||
uid: *uid_b,
|
uid: *uid_b,
|
||||||
change: HealthChange {
|
change: HealthChange {
|
||||||
amount: healthchange as i32,
|
amount: damage.healthchange as i32,
|
||||||
cause: HealthSource::Attack { by: *uid },
|
cause: HealthSource::Attack { by: *uid },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -165,7 +163,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
if knockback != 0.0 {
|
if knockback != 0.0 {
|
||||||
local_emitter.emit(LocalEvent::ApplyForce {
|
local_emitter.emit(LocalEvent::ApplyForce {
|
||||||
entity: b,
|
entity: b,
|
||||||
force: attack.knockback
|
force: knockback
|
||||||
* *Dir::slerp(ori.0, Dir::new(Vec3::new(0.0, 0.0, 1.0)), 0.5),
|
* *Dir::slerp(ori.0, Dir::new(Vec3::new(0.0, 0.0, 1.0)), 0.5),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
projectile, Alignment, Energy, EnergySource, HealthSource, Ori, PhysicsState, Pos,
|
projectile, Alignment, Damage, DamageSource, Energy, EnergySource, HealthChange,
|
||||||
Projectile, Vel,
|
HealthSource, Loadout, Ori, PhysicsState, Pos, Projectile, Vel,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
state::DeltaTime,
|
state::DeltaTime,
|
||||||
@ -29,6 +29,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Projectile>,
|
WriteStorage<'a, Projectile>,
|
||||||
WriteStorage<'a, Energy>,
|
WriteStorage<'a, Energy>,
|
||||||
ReadStorage<'a, Alignment>,
|
ReadStorage<'a, Alignment>,
|
||||||
|
ReadStorage<'a, Loadout>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -46,6 +47,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut projectiles,
|
mut projectiles,
|
||||||
mut energies,
|
mut energies,
|
||||||
alignments,
|
alignments,
|
||||||
|
loadouts,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut local_emitter = local_bus.emitter();
|
let mut local_emitter = local_bus.emitter();
|
||||||
@ -84,8 +86,19 @@ impl<'a> System<'a> for Sys {
|
|||||||
else if let Some(other) = physics.touch_entity {
|
else if let Some(other) = physics.touch_entity {
|
||||||
for effect in projectile.hit_entity.drain(..) {
|
for effect in projectile.hit_entity.drain(..) {
|
||||||
match effect {
|
match effect {
|
||||||
projectile::Effect::Damage(change) => {
|
projectile::Effect::Damage(healthchange) => {
|
||||||
let owner_uid = projectile.owner.unwrap();
|
let owner_uid = projectile.owner.unwrap();
|
||||||
|
let mut damage = Damage {
|
||||||
|
healthchange: healthchange as f32,
|
||||||
|
source: DamageSource::Projectile,
|
||||||
|
};
|
||||||
|
if let Some(entity) =
|
||||||
|
uid_allocator.retrieve_entity_internal(other.into())
|
||||||
|
{
|
||||||
|
if let Some(loadout) = loadouts.get(entity) {
|
||||||
|
damage.modify_damage(false, loadout);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Hacky: remove this when groups get implemented
|
// Hacky: remove this when groups get implemented
|
||||||
let passive = uid_allocator
|
let passive = uid_allocator
|
||||||
.retrieve_entity_internal(other.into())
|
.retrieve_entity_internal(other.into())
|
||||||
@ -96,7 +109,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if other != projectile.owner.unwrap() && !passive {
|
if other != projectile.owner.unwrap() && !passive {
|
||||||
server_emitter.emit(ServerEvent::Damage { uid: other, change });
|
server_emitter.emit(ServerEvent::Damage {
|
||||||
|
uid: other,
|
||||||
|
change: HealthChange {
|
||||||
|
amount: damage.healthchange as i32,
|
||||||
|
cause: HealthSource::Attack { by: owner_uid },
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
projectile::Effect::Knockback(knockback) => {
|
projectile::Effect::Knockback(knockback) => {
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
use crate::{client::Client, Server, SpawnPoint, StateExt};
|
use crate::{client::Client, Server, SpawnPoint, StateExt};
|
||||||
use common::{
|
use common::{
|
||||||
assets,
|
assets,
|
||||||
comp::{self, item::lottery::Lottery, object, Body, HealthChange, HealthSource, Player, Stats},
|
comp::{
|
||||||
|
self, item::lottery::Lottery, object, Body, Damage, DamageSource, HealthChange,
|
||||||
|
HealthSource, Player, Stats,
|
||||||
|
},
|
||||||
msg::{PlayerListUpdate, ServerMsg},
|
msg::{PlayerListUpdate, ServerMsg},
|
||||||
state::BlockChange,
|
state::BlockChange,
|
||||||
sync::{Uid, WorldSyncExt},
|
sync::{Uid, WorldSyncExt},
|
||||||
sys::combat::{BLOCK_ANGLE, BLOCK_EFFICIENCY},
|
sys::combat::BLOCK_ANGLE,
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
vol::{ReadVol, Vox},
|
vol::{ReadVol, Vox},
|
||||||
};
|
};
|
||||||
@ -159,9 +162,16 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3<f32>)
|
|||||||
let state = &server.state;
|
let state = &server.state;
|
||||||
if vel.z <= -30.0 {
|
if vel.z <= -30.0 {
|
||||||
if let Some(stats) = state.ecs().write_storage::<comp::Stats>().get_mut(entity) {
|
if let Some(stats) = state.ecs().write_storage::<comp::Stats>().get_mut(entity) {
|
||||||
let falldmg = vel.z.powi(2) as i32 / 20 - 40;
|
let falldmg = vel.z.powi(2) / 20.0 - 40.0;
|
||||||
|
let mut damage = Damage {
|
||||||
|
healthchange: -falldmg,
|
||||||
|
source: DamageSource::Falling,
|
||||||
|
};
|
||||||
|
if let Some(loadout) = state.ecs().read_storage::<comp::Loadout>().get(entity) {
|
||||||
|
damage.modify_damage(false, loadout);
|
||||||
|
}
|
||||||
stats.health.change_by(comp::HealthChange {
|
stats.health.change_by(comp::HealthChange {
|
||||||
amount: -falldmg,
|
amount: damage.healthchange as i32,
|
||||||
cause: comp::HealthSource::World,
|
cause: comp::HealthSource::World,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -211,11 +221,12 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, power: f32, owner: Opti
|
|||||||
// Go through all other entities
|
// Go through all other entities
|
||||||
let hit_range = 3.0 * power;
|
let hit_range = 3.0 * power;
|
||||||
let ecs = &server.state.ecs();
|
let ecs = &server.state.ecs();
|
||||||
for (pos_b, ori_b, character_b, stats_b) in (
|
for (pos_b, ori_b, character_b, stats_b, loadout_b) in (
|
||||||
&ecs.read_storage::<comp::Pos>(),
|
&ecs.read_storage::<comp::Pos>(),
|
||||||
&ecs.read_storage::<comp::Ori>(),
|
&ecs.read_storage::<comp::Ori>(),
|
||||||
ecs.read_storage::<comp::CharacterState>().maybe(),
|
ecs.read_storage::<comp::CharacterState>().maybe(),
|
||||||
&mut ecs.write_storage::<comp::Stats>(),
|
&mut ecs.write_storage::<comp::Stats>(),
|
||||||
|
ecs.read_storage::<comp::Loadout>().maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
@ -227,21 +238,22 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, power: f32, owner: Opti
|
|||||||
&& distance_squared < hit_range.powi(2)
|
&& distance_squared < hit_range.powi(2)
|
||||||
{
|
{
|
||||||
// Weapon gives base damage
|
// Weapon gives base damage
|
||||||
let mut dmg = ((1.0 - distance_squared / hit_range.powi(2)) * power * 10.0) as u32;
|
let dmg = (1.0 - distance_squared / hit_range.powi(2)) * power * 10.0;
|
||||||
|
|
||||||
if rand::random() {
|
let mut damage = Damage {
|
||||||
dmg += 1;
|
healthchange: -dmg,
|
||||||
}
|
source: DamageSource::Explosion,
|
||||||
|
};
|
||||||
|
|
||||||
// Block
|
let block = character_b.map(|c_b| c_b.is_block()).unwrap_or(false)
|
||||||
if character_b.map(|c_b| c_b.is_block()).unwrap_or(false)
|
&& ori_b.0.angle_between(pos - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0;
|
||||||
&& ori_b.0.angle_between(pos - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0
|
|
||||||
{
|
if let Some(loadout) = loadout_b {
|
||||||
dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as u32
|
damage.modify_damage(block, loadout);
|
||||||
}
|
}
|
||||||
|
|
||||||
stats_b.health.change_by(HealthChange {
|
stats_b.health.change_by(HealthChange {
|
||||||
amount: -(dmg as i32),
|
amount: damage.healthchange as i32,
|
||||||
cause: HealthSource::Projectile { owner },
|
cause: HealthSource::Projectile { owner },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
-- This file should undo anything in `up.sql`
|
@ -0,0 +1,15 @@
|
|||||||
|
-- This migration adjusts projectiles in accordance with the changes made in MR 1222
|
||||||
|
UPDATE
|
||||||
|
loadout
|
||||||
|
SET
|
||||||
|
items = json_replace(
|
||||||
|
items,
|
||||||
|
'$.active_item.ability1.BasicRanged.projectile.hit_entity[0]',
|
||||||
|
json('{"Damage": -3}'),
|
||||||
|
'$.active_item.ability2.BasicRanged.projectile.hit_entity[0]',
|
||||||
|
json('{"Damage": -3}'),
|
||||||
|
'$.second_item.ability1.BasicRanged.projectile.hit_entity[0]',
|
||||||
|
json('{"Damage": -3}'),
|
||||||
|
'$.second_item.ability2.BasicRanged.projectile.hit_entity[0]',
|
||||||
|
json('{"Damage": -3}')
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user