1use crate::{
2 combat::GroupTarget,
3 comp::{
4 CharacterState, StateUpdate,
5 aura::{AuraBuffConstructor, AuraTarget, Auras},
6 character_state::OutputEvents,
7 },
8 event::CreateAuraEntityEvent,
9 resources::Secs,
10 states::{
11 behavior::{CharacterBehavior, JoinData},
12 sprite_summon::create_sprites,
13 utils::*,
14 },
15 terrain::SpriteKind,
16};
17use serde::{Deserialize, Serialize};
18use std::time::Duration;
19
20#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
22pub struct StaticData {
23 pub buildup_duration: Duration,
25 pub cast_duration: Duration,
27 pub recover_duration: Duration,
29 pub targets: GroupTarget,
31 pub auras: Vec<AuraBuffConstructor>,
33 pub aura_duration: Option<Secs>,
35 pub range: f32,
37 pub sprite_info: Option<SpriteInfo>,
39 pub ability_info: AbilityInfo,
41}
42
43#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
44pub struct Data {
45 pub static_data: StaticData,
48 pub timer: Duration,
50 pub stage_section: StageSection,
52 pub achieved_radius: Option<i32>,
54}
55
56impl CharacterBehavior for Data {
57 fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
58 let mut update = StateUpdate::from(data);
59
60 match self.stage_section {
61 StageSection::Buildup => {
62 if self.timer < self.static_data.buildup_duration {
63 update.character = CharacterState::StaticAura(Data {
65 static_data: self.static_data.clone(),
66 timer: tick_attack_or_default(data, self.timer, None),
67 ..*self
68 });
69 } else {
70 update.character = CharacterState::StaticAura(Data {
72 static_data: self.static_data.clone(),
73 timer: Duration::default(),
74 stage_section: StageSection::Action,
75 achieved_radius: self.achieved_radius,
76 });
77 }
78 },
79 StageSection::Action => {
80 if self.timer < self.static_data.cast_duration {
81 let achieved_radius = if let Some(sprite_info) = self.static_data.sprite_info {
83 let timer_frac =
84 self.timer.as_secs_f32() / self.static_data.cast_duration.as_secs_f32();
85
86 let achieved_radius = create_sprites(
87 data,
88 output_events,
89 sprite_info.sprite,
90 timer_frac,
91 sprite_info.summon_distance,
92 self.achieved_radius.unwrap_or(0),
93 360.0,
94 sprite_info.sparseness,
95 data.pos.0,
96 false,
97 sprite_info.del_timeout,
98 );
99 Some(achieved_radius)
100 } else {
101 None
102 };
103 update.character = CharacterState::StaticAura(Data {
105 static_data: self.static_data.clone(),
106 timer: tick_attack_or_default(data, self.timer, None),
107 achieved_radius,
108 ..*self
109 });
110 } else {
111 let targets =
113 AuraTarget::from((Some(self.static_data.targets), Some(data.uid)));
114 let mut auras = Vec::new();
115 for aura_data in &self.static_data.auras {
116 let aura = aura_data.to_aura(
117 (data.uid, self.static_data.ability_info.tool),
118 self.static_data.range,
119 self.static_data.aura_duration,
120 targets,
121 *data.time,
122 None,
123 );
124 auras.push(aura);
125 }
126 output_events.emit_server(CreateAuraEntityEvent {
127 auras: Auras::new(auras),
128 pos: *data.pos,
129 creator_uid: *data.uid,
130 duration: self.static_data.aura_duration,
131 });
132 update.character = CharacterState::StaticAura(Data {
133 static_data: self.static_data.clone(),
134 timer: Duration::default(),
135 stage_section: StageSection::Recover,
136 achieved_radius: self.achieved_radius,
137 });
138 }
139 },
140 StageSection::Recover => {
141 if self.timer < self.static_data.recover_duration {
142 update.character = CharacterState::StaticAura(Data {
143 static_data: self.static_data.clone(),
144 timer: tick_attack_or_default(
145 data,
146 self.timer,
147 Some(data.stats.recovery_speed_modifier),
148 ),
149 ..*self
150 });
151 } else {
152 end_ability(data, &mut update);
154 }
155 },
156 _ => {
157 end_ability(data, &mut update);
159 },
160 }
161
162 handle_interrupts(data, &mut update, output_events);
164
165 update
166 }
167}
168
169#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
170pub struct SpriteInfo {
171 pub sprite: SpriteKind,
172 pub del_timeout: Option<(f32, f32)>,
173 pub summon_distance: (f32, f32),
174 pub sparseness: f64,
175}