use npc_engine_core::{
impl_task_boxed_methods, AgentId, IdleTask, StateDiffRef, StateDiffRefMut, Task, TaskDuration,
};
use npc_engine_utils::OptionDiffDomain;
use crate::domain::{CaptureDomain, DisplayAction};
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Shoot(pub AgentId);
impl Task<CaptureDomain> for Shoot {
fn duration(
&self,
_tick: u64,
_state_diff: StateDiffRef<CaptureDomain>,
_agent: AgentId,
) -> TaskDuration {
0
}
fn weight(&self, _tick: u64, _state_diff: StateDiffRef<CaptureDomain>, _agent: AgentId) -> f32 {
10.0
}
fn execute(
&self,
_tick: u64,
state_diff: StateDiffRefMut<CaptureDomain>,
agent: AgentId,
) -> Option<Box<dyn Task<CaptureDomain>>> {
let diff = CaptureDomain::get_cur_state_mut(state_diff);
let agent_state = diff.agents.get_mut(&agent).unwrap();
agent_state.ammo -= 1;
let target_state = diff.agents.get_mut(&self.0).unwrap();
if target_state.hp > 0 {
target_state.hp -= 1;
}
if target_state.hp == 0 {
diff.agents.remove(&self.0);
}
Some(Box::new(IdleTask))
}
fn display_action(&self) -> DisplayAction {
DisplayAction::Shoot(self.0)
}
fn is_valid(
&self,
_tick: u64,
state_diff: StateDiffRef<CaptureDomain>,
agent: AgentId,
) -> bool {
let state = CaptureDomain::get_cur_state(state_diff);
state.agents.get(&agent).map_or(false, |agent_state| {
if agent_state.ammo == 0 || agent_state.next_location.is_some() {
false
} else {
let location = agent_state.cur_or_last_location;
let target = state.agents.get(&self.0);
target.map_or(false, |target| {
target.cur_or_last_location == location
|| target
.next_location
.map_or(false, |next_location| next_location == location)
})
}
})
}
impl_task_boxed_methods!(CaptureDomain);
}