use crate::prelude::*;
use beet_core::prelude::*;
use beet_flow::prelude::*;
use beet_spatial::prelude::*;
#[action(find_steer_target)]
#[derive(Debug, Clone, PartialEq, Component, Reflect)]
#[reflect(Default, Component)]
#[require(StatId, StatValueGoal)]
pub struct FindStatSteerTarget {}
impl Default for FindStatSteerTarget {
fn default() -> Self { Self {} }
}
impl FindStatSteerTarget {}
fn find_steer_target(
ev: On<GetOutcome>,
mut commands: Commands,
targets: Query<(&StatId, &StatValue, &ChildOf), With<StatProvider>>,
query: Populated<(&FindStatSteerTarget, &StatId, &StatValueGoal)>,
agents: AgentQuery<&Transform>,
transforms: Query<&Transform>,
) -> Result {
let (_action, goal_id, value_goal) = query.get(ev.event_target())?;
let agent = agents.entity(ev.event_target());
let agent_transform = agents.get(ev.event_target())?;
let mut best_score = f32::MAX;
let mut closest_target = None;
for (pickup_id, pickup_value, pickup_parent) in targets.iter() {
if pickup_id != goal_id {
continue;
}
let pickup_transform = transforms
.get(pickup_parent.parent())
.expect(&expect_action::to_have_other(pickup_parent));
let new_dist = Vec3::distance(
agent_transform.translation,
pickup_transform.translation,
);
let new_value =
match (value_goal, f32::is_sign_positive(pickup_value.0)) {
(StatValueGoal::High, true) => pickup_value.0,
(StatValueGoal::Low, false) => pickup_value.0,
_ => continue,
};
let new_score = new_dist + new_value;
if new_score < best_score {
best_score = new_score;
closest_target = Some(pickup_parent.parent());
}
}
if let Some(closest_target) = closest_target {
commands
.entity(agent)
.insert(SteerTarget::Entity(closest_target));
}
Ok(())
}