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