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}