Post review refactoring

* inline `target_dodging` into struct declaration as they are named
anyway
* move `avoid_harm` check out of `Attack::apply_attack` so we don't need
to pass whole Player component.
* another cosmetic things
This commit is contained in:
juliancoffee 2021-07-30 14:34:05 +03:00
parent 7413e7fd11
commit 497a94cd7a
9 changed files with 61 additions and 46 deletions

View File

@ -53,7 +53,6 @@ pub enum AttackSource {
#[derive(Copy, Clone)]
pub struct AttackerInfo<'a> {
pub entity: EcsEntity,
pub player: Option<&'a Player>,
pub uid: Uid,
pub energy: Option<&'a Energy>,
pub combo: Option<&'a Combo>,
@ -63,7 +62,6 @@ pub struct AttackerInfo<'a> {
#[cfg(not(target_arch = "wasm32"))]
pub struct TargetInfo<'a> {
pub entity: EcsEntity,
pub player: Option<&'a Player>,
pub uid: Uid,
pub inventory: Option<&'a Inventory>,
pub stats: Option<&'a Stats>,
@ -76,6 +74,7 @@ pub struct TargetInfo<'a> {
#[derive(Clone, Copy)]
pub struct AttackOptions {
pub target_dodging: bool,
pub avoid_harm: bool,
pub target_group: GroupTarget,
}
@ -182,12 +181,10 @@ impl Attack {
) -> bool {
let AttackOptions {
target_dodging,
avoid_harm,
target_group,
} = options;
let avoid_harm =
attacker.map_or(false, |attacker| avoid_harm(attacker.player, target.player));
// target == OutOfGroup is basic heuristic that this
// "attack" has negative effects.
//
@ -464,7 +461,7 @@ impl Attack {
// This code works only with players.
// You still can kill someone's pet and
// you still can be killed by someone's pet
pub fn avoid_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool {
pub fn avoid_player_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool {
if let (Some(attacker), Some(target)) = (attacker, target) {
return attacker.disallow_harm(target);
}

View File

@ -23,6 +23,12 @@ pub struct Player {
uuid: Uuid,
}
impl BattleMode {
pub fn allow_harm(self, other: Self) -> bool {
matches!((self, other), (BattleMode::PvP, BattleMode::PvP))
}
}
impl Player {
pub fn new(alias: String, battle_mode: BattleMode, uuid: Uuid) -> Self {
Self {
@ -38,10 +44,7 @@ impl Player {
/// tea.
pub fn allow_harm(&self, other: &Player) -> bool {
// TODO: discuss if we want to keep self-harm
matches!(
(self.battle_mode, other.battle_mode),
(BattleMode::PvP, BattleMode::PvP)
)
self.battle_mode.allow_harm(other.battle_mode)
}
/// Inverse of `allow_harm`. Read its doc to learn more.

View File

@ -180,7 +180,7 @@ fn activate_aura(
owner.map_or(false, |attacker| {
let attacker = read_data.players.get(attacker);
let target = read_data.players.get(target);
combat::avoid_harm(attacker, target)
combat::avoid_player_harm(attacker, target)
})
};

View File

@ -1,5 +1,5 @@
use common::{
combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo},
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
comp::{
agent::{Sound, SoundKind},
Beam, BeamSegment, Body, CharacterState, Combo, Energy, Group, Health, HealthSource,
@ -196,7 +196,6 @@ impl<'a> System<'a> for Sys {
.zip(beam_segment.owner)
.map(|(entity, uid)| AttackerInfo {
entity,
player: read_data.players.get(entity),
uid,
energy: read_data.energies.get(entity),
combo: read_data.combos.get(entity),
@ -205,7 +204,6 @@ impl<'a> System<'a> for Sys {
let target_info = TargetInfo {
entity: target,
player: read_data.players.get(target),
uid: *uid_b,
inventory: read_data.inventories.get(target),
stats: read_data.stats.get(target),
@ -215,11 +213,15 @@ impl<'a> System<'a> for Sys {
char_state: read_data.character_states.get(target),
};
// No luck with dodging beams
let target_dodging = false;
let avoid_harm = combat::avoid_player_harm(
beam_owner.and_then(|owner| read_data.players.get(owner)),
read_data.players.get(target),
);
let attack_options = AttackOptions {
target_dodging,
// No luck with dodging beams
target_dodging: false,
avoid_harm,
target_group,
};

View File

@ -1,5 +1,5 @@
use common::{
combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo},
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
comp::{
agent::{Sound, SoundKind},
Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori, Player, Pos,
@ -145,7 +145,6 @@ impl<'a> System<'a> for Sys {
let attacker_info = Some(AttackerInfo {
entity: attacker,
player: read_data.players.get(attacker),
uid: *uid,
energy: read_data.energies.get(attacker),
combo: read_data.combos.get(attacker),
@ -154,7 +153,6 @@ impl<'a> System<'a> for Sys {
let target_info = TargetInfo {
entity: target,
player: read_data.players.get(target),
uid: *uid_b,
inventory: read_data.inventories.get(target),
stats: read_data.stats.get(target),
@ -164,8 +162,14 @@ impl<'a> System<'a> for Sys {
char_state: read_data.char_states.get(target),
};
let avoid_harm = combat::avoid_player_harm(
read_data.players.get(attacker),
read_data.players.get(target),
);
let attack_options = AttackOptions {
target_dodging,
avoid_harm,
target_group,
};

View File

@ -1,5 +1,5 @@
use common::{
combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo},
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
comp::{
agent::{Sound, SoundKind},
projectile, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory,
@ -115,6 +115,7 @@ impl<'a> System<'a> for Sys {
}
let projectile = &mut *projectile;
// FIXME: this code is highway to hell, resolve this
for effect in projectile.hit_entity.drain(..) {
match effect {
projectile::Effect::Attack(attack) => {
@ -135,7 +136,6 @@ impl<'a> System<'a> for Sys {
owner_entity.zip(projectile.owner).map(|(entity, uid)| {
AttackerInfo {
entity,
player: read_data.players.get(entity),
uid,
energy: read_data.energies.get(entity),
combo: read_data.combos.get(entity),
@ -145,7 +145,6 @@ impl<'a> System<'a> for Sys {
let target_info = TargetInfo {
entity: target,
player: read_data.players.get(target),
uid: other,
inventory: read_data.inventories.get(target),
stats: read_data.stats.get(target),
@ -155,10 +154,6 @@ impl<'a> System<'a> for Sys {
char_state: read_data.character_states.get(target),
};
// They say witchers can dodge arrows,
// but we don't have witchers
let target_dodging = false;
if let Some(&body) = read_data.bodies.get(entity) {
outcomes.push(Outcome::ProjectileHit {
pos: pos.0,
@ -172,8 +167,16 @@ impl<'a> System<'a> for Sys {
});
}
let avoid_harm = combat::avoid_player_harm(
owner_entity.and_then(|owner| read_data.players.get(owner)),
read_data.players.get(target),
);
let attack_options = AttackOptions {
target_dodging,
// They say witchers can dodge arrows,
// but we don't have witchers
target_dodging: false,
avoid_harm,
target_group,
};
attack.apply_attack(

View File

@ -1,5 +1,5 @@
use common::{
combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo},
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
comp::{
agent::{Sound, SoundKind},
Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory, Ori,
@ -192,7 +192,6 @@ impl<'a> System<'a> for Sys {
.zip(shockwave.owner)
.map(|(entity, uid)| AttackerInfo {
entity,
player: read_data.players.get(entity),
uid,
energy: read_data.energies.get(entity),
combo: read_data.combos.get(entity),
@ -201,7 +200,6 @@ impl<'a> System<'a> for Sys {
let target_info = TargetInfo {
entity: target,
player: read_data.players.get(target),
uid: *uid_b,
inventory: read_data.inventories.get(target),
stats: read_data.stats.get(target),
@ -211,11 +209,14 @@ impl<'a> System<'a> for Sys {
char_state: read_data.character_states.get(target),
};
// Trying roll during earthquake isn't the best idea
let target_dodging = false;
let avoid_harm = combat::avoid_player_harm(
shockwave_owner.and_then(|owner| read_data.players.get(owner)),
read_data.players.get(target),
);
let attack_options = AttackOptions {
target_dodging,
// Trying roll during earthquake isn't the best idea
target_dodging: false,
avoid_harm,
target_group,
};

View File

@ -871,7 +871,6 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
.zip(owner)
.map(|(entity, uid)| combat::AttackerInfo {
entity,
player: players.get(entity),
uid,
energy: energies.get(entity),
combo: combos.get(entity),
@ -880,7 +879,6 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
let target_info = combat::TargetInfo {
entity: entity_b,
player: players.get(entity_b),
uid: *uid_b,
inventory: inventories.get(entity_b),
stats: stats_b_maybe,
@ -890,10 +888,15 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
char_state: char_state_b_maybe,
};
let avoid_harm = combat::avoid_player_harm(
owner_entity.and_then(|owner| players.get(owner)),
players.get(entity_b),
);
let attack_options = combat::AttackOptions {
// cool guyz maybe don't look at explosions
// but they still got hurt, it's not Hollywood
target_dodging: false,
avoid_harm,
target_group,
};
@ -926,6 +929,13 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
1.0 - distance_squared / explosion.radius.powi(2)
};
let avoid_harm = || {
owner_entity.map_or(false, |attacker| {
let attacker = players.get(attacker);
let target = players.get(entity_b);
combat::avoid_player_harm(attacker, target)
})
};
if strength > 0.0 {
let is_alive = ecs
.read_storage::<comp::Health>()
@ -933,13 +943,8 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
.map_or(true, |h| !h.is_dead);
if is_alive {
let avoid_harm = owner_entity.map_or(false, |attacker| {
let attacker = players.get(attacker);
let target = players.get(entity_b);
combat::avoid_harm(attacker, target)
});
effect.modify_strength(strength);
if !(effect.is_harm() && avoid_harm) {
if !(effect.is_harm() && avoid_harm()) {
server.state().apply_effect(entity_b, effect.clone(), owner);
}
}

View File

@ -37,8 +37,8 @@ pub struct ReadData<'a> {
uids: ReadStorage<'a, Uid>,
clients: ReadStorage<'a, Client>,
server_event_bus: Read<'a, EventBus<ServerEvent>>,
_health_comp: ReadStorage<'a, Health>, // used by plugin feature
_plugin_mgr: ReadPlugin<'a>, // used by plugin feature
_healths: ReadStorage<'a, Health>, // used by plugin feature
_plugin_mgr: ReadPlugin<'a>, // used by plugin feature
_uid_allocator: Read<'a, UidAllocator>, // used by plugin feature
}
@ -117,7 +117,7 @@ impl<'a> System<'a> for Sys {
#[cfg(feature = "plugins")]
let ecs_world = EcsWorld {
entities: &read_data.entities,
health: (&read_data._health_comp).into(),
health: (&read_data._healths).into(),
uid: (&read_data.uids).into(),
player: (&players).into(),
uid_allocator: &read_data._uid_allocator,