NPCs no longer target players inside safezones (and consider them to be defeated)

Warding aura no longer sometimes bypasses safezone invulnerability
This commit is contained in:
Sam 2021-03-16 15:17:08 -04:00
parent f4fa1e9cd3
commit 18173caefe
2 changed files with 28 additions and 20 deletions

View File

@ -166,7 +166,7 @@ impl<'a> System<'a> for Sys {
}, },
}, },
BuffEffect::DamageReduction(dr) => { BuffEffect::DamageReduction(dr) => {
stat.damage_reduction = dr.min(1.0); stat.damage_reduction = stat.damage_reduction.max(*dr).min(1.0);
}, },
}; };
} }

View File

@ -3,6 +3,7 @@ use common::{
comp::{ comp::{
self, self,
agent::{AgentEvent, Tactic, Target, DEFAULT_INTERACTION_TIME, TRADE_INTERACTION_TIME}, agent::{AgentEvent, Tactic, Target, DEFAULT_INTERACTION_TIME, TRADE_INTERACTION_TIME},
buff::{BuffKind, Buffs},
group, group,
inventory::{item::ItemTag, slot::EquipSlot, trade_pricing::TradePricing}, inventory::{item::ItemTag, slot::EquipSlot, trade_pricing::TradePricing},
invite::InviteResponse, invite::InviteResponse,
@ -88,6 +89,7 @@ pub struct ReadData<'a> {
light_emitter: ReadStorage<'a, LightEmitter>, light_emitter: ReadStorage<'a, LightEmitter>,
world: ReadExpect<'a, Arc<world::World>>, world: ReadExpect<'a, Arc<world::World>>,
rtsim_entities: ReadStorage<'a, RtSimEntity>, rtsim_entities: ReadStorage<'a, RtSimEntity>,
buffs: ReadStorage<'a, Buffs>,
} }
// This is 3.1 to last longer than the last damage timer (3.0 seconds) // This is 3.1 to last longer than the last damage timer (3.0 seconds)
@ -316,13 +318,13 @@ impl<'a> System<'a> for Sys {
target: attacker, target: attacker,
hostile: true, hostile: true,
}); });
if let (Some(tgt_pos), Some(tgt_health)) = ( if let Some(tgt_pos) =
read_data.positions.get(attacker), read_data.positions.get(attacker)
read_data.healths.get(attacker), {
) { if should_stop_attacking(
if tgt_health.is_dead read_data.healths.get(attacker),
|| dist_sqrd > MAX_CHASE_DIST.powi(2) read_data.buffs.get(attacker),
{ ) {
agent.target = Some(Target { agent.target = Some(Target {
target, target,
hostile: false, hostile: false,
@ -389,12 +391,12 @@ impl<'a> System<'a> for Sys {
read_data.uid_allocator.retrieve_entity_internal(by.id()) read_data.uid_allocator.retrieve_entity_internal(by.id())
{ {
if let Some(tgt_pos) = read_data.positions.get(attacker) { if let Some(tgt_pos) = read_data.positions.get(attacker) {
// If the target is dead, remove the target and idle. // If the target is dead or in a safezone, remove the target
if read_data // and idle.
.healths if should_stop_attacking(
.get(attacker) read_data.healths.get(attacker),
.map_or(true, |a| a.is_dead) read_data.buffs.get(attacker),
{ ) {
agent.target = None; agent.target = None;
data.idle_tree( data.idle_tree(
agent, agent,
@ -520,10 +522,7 @@ impl<'a> AgentData<'a> {
event_emitter: &mut Emitter<'_, ServerEvent>, event_emitter: &mut Emitter<'_, ServerEvent>,
) { ) {
if let Some(Target { target, .. }) = agent.target { if let Some(Target { target, .. }) = agent.target {
if let (Some(tgt_pos), Some(tgt_health)) = ( if let Some(tgt_pos) = read_data.positions.get(target) {
read_data.positions.get(target),
read_data.healths.get(target),
) {
let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0); let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0);
// Should the agent flee? // Should the agent flee?
if 1.0 - agent.psyche.aggro > self.damage && self.flees { if 1.0 - agent.psyche.aggro > self.damage && self.flees {
@ -549,8 +548,11 @@ impl<'a> AgentData<'a> {
// If not fleeing, attack the hostile // If not fleeing, attack the hostile
// entity! // entity!
} else { } else {
// If the hostile entity is dead, return to idle // If the hostile entity is dead or in a safezone, return to idle
if tgt_health.is_dead { if should_stop_attacking(
read_data.healths.get(target),
read_data.buffs.get(target),
) {
agent.target = None; agent.target = None;
if agent.can_speak { if agent.can_speak {
let msg = "I have destroyed my enemy!".to_string(); let msg = "I have destroyed my enemy!".to_string();
@ -2412,3 +2414,9 @@ fn can_see_tgt(terrain: &TerrainGrid, pos: &Pos, tgt_pos: &Pos, dist_sqrd: f32)
.powi(2) .powi(2)
>= dist_sqrd >= dist_sqrd
} }
// If target is dead or has invulnerability buff, returns true
fn should_stop_attacking(health: Option<&Health>, buffs: Option<&Buffs>) -> bool {
health.map_or(true, |a| a.is_dead)
|| buffs.map_or(false, |b| b.kinds.contains_key(&BuffKind::Invulnerability))
}