veloren_common/states/
behavior.rs

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    // Impl these to provide behavior for these inputs
23    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
135/// Read-Only Data sent from Character Behavior System to behavior fn's
136pub 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}