mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Roll now gives i-frames.
This commit is contained in:
parent
fae3ef6e59
commit
4a1a3f3ecc
@ -145,6 +145,20 @@ impl CharacterState {
|
|||||||
// Check if state is the same without looking at the inner data
|
// Check if state is the same without looking at the inner data
|
||||||
std::mem::discriminant(self) == std::mem::discriminant(other)
|
std::mem::discriminant(self) == std::mem::discriminant(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_invincible(&self) -> bool {
|
||||||
|
if let CharacterState::Roll(data) = self {
|
||||||
|
use utils::StageSection;
|
||||||
|
match data.stage_section {
|
||||||
|
StageSection::Buildup => data.static_data.buildup_iframes,
|
||||||
|
StageSection::Movement => data.static_data.movement_iframes,
|
||||||
|
StageSection::Recover => data.static_data.recover_iframes,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CharacterState {
|
impl Default for CharacterState {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
group, Beam, BeamSegment, Body, Energy, EnergyChange, EnergySource, Health, HealthChange,
|
group, Beam, BeamSegment, Body, CharacterState, Energy, EnergyChange, EnergySource, Health,
|
||||||
HealthSource, Last, Loadout, Ori, Pos, Scale,
|
HealthChange, HealthSource, Last, Loadout, Ori, Pos, Scale,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
state::{DeltaTime, Time},
|
state::{DeltaTime, Time},
|
||||||
@ -34,6 +34,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadStorage<'a, Energy>,
|
ReadStorage<'a, Energy>,
|
||||||
WriteStorage<'a, BeamSegment>,
|
WriteStorage<'a, BeamSegment>,
|
||||||
WriteStorage<'a, Beam>,
|
WriteStorage<'a, Beam>,
|
||||||
|
ReadStorage<'a, CharacterState>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -56,6 +57,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
energies,
|
energies,
|
||||||
mut beam_segments,
|
mut beam_segments,
|
||||||
mut beams,
|
mut beams,
|
||||||
|
char_states,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
@ -112,7 +114,16 @@ impl<'a> System<'a> for Sys {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Go through all other effectable entities
|
// Go through all other effectable entities
|
||||||
for (b, uid_b, pos_b, last_pos_b_maybe, scale_b_maybe, health_b, body_b) in (
|
for (
|
||||||
|
b,
|
||||||
|
uid_b,
|
||||||
|
pos_b,
|
||||||
|
last_pos_b_maybe,
|
||||||
|
scale_b_maybe,
|
||||||
|
health_b,
|
||||||
|
body_b,
|
||||||
|
char_state_b_maybe,
|
||||||
|
) in (
|
||||||
&entities,
|
&entities,
|
||||||
&uids,
|
&uids,
|
||||||
&positions,
|
&positions,
|
||||||
@ -121,6 +132,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
scales.maybe(),
|
scales.maybe(),
|
||||||
&healths,
|
&healths,
|
||||||
&bodies,
|
&bodies,
|
||||||
|
char_states.maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
@ -134,6 +146,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
let rad_b = body_b.radius() * scale_b;
|
let rad_b = body_b.radius() * scale_b;
|
||||||
let height_b = body_b.height() * scale_b;
|
let height_b = body_b.height() * scale_b;
|
||||||
|
|
||||||
|
// Check if entity is immune to damage
|
||||||
|
let is_invincible = char_state_b_maybe.map_or(false, |c_s| c_s.is_invincible());
|
||||||
|
|
||||||
// Check if it is a hit
|
// Check if it is a hit
|
||||||
let hit = entity != b
|
let hit = entity != b
|
||||||
&& !health_b.is_dead
|
&& !health_b.is_dead
|
||||||
@ -160,7 +175,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
for (target, damage) in beam_segment.damages.iter() {
|
for (target, damage) in beam_segment.damages.iter() {
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
if *target != target_group {
|
if *target != target_group
|
||||||
|
|| (!matches!(target, GroupTarget::InGroup) && is_invincible)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{buff, group, Attacking, Body, Health, Loadout, Ori, Pos, Scale},
|
comp::{buff, group, Attacking, Body, CharacterState, Health, Loadout, Ori, Pos, Scale},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
metrics::SysMetrics,
|
metrics::SysMetrics,
|
||||||
span,
|
span,
|
||||||
@ -31,6 +31,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadStorage<'a, Loadout>,
|
ReadStorage<'a, Loadout>,
|
||||||
ReadStorage<'a, group::Group>,
|
ReadStorage<'a, group::Group>,
|
||||||
WriteStorage<'a, Attacking>,
|
WriteStorage<'a, Attacking>,
|
||||||
|
ReadStorage<'a, CharacterState>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -49,6 +50,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
loadouts,
|
loadouts,
|
||||||
groups,
|
groups,
|
||||||
mut attacking_storage,
|
mut attacking_storage,
|
||||||
|
char_states,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
@ -72,8 +74,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
attack.applied = true;
|
attack.applied = true;
|
||||||
|
|
||||||
// Go through all other entities
|
// Go through all other entities
|
||||||
for (b, pos_b, scale_b_maybe, health_b, body_b) in
|
for (b, pos_b, scale_b_maybe, health_b, body_b, char_state_b_maybe) in (
|
||||||
(&entities, &positions, scales.maybe(), &healths, &bodies).join()
|
&entities,
|
||||||
|
&positions,
|
||||||
|
scales.maybe(),
|
||||||
|
&healths,
|
||||||
|
&bodies,
|
||||||
|
char_states.maybe(),
|
||||||
|
)
|
||||||
|
.join()
|
||||||
{
|
{
|
||||||
// 2D versions
|
// 2D versions
|
||||||
let pos2 = Vec2::from(pos.0);
|
let pos2 = Vec2::from(pos.0);
|
||||||
@ -85,6 +94,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
let scale_b = scale_b_maybe.map_or(1.0, |s| s.0);
|
let scale_b = scale_b_maybe.map_or(1.0, |s| s.0);
|
||||||
let rad_b = body_b.radius() * scale_b;
|
let rad_b = body_b.radius() * scale_b;
|
||||||
|
|
||||||
|
// Check if entity is invincible
|
||||||
|
let is_invincible = char_state_b_maybe.map_or(false, |c_s| c_s.is_invincible());
|
||||||
|
|
||||||
// Check if it is a hit
|
// Check if it is a hit
|
||||||
if entity != b
|
if entity != b
|
||||||
&& !health_b.is_dead
|
&& !health_b.is_dead
|
||||||
@ -106,7 +118,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
for (target, damage) in attack.damages.iter() {
|
for (target, damage) in attack.damages.iter() {
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
if *target != target_group {
|
if *target != target_group
|
||||||
|
|| (!matches!(target, GroupTarget::InGroup) && is_invincible)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
buff::{BuffChange, BuffSource},
|
buff::{BuffChange, BuffSource},
|
||||||
projectile, EnergyChange, EnergySource, Group, HealthSource, Loadout, Ori, PhysicsState,
|
projectile, CharacterState, EnergyChange, EnergySource, Group, HealthSource, Loadout, Ori,
|
||||||
Pos, Projectile, Vel,
|
PhysicsState, Pos, Projectile, Vel,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
metrics::SysMetrics,
|
metrics::SysMetrics,
|
||||||
@ -35,6 +35,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Projectile>,
|
WriteStorage<'a, Projectile>,
|
||||||
ReadStorage<'a, Loadout>,
|
ReadStorage<'a, Loadout>,
|
||||||
ReadStorage<'a, Group>,
|
ReadStorage<'a, Group>,
|
||||||
|
ReadStorage<'a, CharacterState>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -53,6 +54,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut projectiles,
|
mut projectiles,
|
||||||
loadouts,
|
loadouts,
|
||||||
groups,
|
groups,
|
||||||
|
char_states,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
@ -102,6 +104,18 @@ impl<'a> System<'a> for Sys {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if entity is immune to damage
|
||||||
|
// TODO: When projectiles are reduced down to a collection of (target, effect)s,
|
||||||
|
// move this check there so that future projectiles intended for allies cannot
|
||||||
|
// be dodged by those allies
|
||||||
|
let entity_invincible = uid_allocator
|
||||||
|
.retrieve_entity_internal(other.into())
|
||||||
|
.and_then(|e| char_states.get(e))
|
||||||
|
.map_or(false, |c_s| c_s.is_invincible());
|
||||||
|
if entity_invincible {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for effect in projectile.hit_entity.drain(..) {
|
for effect in projectile.hit_entity.drain(..) {
|
||||||
match effect {
|
match effect {
|
||||||
projectile::Effect::Damage(target, damage) => {
|
projectile::Effect::Damage(target, damage) => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
group, Body, Health, HealthSource, Last, Loadout, Ori, PhysicsState, Pos, Scale, Shockwave,
|
group, Body, CharacterState, Health, HealthSource, Last, Loadout, Ori, PhysicsState, Pos,
|
||||||
ShockwaveHitEntities,
|
Scale, Shockwave, ShockwaveHitEntities,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
state::{DeltaTime, Time},
|
state::{DeltaTime, Time},
|
||||||
@ -36,6 +36,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadStorage<'a, PhysicsState>,
|
ReadStorage<'a, PhysicsState>,
|
||||||
WriteStorage<'a, Shockwave>,
|
WriteStorage<'a, Shockwave>,
|
||||||
WriteStorage<'a, ShockwaveHitEntities>,
|
WriteStorage<'a, ShockwaveHitEntities>,
|
||||||
|
ReadStorage<'a, CharacterState>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -59,6 +60,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
physics_states,
|
physics_states,
|
||||||
mut shockwaves,
|
mut shockwaves,
|
||||||
mut shockwave_hit_lists,
|
mut shockwave_hit_lists,
|
||||||
|
char_states,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
@ -131,6 +133,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
health_b,
|
health_b,
|
||||||
body_b,
|
body_b,
|
||||||
physics_state_b,
|
physics_state_b,
|
||||||
|
char_state_b_maybe,
|
||||||
) in (
|
) in (
|
||||||
&entities,
|
&entities,
|
||||||
&uids,
|
&uids,
|
||||||
@ -141,6 +144,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&healths,
|
&healths,
|
||||||
&bodies,
|
&bodies,
|
||||||
&physics_states,
|
&physics_states,
|
||||||
|
char_states.maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
@ -176,6 +180,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
GroupTarget::OutOfGroup
|
GroupTarget::OutOfGroup
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if entity is immune to damage
|
||||||
|
let is_invincible = char_state_b_maybe.map_or(false, |c_s| c_s.is_invincible());
|
||||||
|
|
||||||
// Check if it is a hit
|
// Check if it is a hit
|
||||||
let hit = entity != b
|
let hit = entity != b
|
||||||
&& !health_b.is_dead
|
&& !health_b.is_dead
|
||||||
@ -193,7 +200,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
if hit {
|
if hit {
|
||||||
for (target, damage) in shockwave.damages.iter() {
|
for (target, damage) in shockwave.damages.iter() {
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
if *target != target_group {
|
if *target != target_group
|
||||||
|
|| (!matches!(target, GroupTarget::InGroup) && is_invincible)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,7 +647,14 @@ pub fn handle_explosion(
|
|||||||
.get(entity_b)
|
.get(entity_b)
|
||||||
.map_or(false, |h| !h.is_dead);
|
.map_or(false, |h| !h.is_dead);
|
||||||
|
|
||||||
if is_alive {
|
let is_invincible = ecs
|
||||||
|
.read_storage::<comp::CharacterState>()
|
||||||
|
.get(entity_b)
|
||||||
|
.map_or(false, |c_s| c_s.is_invincible());
|
||||||
|
|
||||||
|
if is_alive
|
||||||
|
&& (matches!(target, Some(GroupTarget::InGroup)) || !is_invincible)
|
||||||
|
{
|
||||||
effect.modify_strength(strength);
|
effect.modify_strength(strength);
|
||||||
server.state().apply_effect(entity_b, effect, owner);
|
server.state().apply_effect(entity_b, effect, owner);
|
||||||
// Apply energy change
|
// Apply energy change
|
||||||
|
Loading…
Reference in New Issue
Block a user