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 // 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 {

View File

@ -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;
} }
} }

View File

@ -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;
} }
} }

View File

@ -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) => {

View File

@ -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;
} }
} }

View File

@ -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