veloren_common/states/
blink.rs

1use crate::{
2    comp::{CharacterState, StateUpdate, character_state::OutputEvents},
3    event::TeleportToEvent,
4    states::{
5        behavior::{CharacterBehavior, JoinData},
6        utils::*,
7    },
8};
9use serde::{Deserialize, Serialize};
10use std::time::Duration;
11
12/// Separated out to condense update portions of character state
13#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
14pub struct StaticData {
15    /// How long the state builds up for
16    pub buildup_duration: Duration,
17    /// How long the state recovers for
18    pub recover_duration: Duration,
19    /// What the max range of the teleport is
20    pub max_range: f32,
21    /// Miscellaneous information about the ability
22    pub ability_info: AbilityInfo,
23    /// Used to indicate to the frontend what ability this is for any special
24    /// effects
25    pub frontend_specifier: Option<FrontendSpecifier>,
26}
27
28#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
29pub struct Data {
30    /// Struct containing data that does not change over the course of the
31    /// character state
32    pub static_data: StaticData,
33    /// Timer for each stage
34    pub timer: Duration,
35    /// What section the character stage is in
36    pub stage_section: StageSection,
37}
38
39impl CharacterBehavior for Data {
40    fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
41        let mut update = StateUpdate::from(data);
42
43        handle_orientation(data, &mut update, 1.0, None);
44
45        match self.stage_section {
46            StageSection::Buildup => {
47                if self.timer < self.static_data.buildup_duration {
48                    // Build up
49                    update.character = CharacterState::Blink(Data {
50                        timer: tick_attack_or_default(data, self.timer, None),
51                        ..*self
52                    });
53                } else {
54                    // Blinks to target location, defaults to 25 meters in front if no target
55                    // provided
56                    if let Some(input_attr) = self.static_data.ability_info.input_attr {
57                        if let Some(target) = input_attr.target_entity {
58                            output_events.emit_server(TeleportToEvent {
59                                entity: data.entity,
60                                target,
61                                max_range: Some(self.static_data.max_range),
62                            });
63                        } else if let Some(pos) = input_attr.select_pos {
64                            update.pos.0 = pos;
65                        } else {
66                            update.pos.0 += *data.inputs.look_dir * 25.0;
67                        }
68                    }
69                    // Transitions to recover section of stage
70                    update.character = CharacterState::Blink(Data {
71                        timer: Duration::default(),
72                        stage_section: StageSection::Recover,
73                        ..*self
74                    });
75                }
76            },
77            StageSection::Recover => {
78                if self.timer < self.static_data.recover_duration {
79                    // Recovery
80                    update.character = CharacterState::Blink(Data {
81                        timer: tick_attack_or_default(
82                            data,
83                            self.timer,
84                            Some(data.stats.recovery_speed_modifier),
85                        ),
86                        ..*self
87                    });
88                } else {
89                    // Done
90                    end_ability(data, &mut update);
91                }
92            },
93            _ => {
94                // If it somehow ends up in an incorrect stage section
95                end_ability(data, &mut update);
96            },
97        }
98
99        update
100    }
101}
102
103#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
104pub enum FrontendSpecifier {
105    CultistFlame,
106    FlameThrower,
107}