use crate::{
comp::{
self,
body::parts::Heads,
character_state::OutputEvents,
item::{tool::AbilityMap, MaterialStatManifest},
ActiveAbilities, Alignment, Beam, Body, CharacterActivity, CharacterState, Combo,
ControlAction, Controller, ControllerInputs, Density, Energy, Health, InputAttr, InputKind,
Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, PreviousPhysCache, Scale,
SkillSet, Stance, StateUpdate, Stats, Vel,
},
link::Is,
mounting::{Rider, VolumeRider},
resources::{DeltaTime, Time},
terrain::TerrainGrid,
uid::{IdMaps, Uid},
};
use specs::{storage::FlaggedAccessMut, Entity, LazyUpdate, Read, ReadStorage};
use vek::*;
pub trait CharacterBehavior {
fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate;
fn swap_equipped_weapons(
&self,
data: &JoinData,
_output_events: &mut OutputEvents,
) -> StateUpdate {
StateUpdate::from(data)
}
fn manipulate_loadout(
&self,
data: &JoinData,
_output_events: &mut OutputEvents,
_inv_action: InventoryAction,
) -> StateUpdate {
StateUpdate::from(data)
}
fn wield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn glide_wield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn unwield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn sit(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn dance(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn pet(
&self,
data: &JoinData,
_output_events: &mut OutputEvents,
_target_uid: Uid,
) -> StateUpdate {
StateUpdate::from(data)
}
fn sneak(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn stand(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn talk(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
StateUpdate::from(data)
}
fn start_input(
&self,
data: &JoinData,
input: InputKind,
target_entity: Option<Uid>,
select_pos: Option<Vec3<f32>>,
) -> StateUpdate {
let mut update = StateUpdate::from(data);
update.queued_inputs.insert(input, InputAttr {
select_pos,
target_entity,
});
update
}
fn cancel_input(&self, data: &JoinData, input: InputKind) -> StateUpdate {
let mut update = StateUpdate::from(data);
update.removed_inputs.push(input);
update
}
fn handle_event(
&self,
data: &JoinData,
output_events: &mut OutputEvents,
event: ControlAction,
) -> StateUpdate {
match event {
ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data, output_events),
ControlAction::InventoryAction(inv_action) => {
self.manipulate_loadout(data, output_events, inv_action)
},
ControlAction::Wield => self.wield(data, output_events),
ControlAction::GlideWield => self.glide_wield(data, output_events),
ControlAction::Unwield => self.unwield(data, output_events),
ControlAction::Sit => self.sit(data, output_events),
ControlAction::Dance => self.dance(data, output_events),
ControlAction::Pet { target_uid } => self.pet(data, output_events, target_uid),
ControlAction::Sneak => {
if data.mount_data.is_none() && data.volume_mount_data.is_none() {
self.sneak(data, output_events)
} else {
self.stand(data, output_events)
}
},
ControlAction::Stand => self.stand(data, output_events),
ControlAction::Talk => self.talk(data, output_events),
ControlAction::StartInput {
input,
target_entity,
select_pos,
} => self.start_input(data, input, target_entity, select_pos),
ControlAction::CancelInput(input) => self.cancel_input(data, input),
}
}
}
pub struct JoinData<'a> {
pub entity: Entity,
pub uid: &'a Uid,
pub character: &'a CharacterState,
pub character_activity: &'a CharacterActivity,
pub pos: &'a Pos,
pub vel: &'a Vel,
pub ori: &'a Ori,
pub scale: Option<&'a Scale>,
pub mass: &'a Mass,
pub density: &'a Density,
pub dt: &'a DeltaTime,
pub time: &'a Time,
pub controller: &'a Controller,
pub inputs: &'a ControllerInputs,
pub health: Option<&'a Health>,
pub heads: Option<&'a Heads>,
pub energy: &'a Energy,
pub inventory: Option<&'a Inventory>,
pub body: &'a Body,
pub physics: &'a PhysicsState,
pub melee_attack: Option<&'a Melee>,
pub updater: &'a LazyUpdate,
pub stats: &'a Stats,
pub skill_set: &'a SkillSet,
pub active_abilities: Option<&'a ActiveAbilities>,
pub ability_map: &'a AbilityMap,
pub msm: &'a MaterialStatManifest,
pub combo: Option<&'a Combo>,
pub alignment: Option<&'a comp::Alignment>,
pub terrain: &'a TerrainGrid,
pub mount_data: Option<&'a Is<Rider>>,
pub volume_mount_data: Option<&'a Is<VolumeRider>>,
pub stance: Option<&'a Stance>,
pub id_maps: &'a Read<'a, IdMaps>,
pub alignments: &'a ReadStorage<'a, Alignment>,
pub prev_phys_caches: &'a ReadStorage<'a, PreviousPhysCache>,
}
pub struct JoinStruct<'a> {
pub entity: Entity,
pub uid: &'a Uid,
pub char_state: FlaggedAccessMut<'a, &'a mut CharacterState, CharacterState>,
pub character_activity: FlaggedAccessMut<'a, &'a mut CharacterActivity, CharacterActivity>,
pub pos: &'a mut Pos,
pub vel: &'a mut Vel,
pub ori: &'a mut Ori,
pub scale: Option<&'a Scale>,
pub mass: &'a Mass,
pub density: FlaggedAccessMut<'a, &'a mut Density, Density>,
pub energy: FlaggedAccessMut<'a, &'a mut Energy, Energy>,
pub inventory: Option<&'a Inventory>,
pub controller: &'a mut Controller,
pub health: Option<&'a Health>,
pub heads: Option<&'a Heads>,
pub body: &'a Body,
pub physics: &'a PhysicsState,
pub melee_attack: Option<&'a Melee>,
pub beam: Option<&'a Beam>,
pub stat: &'a Stats,
pub skill_set: &'a SkillSet,
pub active_abilities: Option<&'a ActiveAbilities>,
pub combo: Option<&'a Combo>,
pub alignment: Option<&'a comp::Alignment>,
pub terrain: &'a TerrainGrid,
pub mount_data: Option<&'a Is<Rider>>,
pub volume_mount_data: Option<&'a Is<VolumeRider>>,
pub stance: Option<&'a Stance>,
pub id_maps: &'a Read<'a, IdMaps>,
pub alignments: &'a ReadStorage<'a, Alignment>,
pub prev_phys_caches: &'a ReadStorage<'a, PreviousPhysCache>,
}
impl<'a> JoinData<'a> {
pub fn new(
j: &'a JoinStruct<'a>,
updater: &'a LazyUpdate,
dt: &'a DeltaTime,
time: &'a Time,
msm: &'a MaterialStatManifest,
ability_map: &'a AbilityMap,
) -> Self {
Self {
entity: j.entity,
uid: j.uid,
character: &j.char_state,
character_activity: &j.character_activity,
pos: j.pos,
vel: j.vel,
ori: j.ori,
scale: j.scale,
mass: j.mass,
density: &j.density,
energy: &j.energy,
inventory: j.inventory,
controller: j.controller,
inputs: &j.controller.inputs,
health: j.health,
heads: j.heads,
body: j.body,
physics: j.physics,
melee_attack: j.melee_attack,
stats: j.stat,
skill_set: j.skill_set,
updater,
dt,
time,
msm,
ability_map,
combo: j.combo,
alignment: j.alignment,
terrain: j.terrain,
active_abilities: j.active_abilities,
mount_data: j.mount_data,
volume_mount_data: j.volume_mount_data,
stance: j.stance,
id_maps: j.id_maps,
alignments: j.alignments,
prev_phys_caches: j.prev_phys_caches,
}
}
}