Roll now gives i-frames.

This commit is contained in:
Sam 2020-11-05 16:48:04 -06:00
parent fae3ef6e59
commit 4a1a3f3ecc
6 changed files with 89 additions and 14 deletions

View File

@ -145,6 +145,20 @@ impl CharacterState {
// Check if state is the same without looking at the inner data
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 {

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
group, Beam, BeamSegment, Body, Energy, EnergyChange, EnergySource, Health, HealthChange,
HealthSource, Last, Loadout, Ori, Pos, Scale,
group, Beam, BeamSegment, Body, CharacterState, Energy, EnergyChange, EnergySource, Health,
HealthChange, HealthSource, Last, Loadout, Ori, Pos, Scale,
},
event::{EventBus, ServerEvent},
state::{DeltaTime, Time},
@ -34,6 +34,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Energy>,
WriteStorage<'a, BeamSegment>,
WriteStorage<'a, Beam>,
ReadStorage<'a, CharacterState>,
);
fn run(
@ -56,6 +57,7 @@ impl<'a> System<'a> for Sys {
energies,
mut beam_segments,
mut beams,
char_states,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
@ -112,7 +114,16 @@ impl<'a> System<'a> for Sys {
};
// 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,
&uids,
&positions,
@ -121,6 +132,7 @@ impl<'a> System<'a> for Sys {
scales.maybe(),
&healths,
&bodies,
char_states.maybe(),
)
.join()
{
@ -134,6 +146,9 @@ impl<'a> System<'a> for Sys {
let rad_b = body_b.radius() * 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
let hit = entity != b
&& !health_b.is_dead
@ -160,7 +175,9 @@ impl<'a> System<'a> for Sys {
for (target, damage) in beam_segment.damages.iter() {
if let Some(target) = target {
if *target != target_group {
if *target != target_group
|| (!matches!(target, GroupTarget::InGroup) && is_invincible)
{
continue;
}
}

View File

@ -1,5 +1,5 @@
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},
metrics::SysMetrics,
span,
@ -31,6 +31,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Loadout>,
ReadStorage<'a, group::Group>,
WriteStorage<'a, Attacking>,
ReadStorage<'a, CharacterState>,
);
fn run(
@ -49,6 +50,7 @@ impl<'a> System<'a> for Sys {
loadouts,
groups,
mut attacking_storage,
char_states,
): Self::SystemData,
) {
let start_time = std::time::Instant::now();
@ -72,8 +74,15 @@ impl<'a> System<'a> for Sys {
attack.applied = true;
// Go through all other entities
for (b, pos_b, scale_b_maybe, health_b, body_b) in
(&entities, &positions, scales.maybe(), &healths, &bodies).join()
for (b, pos_b, scale_b_maybe, health_b, body_b, char_state_b_maybe) in (
&entities,
&positions,
scales.maybe(),
&healths,
&bodies,
char_states.maybe(),
)
.join()
{
// 2D versions
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 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
if entity != b
&& !health_b.is_dead
@ -106,7 +118,9 @@ impl<'a> System<'a> for Sys {
for (target, damage) in attack.damages.iter() {
if let Some(target) = target {
if *target != target_group {
if *target != target_group
|| (!matches!(target, GroupTarget::InGroup) && is_invincible)
{
continue;
}
}

View File

@ -1,8 +1,8 @@
use crate::{
comp::{
buff::{BuffChange, BuffSource},
projectile, EnergyChange, EnergySource, Group, HealthSource, Loadout, Ori, PhysicsState,
Pos, Projectile, Vel,
projectile, CharacterState, EnergyChange, EnergySource, Group, HealthSource, Loadout, Ori,
PhysicsState, Pos, Projectile, Vel,
},
event::{EventBus, LocalEvent, ServerEvent},
metrics::SysMetrics,
@ -35,6 +35,7 @@ impl<'a> System<'a> for Sys {
WriteStorage<'a, Projectile>,
ReadStorage<'a, Loadout>,
ReadStorage<'a, Group>,
ReadStorage<'a, CharacterState>,
);
fn run(
@ -53,6 +54,7 @@ impl<'a> System<'a> for Sys {
mut projectiles,
loadouts,
groups,
char_states,
): Self::SystemData,
) {
let start_time = std::time::Instant::now();
@ -102,6 +104,18 @@ impl<'a> System<'a> for Sys {
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(..) {
match effect {
projectile::Effect::Damage(target, damage) => {

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
group, Body, Health, HealthSource, Last, Loadout, Ori, PhysicsState, Pos, Scale, Shockwave,
ShockwaveHitEntities,
group, Body, CharacterState, Health, HealthSource, Last, Loadout, Ori, PhysicsState, Pos,
Scale, Shockwave, ShockwaveHitEntities,
},
event::{EventBus, LocalEvent, ServerEvent},
state::{DeltaTime, Time},
@ -36,6 +36,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, PhysicsState>,
WriteStorage<'a, Shockwave>,
WriteStorage<'a, ShockwaveHitEntities>,
ReadStorage<'a, CharacterState>,
);
fn run(
@ -59,6 +60,7 @@ impl<'a> System<'a> for Sys {
physics_states,
mut shockwaves,
mut shockwave_hit_lists,
char_states,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
@ -131,6 +133,7 @@ impl<'a> System<'a> for Sys {
health_b,
body_b,
physics_state_b,
char_state_b_maybe,
) in (
&entities,
&uids,
@ -141,6 +144,7 @@ impl<'a> System<'a> for Sys {
&healths,
&bodies,
&physics_states,
char_states.maybe(),
)
.join()
{
@ -176,6 +180,9 @@ impl<'a> System<'a> for Sys {
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
let hit = entity != b
&& !health_b.is_dead
@ -193,7 +200,9 @@ impl<'a> System<'a> for Sys {
if hit {
for (target, damage) in shockwave.damages.iter() {
if let Some(target) = target {
if *target != target_group {
if *target != target_group
|| (!matches!(target, GroupTarget::InGroup) && is_invincible)
{
continue;
}
}

View File

@ -647,7 +647,14 @@ pub fn handle_explosion(
.get(entity_b)
.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);
server.state().apply_effect(entity_b, effect, owner);
// Apply energy change