veloren_common/states/
stunned.rs

1use super::utils::*;
2use crate::{
3    comp::{CharacterState, PoiseState, StateUpdate, character_state::OutputEvents},
4    states::behavior::{CharacterBehavior, JoinData},
5};
6use serde::{Deserialize, Serialize};
7use std::time::Duration;
8
9/// Separated out to condense update portions of character state
10#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
11pub struct StaticData {
12    /// How long until state begins to exit
13    pub buildup_duration: Duration,
14    /// How long the state has until exiting
15    pub recover_duration: Duration,
16    /// Fraction of normal movement speed allowed during the state
17    pub movement_speed: f32,
18    pub ori_rate: f32,
19    pub poise_state: PoiseState,
20}
21
22#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
23pub struct Data {
24    /// Struct containing data that does not change over the course of the
25    /// character state
26    pub static_data: StaticData,
27    /// Timer for each stage
28    pub timer: Duration,
29    /// What section the character stage is in
30    pub stage_section: StageSection,
31    /// Whether the character was wielding or not
32    pub was_wielded: bool,
33}
34
35impl CharacterBehavior for Data {
36    fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
37        let mut update = StateUpdate::from(data);
38
39        if matches!(
40            self.static_data.poise_state,
41            PoiseState::Dazed | PoiseState::KnockedDown
42        ) {
43            leave_stance(data, output_events);
44        }
45
46        handle_orientation(data, &mut update, self.static_data.ori_rate, None);
47        handle_move(data, &mut update, self.static_data.movement_speed);
48
49        match self.stage_section {
50            StageSection::Buildup => {
51                if self.timer < self.static_data.buildup_duration {
52                    // Build up
53                    update.character = CharacterState::Stunned(Data {
54                        timer: tick_attack_or_default(data, self.timer, None),
55                        ..*self
56                    });
57                } else {
58                    // Transitions to recovery section of stage
59                    update.character = CharacterState::Stunned(Data {
60                        timer: Duration::default(),
61                        stage_section: StageSection::Recover,
62                        ..*self
63                    });
64                }
65            },
66            StageSection::Recover => {
67                if self.timer < self.static_data.recover_duration {
68                    // Recovery
69                    update.character = CharacterState::Stunned(Data {
70                        timer: tick_attack_or_default(
71                            data,
72                            self.timer,
73                            Some(data.stats.recovery_speed_modifier),
74                        ),
75                        ..*self
76                    });
77                } else {
78                    // Done
79                    end_ability(data, &mut update);
80                }
81            },
82            _ => {
83                // If it somehow ends up in an incorrect stage section
84                end_ability(data, &mut update);
85            },
86        }
87
88        update
89    }
90}