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(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
63 StateUpdate::from(data)
64 }
65 fn on_input(
66 &self,
67 data: &JoinData,
68 _input: InputKind,
69 _output_events: &mut OutputEvents,
70 ) -> StateUpdate {
71 StateUpdate::from(data)
72 }
73
74 fn start_input(
75 &self,
76 data: &JoinData,
77 input: InputKind,
78 target_entity: Option<Uid>,
79 select_pos: Option<Vec3<f32>>,
80 output_events: &mut OutputEvents,
81 ) -> StateUpdate {
82 let mut update = self.on_input(data, input, output_events);
83 update.queued_inputs.insert(input, InputAttr {
84 select_pos,
85 target_entity,
86 });
87 update
88 }
89 fn cancel_input(&self, data: &JoinData, input: InputKind) -> StateUpdate {
90 let mut update = StateUpdate::from(data);
91 update.removed_inputs.push(input);
92 update
93 }
94 fn handle_event(
95 &self,
96 data: &JoinData,
97 output_events: &mut OutputEvents,
98 event: ControlAction,
99 ) -> StateUpdate {
100 match event {
101 ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data, output_events),
102 ControlAction::InventoryAction(inv_action) => {
103 self.manipulate_loadout(data, output_events, inv_action)
104 },
105 ControlAction::Wield => self.wield(data, output_events),
106 ControlAction::GlideWield => self.glide_wield(data, output_events),
107 ControlAction::Unwield => self.unwield(data, output_events),
108 ControlAction::Sit => self.sit(data, output_events),
109 ControlAction::Crawl => self.crawl(data, output_events),
110 ControlAction::Dance => self.dance(data, output_events),
111 ControlAction::Sneak => {
112 if data.mount_data.is_none() && data.volume_mount_data.is_none() {
113 self.sneak(data, output_events)
114 } else {
115 self.stand(data, output_events)
116 }
117 },
118 ControlAction::Stand => self.stand(data, output_events),
119 ControlAction::Talk => self.talk(data, output_events),
120 ControlAction::StartInput {
121 input,
122 target_entity,
123 select_pos,
124 } => self.start_input(data, input, target_entity, select_pos, output_events),
125 ControlAction::CancelInput(input) => self.cancel_input(data, input),
126 }
127 }
128}
129
130pub struct JoinData<'a> {
132 pub entity: Entity,
133 pub uid: &'a Uid,
134 pub character: &'a CharacterState,
135 pub character_activity: &'a CharacterActivity,
136 pub pos: &'a Pos,
137 pub vel: &'a Vel,
138 pub ori: &'a Ori,
139 pub scale: Option<&'a Scale>,
140 pub mass: &'a Mass,
141 pub density: &'a Density,
142 pub dt: &'a DeltaTime,
143 pub time: &'a Time,
144 pub controller: &'a Controller,
145 pub inputs: &'a ControllerInputs,
146 pub health: Option<&'a Health>,
147 pub heads: Option<&'a Heads>,
148 pub energy: &'a Energy,
149 pub inventory: Option<&'a Inventory>,
150 pub body: &'a Body,
151 pub physics: &'a PhysicsState,
152 pub melee_attack: Option<&'a Melee>,
153 pub updater: &'a LazyUpdate,
154 pub stats: &'a Stats,
155 pub skill_set: &'a SkillSet,
156 pub active_abilities: Option<&'a ActiveAbilities>,
157 pub ability_map: &'a AbilityMap,
158 pub msm: &'a MaterialStatManifest,
159 pub combo: Option<&'a Combo>,
160 pub alignment: Option<&'a comp::Alignment>,
161 pub terrain: &'a TerrainGrid,
162 pub mount_data: Option<&'a Is<Rider>>,
163 pub volume_mount_data: Option<&'a Is<VolumeRider>>,
164 pub stance: Option<&'a Stance>,
165 pub id_maps: &'a Read<'a, IdMaps>,
166 pub alignments: &'a ReadStorage<'a, Alignment>,
167 pub prev_phys_caches: &'a ReadStorage<'a, PreviousPhysCache>,
168}
169
170pub struct JoinStruct<'a> {
171 pub entity: Entity,
172 pub uid: &'a Uid,
173 pub char_state: FlaggedAccessMut<'a, &'a mut CharacterState, CharacterState>,
174 pub character_activity: FlaggedAccessMut<'a, &'a mut CharacterActivity, CharacterActivity>,
175 pub pos: &'a mut Pos,
176 pub vel: &'a mut Vel,
177 pub ori: &'a mut Ori,
178 pub scale: Option<&'a Scale>,
179 pub mass: &'a Mass,
180 pub density: FlaggedAccessMut<'a, &'a mut Density, Density>,
181 pub energy: FlaggedAccessMut<'a, &'a mut Energy, Energy>,
182 pub inventory: Option<&'a Inventory>,
183 pub controller: &'a mut Controller,
184 pub health: Option<&'a Health>,
185 pub heads: Option<&'a Heads>,
186 pub body: &'a Body,
187 pub physics: &'a PhysicsState,
188 pub melee_attack: Option<&'a Melee>,
189 pub beam: Option<&'a Beam>,
190 pub stat: &'a Stats,
191 pub skill_set: &'a SkillSet,
192 pub active_abilities: Option<&'a ActiveAbilities>,
193 pub combo: Option<&'a Combo>,
194 pub alignment: Option<&'a comp::Alignment>,
195 pub terrain: &'a TerrainGrid,
196 pub mount_data: Option<&'a Is<Rider>>,
197 pub volume_mount_data: Option<&'a Is<VolumeRider>>,
198 pub stance: Option<&'a Stance>,
199 pub id_maps: &'a Read<'a, IdMaps>,
200 pub alignments: &'a ReadStorage<'a, Alignment>,
201 pub prev_phys_caches: &'a ReadStorage<'a, PreviousPhysCache>,
202}
203
204impl<'a> JoinData<'a> {
205 pub fn new(
206 j: &'a JoinStruct<'a>,
207 updater: &'a LazyUpdate,
208 dt: &'a DeltaTime,
209 time: &'a Time,
210 msm: &'a MaterialStatManifest,
211 ability_map: &'a AbilityMap,
212 ) -> Self {
213 Self {
214 entity: j.entity,
215 uid: j.uid,
216 character: &j.char_state,
217 character_activity: &j.character_activity,
218 pos: j.pos,
219 vel: j.vel,
220 ori: j.ori,
221 scale: j.scale,
222 mass: j.mass,
223 density: &j.density,
224 energy: &j.energy,
225 inventory: j.inventory,
226 controller: j.controller,
227 inputs: &j.controller.inputs,
228 health: j.health,
229 heads: j.heads,
230 body: j.body,
231 physics: j.physics,
232 melee_attack: j.melee_attack,
233 stats: j.stat,
234 skill_set: j.skill_set,
235 updater,
236 dt,
237 time,
238 msm,
239 ability_map,
240 combo: j.combo,
241 alignment: j.alignment,
242 terrain: j.terrain,
243 active_abilities: j.active_abilities,
244 mount_data: j.mount_data,
245 volume_mount_data: j.volume_mount_data,
246 stance: j.stance,
247 id_maps: j.id_maps,
248 alignments: j.alignments,
249 prev_phys_caches: j.prev_phys_caches,
250 }
251 }
252}