veloren_common/states/
glide_wield.rs1use super::utils::*;
2use crate::{
3    comp::{
4        CharacterState, InventoryAction, Ori, StateUpdate, character_state::OutputEvents,
5        controller::InputKind, slot::EquipSlot,
6    },
7    event::LocalEvent,
8    outcome::Outcome,
9    states::{
10        behavior::{CharacterBehavior, JoinData},
11        glide, idle,
12    },
13};
14use serde::{Deserialize, Serialize};
15
16#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
17pub struct Data {
18    pub ori: Ori,
19    span_length: f32,
20    chord_length: f32,
21}
22
23impl From<&JoinData<'_>> for Data {
24    fn from(data: &JoinData) -> Self {
25        let scale = data.body.dimensions().z.sqrt();
26        Self {
27            span_length: scale * 4.5,
53            chord_length: scale,
54            ori: *data.ori,
55        }
56    }
57}
58
59impl CharacterBehavior for Data {
60    fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
61        let mut update = StateUpdate::from(data);
62
63        handle_orientation(data, &mut update, 1.0, None);
64        handle_move(data, &mut update, 1.0);
65        handle_jump(data, output_events, &mut update, 1.0);
66        if input_is_pressed(data, InputKind::Roll) {
67            handle_input(data, output_events, &mut update, InputKind::Roll);
68        }
69        handle_glider_input_or(data, &mut update, output_events, handle_wield);
70
71        if matches!(update.character, CharacterState::GlideWield(_)) {
73            update.character = if data.physics.on_ground.is_none() {
75                CharacterState::Glide(glide::Data::new(
76                    self.span_length,
77                    self.chord_length,
78                    self.ori,
79                ))
80            } else if data
82                .inventory
83                .and_then(|inv| inv.equipped(EquipSlot::Glider))
84                .is_some()
85                && data.physics.in_liquid().is_none_or(|depth| depth < 0.5)
86            {
87                CharacterState::GlideWield(Self {
88                    ori: self.ori.slerped_towards(
90                        data.ori.slerped_towards(
91                            Ori::from(data.inputs.look_dir).pitched_up(0.6),
92                            (1.0 + data.inputs.look_dir.dot(*data.ori.look_dir()).max(0.0)) / 3.0,
93                        ),
94                        5.0 * data.dt.0,
95                    ),
96                    ..*self
97                })
98            } else {
99                CharacterState::Idle(idle::Data::default())
100            };
101        }
102
103        update
104    }
105
106    fn manipulate_loadout(
107        &self,
108        data: &JoinData,
109        output_events: &mut OutputEvents,
110        inv_action: InventoryAction,
111    ) -> StateUpdate {
112        let mut update = StateUpdate::from(data);
113        handle_manipulate_loadout(data, output_events, &mut update, inv_action);
114        update
115    }
116
117    fn unwield(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
118        let mut update = StateUpdate::from(data);
119        output_events.emit_local(LocalEvent::CreateOutcome(Outcome::Glider {
120            pos: data.pos.0,
121            wielded: false,
122        }));
123        update.character = CharacterState::Idle(idle::Data::default());
124        update
125    }
126
127    fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
128        let mut update = StateUpdate::from(data);
129        attempt_sit(data, &mut update);
130        update
131    }
132
133    fn crawl(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
134        let mut update = StateUpdate::from(data);
135        attempt_crawl(data, &mut update);
136        update
137    }
138
139    fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
140        let mut update = StateUpdate::from(data);
141        attempt_dance(data, &mut update);
142        update
143    }
144
145    fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
146        let mut update = StateUpdate::from(data);
147        attempt_sneak(data, &mut update);
148        update
149    }
150}