1use crate::{
2 comp::{
3 self, ActiveAbilities, Alignment, Beam, Body, CharacterActivity, CharacterState, Combo,
4 ControlAction, Controller, ControllerInputs, Density, Energy, Health, InputAttr, InputKind,
5 Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, PreviousPhysCache, Scale,
6 SkillSet, Stance, StateUpdate, Stats, Vel,
7 body::parts::Heads,
8 character_state::OutputEvents,
9 item::{MaterialStatManifest, tool::AbilityMap},
10 },
11 link::Is,
12 mounting::{Rider, VolumeRider},
13 resources::{DeltaTime, Time},
14 terrain::TerrainGrid,
15 uid::{IdMaps, Uid},
16};
17use specs::{Entity, LazyUpdate, Read, ReadStorage, storage::FlaggedAccessMut};
18use vek::*;
19
20pub trait CharacterBehavior {
21 fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate;
22 fn swap_equipped_weapons(
24 &self,
25 data: &JoinData,
26 _output_events: &mut OutputEvents,
27 ) -> StateUpdate {
28 StateUpdate::from(data)
29 }
30 fn manipulate_loadout(
31 &self,
32 data: &JoinData,
33 _output_events: &mut OutputEvents,
34 _inv_action: InventoryAction,
35 ) -> StateUpdate {
36 StateUpdate::from(data)
37 }
38 fn wield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
39 StateUpdate::from(data)
40 }
41 fn glide_wield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
42 StateUpdate::from(data)
43 }
44 fn unwield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
45 StateUpdate::from(data)
46 }
47 fn sit(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
48 StateUpdate::from(data)
49 }
50 fn crawl(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
51 StateUpdate::from(data)
52 }
53 fn dance(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
54 StateUpdate::from(data)
55 }
56 fn sneak(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
57 StateUpdate::from(data)
58 }
59 fn stand(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
60 StateUpdate::from(data)
61 }
62 fn talk(
63 &self,
64 data: &JoinData,
65 _output_events: &mut OutputEvents,
66 _tgt: Option<Uid>,
67 ) -> StateUpdate {
68 StateUpdate::from(data)
69 }
70 fn on_input(
71 &self,
72 data: &JoinData,
73 _input: InputKind,
74 _output_events: &mut OutputEvents,
75 ) -> StateUpdate {
76 StateUpdate::from(data)
77 }
78
79 fn start_input(
80 &self,
81 data: &JoinData,
82 input: InputKind,
83 target_entity: Option<Uid>,
84 select_pos: Option<Vec3<f32>>,
85 output_events: &mut OutputEvents,
86 ) -> StateUpdate {
87 let mut update = self.on_input(data, input, output_events);
88 update.queued_inputs.insert(input, InputAttr {
89 select_pos,
90 target_entity,
91 });
92 update
93 }
94 fn cancel_input(&self, data: &JoinData, input: InputKind) -> StateUpdate {
95 let mut update = StateUpdate::from(data);
96 update.removed_inputs.push(input);
97 update
98 }
99 fn handle_event(
100 &self,
101 data: &JoinData,
102 output_events: &mut OutputEvents,
103 event: ControlAction,
104 ) -> StateUpdate {
105 match event {
106 ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data, output_events),
107 ControlAction::InventoryAction(inv_action) => {
108 self.manipulate_loadout(data, output_events, inv_action)
109 },
110 ControlAction::Wield => self.wield(data, output_events),
111 ControlAction::GlideWield => self.glide_wield(data, output_events),
112 ControlAction::Unwield => self.unwield(data, output_events),
113 ControlAction::Sit => self.sit(data, output_events),
114 ControlAction::Crawl => self.crawl(data, output_events),
115 ControlAction::Dance => self.dance(data, output_events),
116 ControlAction::Sneak => {
117 if data.mount_data.is_none() && data.volume_mount_data.is_none() {
118 self.sneak(data, output_events)
119 } else {
120 self.stand(data, output_events)
121 }
122 },
123 ControlAction::Stand => self.stand(data, output_events),
124 ControlAction::Talk(tgt) => self.talk(data, output_events, tgt),
125 ControlAction::StartInput {
126 input,
127 target_entity,
128 select_pos,
129 } => self.start_input(data, input, target_entity, select_pos, output_events),
130 ControlAction::CancelInput { input } => self.cancel_input(data, input),
131 }
132 }
133}
134
135pub struct JoinData<'a> {
137 pub entity: Entity,
138 pub uid: &'a Uid,
139 pub character: &'a CharacterState,
140 pub character_activity: &'a CharacterActivity,
141 pub pos: &'a Pos,
142 pub vel: &'a Vel,
143 pub ori: &'a Ori,
144 pub scale: Option<&'a Scale>,
145 pub mass: &'a Mass,
146 pub density: &'a Density,
147 pub dt: &'a DeltaTime,
148 pub time: &'a Time,
149 pub controller: &'a Controller,
150 pub inputs: &'a ControllerInputs,
151 pub health: Option<&'a Health>,
152 pub heads: Option<&'a Heads>,
153 pub energy: &'a Energy,
154 pub inventory: Option<&'a Inventory>,
155 pub body: &'a Body,
156 pub physics: &'a PhysicsState,
157 pub melee_attack: Option<&'a Melee>,
158 pub updater: &'a LazyUpdate,
159 pub stats: &'a Stats,
160 pub skill_set: &'a SkillSet,
161 pub active_abilities: Option<&'a ActiveAbilities>,
162 pub ability_map: &'a AbilityMap,
163 pub msm: &'a MaterialStatManifest,
164 pub combo: Option<&'a Combo>,
165 pub alignment: Option<&'a comp::Alignment>,
166 pub terrain: &'a TerrainGrid,
167 pub mount_data: Option<&'a Is<Rider>>,
168 pub volume_mount_data: Option<&'a Is<VolumeRider>>,
169 pub stance: Option<&'a Stance>,
170 pub id_maps: &'a Read<'a, IdMaps>,
171 pub alignments: &'a ReadStorage<'a, Alignment>,
172 pub prev_phys_caches: &'a ReadStorage<'a, PreviousPhysCache>,
173 pub bodies: &'a ReadStorage<'a, Body>,
174}
175
176pub struct JoinStruct<'a> {
177 pub entity: Entity,
178 pub uid: &'a Uid,
179 pub char_state: FlaggedAccessMut<'a, &'a mut CharacterState, CharacterState>,
180 pub character_activity: FlaggedAccessMut<'a, &'a mut CharacterActivity, CharacterActivity>,
181 pub pos: &'a mut Pos,
182 pub vel: &'a mut Vel,
183 pub ori: &'a mut Ori,
184 pub scale: Option<&'a Scale>,
185 pub mass: &'a Mass,
186 pub density: FlaggedAccessMut<'a, &'a mut Density, Density>,
187 pub energy: FlaggedAccessMut<'a, &'a mut Energy, Energy>,
188 pub inventory: Option<&'a Inventory>,
189 pub controller: &'a mut Controller,
190 pub health: Option<&'a Health>,
191 pub heads: Option<&'a Heads>,
192 pub body: &'a Body,
193 pub physics: &'a PhysicsState,
194 pub melee_attack: Option<&'a Melee>,
195 pub beam: Option<&'a Beam>,
196 pub stat: &'a Stats,
197 pub skill_set: &'a SkillSet,
198 pub active_abilities: Option<&'a ActiveAbilities>,
199 pub combo: Option<&'a Combo>,
200 pub alignment: Option<&'a comp::Alignment>,
201 pub terrain: &'a TerrainGrid,
202 pub mount_data: Option<&'a Is<Rider>>,
203 pub volume_mount_data: Option<&'a Is<VolumeRider>>,
204 pub stance: Option<&'a Stance>,
205 pub id_maps: &'a Read<'a, IdMaps>,
206 pub alignments: &'a ReadStorage<'a, Alignment>,
207 pub prev_phys_caches: &'a ReadStorage<'a, PreviousPhysCache>,
208 pub bodies: &'a ReadStorage<'a, Body>,
209}
210
211impl<'a> JoinData<'a> {
212 pub fn new(
213 j: &'a JoinStruct<'a>,
214 updater: &'a LazyUpdate,
215 dt: &'a DeltaTime,
216 time: &'a Time,
217 msm: &'a MaterialStatManifest,
218 ability_map: &'a AbilityMap,
219 ) -> Self {
220 Self {
221 entity: j.entity,
222 uid: j.uid,
223 character: &j.char_state,
224 character_activity: &j.character_activity,
225 pos: j.pos,
226 vel: j.vel,
227 ori: j.ori,
228 scale: j.scale,
229 mass: j.mass,
230 density: &j.density,
231 energy: &j.energy,
232 inventory: j.inventory,
233 controller: j.controller,
234 inputs: &j.controller.inputs,
235 health: j.health,
236 heads: j.heads,
237 body: j.body,
238 physics: j.physics,
239 melee_attack: j.melee_attack,
240 stats: j.stat,
241 skill_set: j.skill_set,
242 updater,
243 dt,
244 time,
245 msm,
246 ability_map,
247 combo: j.combo,
248 alignment: j.alignment,
249 terrain: j.terrain,
250 active_abilities: j.active_abilities,
251 mount_data: j.mount_data,
252 volume_mount_data: j.volume_mount_data,
253 stance: j.stance,
254 id_maps: j.id_maps,
255 alignments: j.alignments,
256 prev_phys_caches: j.prev_phys_caches,
257 bodies: j.bodies,
258 }
259 }
260}