mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Avoid negative bounds in harm checks
* disallow_harm -> allow_harm to avoid negative reasoning since it mostly requires double negation in code * allow_harm -> may_harm to specify side-effect free
This commit is contained in:
parent
44916383c6
commit
4766450258
@ -74,7 +74,7 @@ pub struct TargetInfo<'a> {
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct AttackOptions {
|
||||
pub target_dodging: bool,
|
||||
pub avoid_harm: bool,
|
||||
pub may_harm: bool,
|
||||
pub target_group: GroupTarget,
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ impl Attack {
|
||||
) -> bool {
|
||||
let AttackOptions {
|
||||
target_dodging,
|
||||
avoid_harm,
|
||||
may_harm,
|
||||
target_group,
|
||||
} = options;
|
||||
|
||||
@ -192,11 +192,11 @@ impl Attack {
|
||||
// it should avoid such "damage" or effect
|
||||
let avoid_damage = |attack_damage: &AttackDamage| {
|
||||
matches!(attack_damage.target, Some(GroupTarget::OutOfGroup))
|
||||
&& (target_dodging || avoid_harm)
|
||||
&& (target_dodging || !may_harm)
|
||||
};
|
||||
let avoid_effect = |attack_effect: &AttackEffect| {
|
||||
matches!(attack_effect.target, Some(GroupTarget::OutOfGroup))
|
||||
&& (target_dodging || avoid_harm)
|
||||
&& (target_dodging || !may_harm)
|
||||
};
|
||||
let is_crit = thread_rng().gen::<f32>() < self.crit_chance;
|
||||
let mut is_applied = false;
|
||||
@ -456,16 +456,15 @@ impl Attack {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if we should avoid negative effects from one player to another
|
||||
/// Checks if we should allow 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_player_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool {
|
||||
if let (Some(attacker), Some(target)) = (attacker, target) {
|
||||
return attacker.disallow_harm(target);
|
||||
}
|
||||
false
|
||||
pub fn may_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool {
|
||||
attacker
|
||||
.zip(target)
|
||||
.map_or(true, |(attacker, target)| attacker.may_harm(target))
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
@ -24,7 +24,7 @@ pub struct Player {
|
||||
}
|
||||
|
||||
impl BattleMode {
|
||||
pub fn allow_harm(self, other: Self) -> bool {
|
||||
pub fn may_harm(self, other: Self) -> bool {
|
||||
matches!((self, other), (BattleMode::PvP, BattleMode::PvP))
|
||||
}
|
||||
}
|
||||
@ -43,12 +43,7 @@ impl Player {
|
||||
/// Simple as tea, if they don't want the tea, don't make them drink the
|
||||
/// tea.
|
||||
/// You can make tea for yourself though.
|
||||
pub fn allow_harm(&self, other: &Player) -> bool {
|
||||
self.battle_mode.allow_harm(other.battle_mode) || self.uuid == other.uuid
|
||||
}
|
||||
|
||||
/// Inverse of `allow_harm`. Read its doc to learn more.
|
||||
pub fn disallow_harm(&self, other: &Player) -> bool { !self.allow_harm(other) }
|
||||
pub fn may_harm(&self, other: &Player) -> bool { self.battle_mode.may_harm(other.battle_mode) }
|
||||
|
||||
pub fn is_valid(&self) -> bool { Self::alias_validate(&self.alias).is_ok() }
|
||||
|
||||
|
@ -170,21 +170,29 @@ fn activate_aura(
|
||||
// Add other specific buff conditions here
|
||||
_ => true,
|
||||
};
|
||||
let avoid_harm = || {
|
||||
|
||||
// TODO: this check will disable friendly fire with PvE switch.
|
||||
//
|
||||
// Which means that you can't apply debuffs on you and your group
|
||||
// even if it's intented mechanics.
|
||||
//
|
||||
// Not that we have this for now, but think about this
|
||||
// when we will add this.
|
||||
let may_harm = || {
|
||||
let owner = match source {
|
||||
BuffSource::Character { by } => {
|
||||
read_data.uid_allocator.retrieve_entity_internal(by.into())
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
owner.map_or(false, |attacker| {
|
||||
owner.map_or(true, |attacker| {
|
||||
let attacker = read_data.players.get(attacker);
|
||||
let target = read_data.players.get(target);
|
||||
combat::avoid_player_harm(attacker, target)
|
||||
combat::may_harm(attacker, target)
|
||||
})
|
||||
};
|
||||
|
||||
conditions_held && (kind.is_buff() || !avoid_harm())
|
||||
conditions_held && (kind.is_buff() || may_harm())
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -214,14 +214,14 @@ impl<'a> System<'a> for Sys {
|
||||
};
|
||||
|
||||
|
||||
let avoid_harm = combat::avoid_player_harm(
|
||||
let may_harm = combat::may_harm(
|
||||
beam_owner.and_then(|owner| read_data.players.get(owner)),
|
||||
read_data.players.get(target),
|
||||
);
|
||||
let attack_options = AttackOptions {
|
||||
// No luck with dodging beams
|
||||
target_dodging: false,
|
||||
avoid_harm,
|
||||
may_harm,
|
||||
target_group,
|
||||
};
|
||||
|
||||
|
@ -162,14 +162,14 @@ impl<'a> System<'a> for Sys {
|
||||
char_state: read_data.char_states.get(target),
|
||||
};
|
||||
|
||||
let avoid_harm = combat::avoid_player_harm(
|
||||
let may_harm = combat::may_harm(
|
||||
read_data.players.get(attacker),
|
||||
read_data.players.get(target),
|
||||
);
|
||||
|
||||
let attack_options = AttackOptions {
|
||||
target_dodging,
|
||||
avoid_harm,
|
||||
may_harm,
|
||||
target_group,
|
||||
};
|
||||
|
||||
|
@ -281,7 +281,7 @@ fn dispatch_hit(
|
||||
});
|
||||
}
|
||||
|
||||
let avoid_harm = combat::avoid_player_harm(
|
||||
let may_harm = combat::may_harm(
|
||||
owner.and_then(|owner| read_data.players.get(owner)),
|
||||
read_data.players.get(target),
|
||||
);
|
||||
@ -290,7 +290,7 @@ fn dispatch_hit(
|
||||
// They say witchers can dodge arrows,
|
||||
// but we don't have witchers
|
||||
target_dodging: false,
|
||||
avoid_harm,
|
||||
may_harm,
|
||||
target_group: projectile_target_info.target_group,
|
||||
};
|
||||
|
||||
|
@ -209,14 +209,14 @@ impl<'a> System<'a> for Sys {
|
||||
char_state: read_data.character_states.get(target),
|
||||
};
|
||||
|
||||
let avoid_harm = combat::avoid_player_harm(
|
||||
let may_harm = combat::may_harm(
|
||||
shockwave_owner.and_then(|owner| read_data.players.get(owner)),
|
||||
read_data.players.get(target),
|
||||
);
|
||||
let attack_options = AttackOptions {
|
||||
// Trying roll during earthquake isn't the best idea
|
||||
target_dodging: false,
|
||||
avoid_harm,
|
||||
may_harm,
|
||||
target_group,
|
||||
};
|
||||
|
||||
|
@ -888,7 +888,7 @@ 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(
|
||||
let may_harm = combat::may_harm(
|
||||
owner_entity.and_then(|owner| players.get(owner)),
|
||||
players.get(entity_b),
|
||||
);
|
||||
@ -896,7 +896,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
||||
// cool guyz maybe don't look at explosions
|
||||
// but they still got hurt, it's not Hollywood
|
||||
target_dodging: false,
|
||||
avoid_harm,
|
||||
may_harm,
|
||||
target_group,
|
||||
};
|
||||
|
||||
@ -929,11 +929,22 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
||||
1.0 - distance_squared / explosion.radius.powi(2)
|
||||
};
|
||||
|
||||
let avoid_harm = || {
|
||||
// Player check only accounts for PvP/PvE flag.
|
||||
//
|
||||
// But bombs are intented to do
|
||||
// friendly fire.
|
||||
//
|
||||
// What exactly friendly fire is subject to discussion.
|
||||
// As we probably want to minimize possibility of being dick
|
||||
// even to your group members, the only exception is when
|
||||
// you want to harm yourself.
|
||||
//
|
||||
// This can be changed later.
|
||||
let may_harm = || {
|
||||
owner_entity.map_or(false, |attacker| {
|
||||
let attacker = players.get(attacker);
|
||||
let target = players.get(entity_b);
|
||||
combat::avoid_player_harm(attacker, target)
|
||||
let attacker_player = players.get(attacker);
|
||||
let target_player = players.get(entity_b);
|
||||
combat::may_harm(attacker_player, target_player) || attacker == entity_b
|
||||
})
|
||||
};
|
||||
if strength > 0.0 {
|
||||
@ -944,7 +955,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
||||
|
||||
if is_alive {
|
||||
effect.modify_strength(strength);
|
||||
if !(effect.is_harm() && avoid_harm()) {
|
||||
if !effect.is_harm() || may_harm() {
|
||||
server.state().apply_effect(entity_b, effect.clone(), owner);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user