mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'holychowders/refactor_hostility_logic' into 'master'
Extract some retargeting logic. See merge request veloren/veloren!3321
This commit is contained in:
commit
9d521988b3
@ -285,8 +285,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
.unwrap_or_else(Vec2::zero);
|
.unwrap_or_else(Vec2::zero);
|
||||||
controller.push_basic_input(InputKind::Roll);
|
controller.push_basic_input(InputKind::Roll);
|
||||||
} else {
|
} else {
|
||||||
// Target an entity that's attacking us if the attack
|
// Target an entity that's attacking us if the attack was recent and we have
|
||||||
// was recent and we have a health component
|
// a health component
|
||||||
match health {
|
match health {
|
||||||
Some(health)
|
Some(health)
|
||||||
if read_data.time.0 - health.last_change.time.0
|
if read_data.time.0 - health.last_change.time.0
|
||||||
@ -300,9 +300,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
// means safezone), untarget them and idle.
|
// means safezone), untarget them and idle.
|
||||||
if is_dead_or_invulnerable(attacker, &read_data) {
|
if is_dead_or_invulnerable(attacker, &read_data) {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
} else if let Some(tgt_pos) =
|
} else {
|
||||||
read_data.positions.get(attacker)
|
|
||||||
{
|
|
||||||
if agent.target.is_none() {
|
if agent.target.is_none() {
|
||||||
controller.push_event(ControlEvent::Utterance(
|
controller.push_event(ControlEvent::Utterance(
|
||||||
UtteranceKind::Angry,
|
UtteranceKind::Angry,
|
||||||
@ -311,45 +309,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
// Determine whether the new target should be a priority
|
// Determine whether the new target should be a priority
|
||||||
// over the old one (i.e: because it's either close or
|
// over the old one (i.e: because it's either close or
|
||||||
// because they attacked us)
|
// because they attacked us).
|
||||||
let more_dangerous_than_old_target =
|
if agent.target.map_or(true, |target| {
|
||||||
agent.target.map_or(true, |old_tgt| {
|
data.is_entity_more_dangerous_than_target(
|
||||||
if let Some(old_tgt_pos) =
|
attacker, target, &read_data,
|
||||||
read_data.positions.get(old_tgt.target)
|
)
|
||||||
{
|
}) {
|
||||||
// Fuzzy factor that makes it harder for
|
|
||||||
// players to cheese enemies by making them
|
|
||||||
// quickly flip aggro between two players.
|
|
||||||
// It
|
|
||||||
// does this by only switching aggro if the
|
|
||||||
// new target is closer to the enemy by a
|
|
||||||
// specific proportional threshold.
|
|
||||||
const FUZZY_DIST_COMPARISON: f32 = 0.8;
|
|
||||||
// Only switch to new target if it is closer
|
|
||||||
// than the old target, or if the old target
|
|
||||||
// had not triggered aggro (the new target
|
|
||||||
// has because damage always triggers it)
|
|
||||||
let old_tgt_not_threat = !old_tgt.aggro_on;
|
|
||||||
let old_tgt_further =
|
|
||||||
tgt_pos.0.distance(pos.0)
|
|
||||||
< old_tgt_pos.0.distance(pos.0)
|
|
||||||
* FUZZY_DIST_COMPARISON;
|
|
||||||
let new_tgt_hostile = read_data
|
|
||||||
.alignments
|
|
||||||
.get(attacker)
|
|
||||||
.zip(alignment)
|
|
||||||
.map_or(false, |(attacker, us)| {
|
|
||||||
us.hostile_towards(*attacker)
|
|
||||||
});
|
|
||||||
old_tgt_not_threat
|
|
||||||
|| (old_tgt_further && new_tgt_hostile)
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Select the attacker as the new target
|
|
||||||
if more_dangerous_than_old_target {
|
|
||||||
agent.target = Some(Target {
|
agent.target = Some(Target {
|
||||||
target: attacker,
|
target: attacker,
|
||||||
hostile: true,
|
hostile: true,
|
||||||
@ -359,10 +324,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remember this attack if we're an RtSim entity
|
// Remember this attack if we're an RtSim entity
|
||||||
if let Some(tgt_stats) =
|
if let Some(attacker_stats) =
|
||||||
data.rtsim_entity.and(read_data.stats.get(attacker))
|
data.rtsim_entity.and(read_data.stats.get(attacker))
|
||||||
{
|
{
|
||||||
agent.add_enemy(&tgt_stats.name, read_data.time.0);
|
agent.add_enemy(
|
||||||
|
&attacker_stats.name,
|
||||||
|
read_data.time.0,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2518,4 +2486,36 @@ impl<'a> AgentData<'a> {
|
|||||||
fn below_flee_health(&self, agent: &Agent) -> bool {
|
fn below_flee_health(&self, agent: &Agent) -> bool {
|
||||||
self.damage.min(1.0) < agent.psyche.flee_health
|
self.damage.min(1.0) < agent.psyche.flee_health
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_entity_more_dangerous_than_target(
|
||||||
|
&self,
|
||||||
|
entity: EcsEntity,
|
||||||
|
target: Target,
|
||||||
|
read_data: &ReadData,
|
||||||
|
) -> bool {
|
||||||
|
let entity_pos = read_data.positions.get(entity);
|
||||||
|
let target_pos = read_data.positions.get(target.target);
|
||||||
|
|
||||||
|
entity_pos.map_or(false, |entity_pos| {
|
||||||
|
target_pos.map_or(true, |target_pos| {
|
||||||
|
// Fuzzy factor that makes it harder for players to cheese enemies by making
|
||||||
|
// them quickly flip aggro between two players.
|
||||||
|
// It does this by only switching aggro if the entity is closer to the enemy by
|
||||||
|
// a specific proportional threshold.
|
||||||
|
const FUZZY_DIST_COMPARISON: f32 = 0.8;
|
||||||
|
|
||||||
|
let is_target_further = target_pos.0.distance(entity_pos.0)
|
||||||
|
< target_pos.0.distance(entity_pos.0) * FUZZY_DIST_COMPARISON;
|
||||||
|
let is_entity_hostile = read_data
|
||||||
|
.alignments
|
||||||
|
.get(entity)
|
||||||
|
.zip(self.alignment)
|
||||||
|
.map_or(false, |(entity, me)| me.hostile_towards(*entity));
|
||||||
|
|
||||||
|
// Consider entity more dangerous than target if entity is closer or if target
|
||||||
|
// had not triggered aggro.
|
||||||
|
!target.aggro_on || (is_target_further && is_entity_hostile)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user