veloren_common/states/
regrow_head.rs

1use std::time::Duration;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    comp::{CharacterState, StateUpdate},
7    event::RegrowHeadEvent,
8    states::utils::{end_ability, tick_attack_or_default},
9};
10
11use super::{
12    behavior::CharacterBehavior,
13    utils::{AbilityInfo, StageSection},
14};
15
16#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
17pub enum FrontendSpecifier {
18    Hydra,
19}
20
21#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
22pub struct StaticData {
23    /// How long until state has until the head regrowing
24    pub buildup_duration: Duration,
25    /// How long the state has until exiting
26    pub recover_duration: Duration,
27    /// How much energy this ability costs.
28    pub energy_cost: f32,
29    pub ability_info: AbilityInfo,
30    /// Used to specify the transformation to the frontend
31    pub specifier: Option<FrontendSpecifier>,
32}
33
34#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
35pub struct Data {
36    /// Struct containing data that does not change over the course of the
37    /// character state
38    pub static_data: StaticData,
39    /// Timer for each stage
40    pub timer: Duration,
41    /// What section the character stage is in
42    pub stage_section: StageSection,
43}
44
45impl CharacterBehavior for Data {
46    fn behavior(
47        &self,
48        data: &super::behavior::JoinData,
49        output_events: &mut crate::comp::character_state::OutputEvents,
50    ) -> crate::comp::StateUpdate {
51        let mut update = StateUpdate::from(data);
52        match self.stage_section {
53            StageSection::Buildup => {
54                // Tick the timer as long as buildup hasn't finihsed
55                if self.timer < self.static_data.buildup_duration {
56                    update.character = CharacterState::RegrowHead(Data {
57                        static_data: self.static_data.clone(),
58                        timer: tick_attack_or_default(data, self.timer, None),
59                        ..*self
60                    });
61                // Buildup finished, regrow head
62                } else {
63                    output_events.emit_server(RegrowHeadEvent {
64                        entity: data.entity,
65                    });
66                    update.character = CharacterState::RegrowHead(Data {
67                        static_data: self.static_data.clone(),
68                        timer: Duration::default(),
69                        stage_section: StageSection::Recover,
70                    });
71                }
72            },
73            StageSection::Recover => {
74                // Wait for recovery period to finish
75                if self.timer < self.static_data.recover_duration {
76                    update.character = CharacterState::RegrowHead(Data {
77                        static_data: self.static_data.clone(),
78                        timer: tick_attack_or_default(
79                            data,
80                            self.timer,
81                            Some(data.stats.recovery_speed_modifier),
82                        ),
83                        ..*self
84                    });
85                } else {
86                    // End the ability after recovery is done
87                    end_ability(data, &mut update);
88                }
89            },
90            _ => {
91                // If we somehow ended up in an incorrect character state, end the ability
92                end_ability(data, &mut update);
93            },
94        }
95
96        update
97    }
98}