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 = {
26 let mut scale = data.body.dimensions().z;
27 if let crate::comp::Body::Humanoid(humanoid) = data.body {
28 scale /= humanoid.height_scale()
29 };
30 scale.sqrt()
31 };
32
33 Self {
34 span_length: scale * 3.0,
60 chord_length: scale * 0.8,
61 ori: *data.ori,
62 }
63 }
64}
65
66impl CharacterBehavior for Data {
67 fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
68 let mut update = StateUpdate::from(data);
69
70 handle_orientation(data, &mut update, 1.0, None);
71 handle_move(data, &mut update, 1.0);
72 handle_jump(data, output_events, &mut update, 1.0);
73 if input_is_pressed(data, InputKind::Roll) {
74 handle_input(data, output_events, &mut update, InputKind::Roll);
75 }
76 handle_glider_input_or(data, &mut update, output_events, handle_wield);
77
78 if matches!(update.character, CharacterState::GlideWield(_)) {
80 update.character = if data.physics.on_ground.is_none() {
82 CharacterState::Glide(glide::Data::new(
83 self.span_length,
84 self.chord_length,
85 self.ori,
86 ))
87 } else if data
89 .inventory
90 .and_then(|inv| inv.equipped(EquipSlot::Glider))
91 .is_some()
92 && data.physics.in_liquid().is_none_or(|depth| depth < 0.5)
93 {
94 CharacterState::GlideWield(Self {
95 ori: self.ori.slerped_towards(
97 data.ori.slerped_towards(
98 Ori::from(data.inputs.look_dir).pitched_up(0.6),
99 (1.0 + data.inputs.look_dir.dot(*data.ori.look_dir()).max(0.0)) / 3.0,
100 ),
101 5.0 * data.dt.0,
102 ),
103 ..*self
104 })
105 } else {
106 CharacterState::Idle(idle::Data::default())
107 };
108 }
109
110 update
111 }
112
113 fn manipulate_loadout(
114 &self,
115 data: &JoinData,
116 output_events: &mut OutputEvents,
117 inv_action: InventoryAction,
118 ) -> StateUpdate {
119 let mut update = StateUpdate::from(data);
120 handle_manipulate_loadout(data, output_events, &mut update, inv_action);
121 update
122 }
123
124 fn unwield(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
125 let mut update = StateUpdate::from(data);
126 output_events.emit_local(LocalEvent::CreateOutcome(Outcome::Glider {
127 pos: data.pos.0,
128 wielded: false,
129 }));
130 update.character = CharacterState::Idle(idle::Data::default());
131 update
132 }
133
134 fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
135 let mut update = StateUpdate::from(data);
136 attempt_sit(data, &mut update);
137 update
138 }
139
140 fn crawl(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
141 let mut update = StateUpdate::from(data);
142 attempt_crawl(data, &mut update);
143 update
144 }
145
146 fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
147 let mut update = StateUpdate::from(data);
148 attempt_dance(data, &mut update);
149 update
150 }
151
152 fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate {
153 let mut update = StateUpdate::from(data);
154 attempt_sneak(data, &mut update);
155 update
156 }
157}