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(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
63        StateUpdate::from(data)
64    }
65    // start_input has custom implementation in the following character states that
66    // may also need to be modified when changes are made here: ComboMelee2
67    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
122/// Read-Only Data sent from Character Behavior System to behavior fn's
123pub 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}