diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 2768bae257..e45c9e468d 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -420,15 +420,23 @@ pub struct Target { pub selected_at: f64, /// Whether the target has come close enough to trigger aggro. pub aggro_on: bool, + pub last_known_pos: Option>, } impl Target { - pub fn new(target: EcsEntity, hostile: bool, selected_at: f64, aggro_on: bool) -> Self { + pub fn new( + target: EcsEntity, + hostile: bool, + selected_at: f64, + aggro_on: bool, + last_known_pos: Option>, + ) -> Self { Self { target, hostile, selected_at, aggro_on, + last_known_pos, } } } diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index eeec85efd0..3b8061ad16 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -735,6 +735,7 @@ impl<'a> AgentData<'a> { hostile: attack_target, selected_at: read_data.time.0, aggro_on, + last_known_pos: get_pos(entity).map(|pos| pos.0), }) } @@ -1341,14 +1342,24 @@ impl<'a> AgentData<'a> { controller.push_utterance(UtteranceKind::Angry); } - agent.target = Some(Target::new(attacker, true, read_data.time.0, true)); + let attacker_pos = read_data.positions.get(attacker).map(|pos| pos.0); + agent.target = Some(Target::new( + attacker, + true, + read_data.time.0, + true, + attacker_pos, + )); if let Some(tgt_pos) = read_data.positions.get(attacker) { if is_dead_or_invulnerable(attacker, read_data) { - // FIXME?: Shouldn't target be set to `None`? - // If is dead, then probably. If invulnerable, maybe not. - agent.target = - Some(Target::new(target, false, read_data.time.0, false)); + agent.target = Some(Target::new( + target, + false, + read_data.time.0, + false, + Some(tgt_pos.0), + )); self.idle(agent, controller, read_data, rng); } else { diff --git a/server/src/sys/agent/behavior_tree.rs b/server/src/sys/agent/behavior_tree.rs index 18a34b5372..3ccec1fc77 100644 --- a/server/src/sys/agent/behavior_tree.rs +++ b/server/src/sys/agent/behavior_tree.rs @@ -266,6 +266,11 @@ fn target_if_attacked(bdata: &mut BehaviorData) -> bool { hostile: true, selected_at: bdata.read_data.time.0, aggro_on: true, + last_known_pos: bdata + .read_data + .positions + .get(attacker) + .map(|pos| pos.0), }); } @@ -440,7 +445,15 @@ fn set_owner_if_no_target(bdata: &mut BehaviorData) -> bool { if bdata.agent.target.is_none() && small_chance { if let Some(Alignment::Owned(owner)) = bdata.agent_data.alignment { if let Some(owner) = get_entity_by_id(owner.id(), bdata.read_data) { - bdata.agent.target = Some(Target::new(owner, false, bdata.read_data.time.0, false)); + let owner_pos = bdata.read_data.positions.get(owner).map(|pos| pos.0); + + bdata.agent.target = Some(Target::new( + owner, + false, + bdata.read_data.time.0, + false, + owner_pos, + )); } } } diff --git a/server/src/sys/agent/behavior_tree/interaction.rs b/server/src/sys/agent/behavior_tree/interaction.rs index 5d13bb524d..9d1088287f 100644 --- a/server/src/sys/agent/behavior_tree/interaction.rs +++ b/server/src/sys/agent/behavior_tree/interaction.rs @@ -91,7 +91,15 @@ pub fn handle_inbox_talk(bdata: &mut BehaviorData) -> bool { if let Some(AgentEvent::Talk(by, subject)) = agent.inbox.pop_front() { if agent.allowed_to_speak() { if let Some(target) = get_entity_by_id(by.id(), read_data) { - agent.target = Some(Target::new(target, false, read_data.time.0, false)); + let target_pos = read_data.positions.get(target).map(|pos| pos.0); + + agent.target = Some(Target::new( + target, + false, + read_data.time.0, + false, + target_pos, + )); if agent_data.look_toward(controller, read_data, target) { controller.push_action(ControlAction::Stand); @@ -415,7 +423,15 @@ pub fn handle_inbox_trade_invite(bdata: &mut BehaviorData) -> bool { controller.push_action(ControlAction::Stand); controller.push_action(ControlAction::Talk); if let Some(target) = get_entity_by_id(with.id(), read_data) { - agent.target = Some(Target::new(target, false, read_data.time.0, false)); + let target_pos = read_data.positions.get(target).map(|pos| pos.0); + + agent.target = Some(Target::new( + target, + false, + read_data.time.0, + false, + target_pos, + )); } controller.push_invite_response(InviteResponse::Accept); agent.behavior.unset(BehaviorState::TRADING_ISSUER); @@ -454,7 +470,15 @@ pub fn handle_inbox_trade_accepted(bdata: &mut BehaviorData) -> bool { if let Some(AgentEvent::TradeAccepted(with)) = agent.inbox.pop_front() { if !agent.behavior.is(BehaviorState::TRADING) { if let Some(target) = get_entity_by_id(with.id(), read_data) { - agent.target = Some(Target::new(target, false, read_data.time.0, false)); + let target_pos = read_data.positions.get(target).map(|pos| pos.0); + + agent.target = Some(Target::new( + target, + false, + read_data.time.0, + false, + target_pos, + )); } agent.behavior.set(BehaviorState::TRADING); agent.behavior.set(BehaviorState::TRADING_ISSUER);