veloren_common/states/
dive_melee.rs1use crate::{
2 combat,
3 comp::{CharacterState, MeleeConstructor, StateUpdate, character_state::OutputEvents},
4 states::{
5 behavior::{CharacterBehavior, JoinData},
6 utils::{StageSection, *},
7 },
8};
9use serde::{Deserialize, Serialize};
10use std::time::Duration;
11
12#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
14pub struct StaticData {
15 pub buildup_duration: Option<Duration>,
17 pub movement_duration: Duration,
19 pub swing_duration: Duration,
21 pub recover_duration: Duration,
23 pub vertical_speed: f32,
25 pub melee_constructor: MeleeConstructor,
27 pub max_scaling: f32,
29 pub ability_info: AbilityInfo,
31}
32
33#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
34pub struct Data {
35 pub static_data: StaticData,
38 pub timer: Duration,
40 pub stage_section: StageSection,
42 pub exhausted: bool,
44 pub max_vertical_speed: f32,
46}
47
48impl CharacterBehavior for Data {
49 fn behavior(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate {
50 let mut update = StateUpdate::from(data);
51
52 if let CharacterState::DiveMelee(c) = &mut update.character {
53 c.max_vertical_speed = c.max_vertical_speed.max(-data.vel.0.z);
54 }
55
56 match self.stage_section {
57 StageSection::Buildup => {
58 handle_orientation(data, &mut update, 0.5, None);
59 handle_move(data, &mut update, 0.3);
60
61 if let Some(buildup_duration) = self.static_data.buildup_duration {
62 if self.timer < buildup_duration {
63 if let CharacterState::DiveMelee(c) = &mut update.character {
64 c.timer = tick_attack_or_default(data, self.timer, None);
65 }
66 } else if let CharacterState::DiveMelee(c) = &mut update.character {
67 c.timer = Duration::default();
68 c.stage_section = StageSection::Action;
69 }
70 } else if let CharacterState::DiveMelee(c) = &mut update.character {
71 c.timer = Duration::default();
72 c.stage_section = StageSection::Action;
73 }
74 },
75 StageSection::Movement => {
76 handle_move(data, &mut update, 1.0);
77 if data.physics.on_ground.is_some() {
78 if let CharacterState::DiveMelee(c) = &mut update.character {
80 c.timer = Duration::default();
81 c.stage_section = StageSection::Action;
82 }
83 } else if self.timer < self.static_data.movement_duration {
84 if let CharacterState::DiveMelee(c) = &mut update.character {
85 c.timer = self
86 .timer
87 .checked_add(Duration::from_secs_f32(data.dt.0))
88 .unwrap_or_default();
89 }
90 } else {
91 end_ability(data, &mut update);
93 }
94 },
95 StageSection::Action => {
96 if !self.exhausted {
97 let precision_mult = combat::compute_precision_mult(data.inventory, data.msm);
99 let tool_stats = get_tool_stats(data, self.static_data.ability_info);
100 let scaling = self.max_vertical_speed / self.static_data.vertical_speed;
101 let scaling = scaling.min(self.static_data.max_scaling);
102
103 data.updater.insert(
104 data.entity,
105 self.static_data
106 .melee_constructor
107 .handle_scaling(scaling)
108 .create_melee(precision_mult, tool_stats),
109 );
110
111 if let CharacterState::DiveMelee(c) = &mut update.character {
112 c.timer = tick_attack_or_default(data, self.timer, None);
113 c.exhausted = true;
114 }
115 } else if self.timer < self.static_data.swing_duration {
116 if let CharacterState::DiveMelee(c) = &mut update.character {
117 c.timer = tick_attack_or_default(data, self.timer, None);
118 }
119 } else {
120 if let CharacterState::DiveMelee(c) = &mut update.character {
122 c.timer = Duration::default();
123 c.stage_section = StageSection::Recover;
124 }
125 }
126 },
127 StageSection::Recover => {
128 handle_orientation(data, &mut update, 0.5, None);
129 handle_move(data, &mut update, 0.3);
130
131 if self.timer < self.static_data.recover_duration {
132 if let CharacterState::DiveMelee(c) = &mut update.character {
134 c.timer = tick_attack_or_default(
135 data,
136 self.timer,
137 Some(data.stats.recovery_speed_modifier),
138 );
139 }
140 } else {
141 end_melee_ability(data, &mut update);
143 }
144 },
145 _ => {
146 end_melee_ability(data, &mut update);
148 },
149 }
150
151 update
152 }
153}