use npc_engine_core::{
impl_task_boxed_methods, AgentId, IdleTask, StateDiffRef, StateDiffRefMut, Task, TaskDuration,
};
use npc_engine_utils::OptionDiffDomain;
use crate::{
constants::{MAP, MAX_AMMO, MAX_HP},
domain::{CaptureDomain, DisplayAction},
};
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub struct Pick;
impl Task<CaptureDomain> for Pick {
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();
let location = agent_state.cur_or_last_location;
match location {
_ if location == MAP.ammo_location() => {
agent_state.ammo = (agent_state.ammo + 1).min(MAX_AMMO);
diff.ammo = 0;
diff.ammo_tick = (tick & 0xff) as u8;
}
_ if location == MAP.medkit_location() => {
agent_state.hp = (agent_state.hp + 1).min(MAX_HP);
diff.medkit = 0;
diff.medkit_tick = (tick & 0xff) as u8;
}
_ => unimplemented!(),
}
Some(Box::new(IdleTask))
}
fn display_action(&self) -> DisplayAction {
DisplayAction::Pick
}
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.next_location.is_some() {
false
} else {
let location = agent_state.cur_or_last_location;
(location == MAP.ammo_location() && state.ammo > 0)
|| (location == MAP.medkit_location() && state.medkit > 0)
}
})
}
impl_task_boxed_methods!(CaptureDomain);
}