This commit is contained in:
juliancoffee 2021-07-28 00:57:48 +03:00
parent 7d4a8cbfa4
commit c7fdb640ac
7 changed files with 45 additions and 103 deletions

View File

@ -13,7 +13,7 @@ use crate::{
poise::PoiseChange,
skills::SkillGroupKind,
Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, HealthChange,
HealthSource, Inventory, Ori, SkillSet, Stats,
HealthSource, Inventory, Ori, Player, SkillSet, Stats,
},
event::ServerEvent,
outcome::Outcome,
@ -53,6 +53,7 @@ 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>,
@ -62,6 +63,7 @@ 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>,
@ -75,7 +77,6 @@ pub struct TargetInfo<'a> {
pub struct AttackOptions {
pub target_dodging: bool,
pub target_group: GroupTarget,
pub avoid_harm: bool,
}
#[cfg(not(target_arch = "wasm32"))]
@ -165,7 +166,6 @@ impl Attack {
1.0 - (1.0 - damage_reduction) * (1.0 - block_reduction)
}
#[allow(clippy::too_many_arguments)]
pub fn apply_attack(
&self,
@ -183,8 +183,11 @@ impl Attack {
let AttackOptions {
target_dodging,
target_group,
avoid_harm,
} = 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.
//
@ -456,6 +459,18 @@ impl Attack {
}
}
/// Checks if we should avoid negative effects from one player to another
// FIXME: handle pets?
// 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 {
if let (Some(attacker), Some(target)) = (attacker, target) {
return attacker.disallow_harm(target);
}
false
}
#[cfg(not(target_arch = "wasm32"))]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AttackDamage {

View File

@ -34,7 +34,8 @@ impl Player {
/// Currently we allow attacking only if both players are opt-in to PvP.
///
/// Simple as tea, if they don't want the tea, don't make them drink the tea.
/// Simple as tea, if they don't want the tea, don't make them drink the
/// tea.
pub fn allow_harm(&self, other: &Player) -> bool {
// TODO: discuss if we want to keep self-harm
matches!(
@ -44,9 +45,7 @@ impl Player {
}
/// Inverse of `allow_harm`. Read its doc to learn more.
pub fn disallow_harm(&self, other: &Player) -> bool {
!self.allow_harm(other)
}
pub fn disallow_harm(&self, other: &Player) -> bool { !self.allow_harm(other) }
pub fn is_valid(&self) -> bool { Self::alias_validate(&self.alias).is_ok() }

View File

@ -196,6 +196,7 @@ 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),
@ -204,6 +205,7 @@ 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),
@ -214,24 +216,11 @@ impl<'a> System<'a> for Sys {
};
// No luck with dodging beams
let is_dodge = false;
let avoid_harm = {
let players = &read_data.players;
beam_owner.map_or(false, |attacker| {
if let (Some(attacker), Some(target)) =
(players.get(attacker), players.get(target))
{
attacker.disallow_harm(target)
} else {
false
}
})
};
let target_dodging = false;
let attack_options = AttackOptions {
target_dodging: is_dodge,
target_dodging,
target_group,
avoid_harm,
};
beam_segment.properties.attack.apply_attack(

View File

@ -116,7 +116,7 @@ impl<'a> System<'a> for Sys {
let rad_b = body_b.radius() * scale_b;
// Check if entity is dodging
let is_dodge = read_data
let target_dodging = read_data
.char_states
.get(target)
.map_or(false, |c_s| c_s.is_melee_dodge());
@ -145,6 +145,7 @@ 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),
@ -153,6 +154,7 @@ 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),
@ -162,33 +164,9 @@ impl<'a> System<'a> for Sys {
char_state: read_data.char_states.get(target),
};
let avoid_harm = {
let players = &read_data.players;
if let (Some(attacker), Some(target)) =
(players.get(attacker), players.get(target))
{
attacker.disallow_harm(target)
} else {
false
}
};
// FIXME: printf debugging, this shouldn't go to master
if let Some(attacker) = read_data.players.get(attacker) {
println!("attacker battle_mode: {:?}", attacker.battle_mode);
} else {
println!("attacker special casing")
}
if let Some(target) = read_data.players.get(target) {
println!("target battle_mode: {:?}", target.battle_mode);
} else {
println!("target special casing")
}
let attack_options = AttackOptions {
target_dodging: is_dodge,
target_dodging,
target_group,
avoid_harm,
};
let is_applied = melee_attack.attack.apply_attack(

View File

@ -135,6 +135,7 @@ 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),
@ -144,6 +145,7 @@ 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,19 +157,7 @@ impl<'a> System<'a> for Sys {
// They say witchers can dodge arrows,
// but we don't have witchers
let is_dodge = false;
let avoid_harm = {
let players = &read_data.players;
projectile_owner.map_or(false, |attacker| {
if let (Some(attacker), Some(target)) =
(players.get(attacker), players.get(target))
{
attacker.disallow_harm(target)
} else {
false
}
})
};
let target_dodging = false;
if let Some(&body) = read_data.bodies.get(entity) {
outcomes.push(Outcome::ProjectileHit {
@ -183,9 +173,8 @@ impl<'a> System<'a> for Sys {
}
let attack_options = AttackOptions {
target_dodging: is_dodge,
target_dodging,
target_group,
avoid_harm,
};
attack.apply_attack(
attacker_info,

View File

@ -192,6 +192,7 @@ 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),
@ -200,6 +201,7 @@ 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),
@ -210,24 +212,11 @@ impl<'a> System<'a> for Sys {
};
// Trying roll during earthquake isn't the best idea
let is_dodge = false;
let avoid_harm = {
let players = &read_data.players;
shockwave_owner.map_or(false, |attacker| {
if let (Some(attacker), Some(target)) =
(players.get(attacker), players.get(target))
{
attacker.disallow_harm(target)
} else {
false
}
})
};
let target_dodging = false;
let attack_options = AttackOptions {
target_dodging: is_dodge,
target_dodging,
target_group,
avoid_harm,
};
shockwave.properties.attack.apply_attack(

View File

@ -871,6 +871,7 @@ 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),
@ -879,6 +880,7 @@ 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,
@ -888,24 +890,11 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
char_state: char_state_b_maybe,
};
let avoid_harm = {
owner_entity.map_or(false, |attacker| {
if let (Some(attacker), Some(target)) =
(players.get(attacker), players.get(entity_b))
{
attacker.disallow_harm(target)
} else {
false
}
})
};
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,
target_group,
avoid_harm,
};
attack.apply_attack(
@ -944,17 +933,11 @@ 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| {
if let (Some(attacker), Some(target)) =
(players.get(attacker), players.get(entity_b))
{
attacker.disallow_harm(target)
} else {
false
}
})
};
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) {
server.state().apply_effect(entity_b, effect.clone(), owner);