1use crate::{
2 combat::GroupTarget,
3 comp::{
4 buff::{BuffCategory, BuffData, BuffKind, BuffSource},
5 tool::ToolKind,
6 },
7 resources::{Secs, Time},
8 uid::Uid,
9};
10use serde::{Deserialize, Serialize};
11use slotmap::{SlotMap, new_key_type};
12use specs::{Component, DerefFlaggedStorage, VecStorage};
13use std::collections::{HashMap, HashSet};
14
15new_key_type! { pub struct AuraKey; }
16
17#[derive(Clone, Debug, Serialize, Deserialize)]
20pub enum AuraKind {
21 Buff {
23 kind: BuffKind,
24 data: BuffData,
25 category: BuffCategory,
26 source: BuffSource,
27 },
28 FriendlyFire,
31 ForcePvP,
35 }
40
41#[derive(Clone, Copy, Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
43pub enum AuraKindVariant {
44 Buff,
45 FriendlyFire,
46 ForcePvP,
47}
48
49#[derive(Clone, Debug, Serialize, Deserialize)]
53pub struct Aura {
54 pub aura_kind: AuraKind,
56 pub radius: f32,
58 pub end_time: Option<Time>,
60 pub target: AuraTarget,
66 pub data: AuraData,
69}
70
71#[derive(Clone, Debug)]
74pub enum AuraChange {
75 Add(Aura),
77 RemoveByKey(Vec<AuraKey>),
79 EnterAura(Uid, AuraKey, AuraKindVariant),
80 ExitAura(Uid, AuraKey, AuraKindVariant),
81}
82
83#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
85pub enum AuraTarget {
86 GroupOf(Uid),
89 NotGroupOf(Uid),
93 All,
95}
96
97#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
98pub enum Specifier {
99 WardingAura,
100 HealingAura,
101 Frozen,
102 FieryAura,
103}
104
105impl From<(Option<GroupTarget>, Option<&Uid>)> for AuraTarget {
106 fn from((target, uid): (Option<GroupTarget>, Option<&Uid>)) -> Self {
107 match (target, uid) {
108 (Some(GroupTarget::InGroup), Some(uid)) => Self::GroupOf(*uid),
109 (Some(GroupTarget::OutOfGroup), Some(uid)) => Self::NotGroupOf(*uid),
110 (Some(GroupTarget::All), _) => Self::All,
111 _ => Self::All,
112 }
113 }
114}
115
116impl AsRef<AuraKindVariant> for AuraKind {
117 fn as_ref(&self) -> &AuraKindVariant {
118 match self {
119 AuraKind::Buff { .. } => &AuraKindVariant::Buff,
120 AuraKind::FriendlyFire => &AuraKindVariant::FriendlyFire,
121 AuraKind::ForcePvP => &AuraKindVariant::ForcePvP,
122 }
123 }
124}
125
126#[derive(Clone, Debug, Serialize, Deserialize)]
127pub struct AuraData {
128 pub duration: Option<Secs>,
129}
130
131impl AuraData {
132 #[must_use]
133 fn new(duration: Option<Secs>) -> Self { Self { duration } }
134}
135
136impl Aura {
137 pub fn new(
139 aura_kind: AuraKind,
140 radius: f32,
141 duration: Option<Secs>,
142 target: AuraTarget,
143 time: Time,
144 ) -> Self {
145 Self {
146 aura_kind,
147 radius,
148 end_time: duration.map(|dur| Time(time.0 + dur.0)),
149 target,
150 data: AuraData::new(duration),
151 }
152 }
153}
154
155#[derive(Clone, Debug, Serialize, Deserialize, Default)]
157pub struct Auras {
158 pub auras: SlotMap<AuraKey, Aura>,
159}
160
161impl Auras {
162 pub fn new(auras: Vec<Aura>) -> Self {
163 let mut auras_comp: SlotMap<AuraKey, Aura> = SlotMap::with_key();
164 for aura in auras {
165 auras_comp.insert(aura);
166 }
167 Self { auras: auras_comp }
168 }
169
170 pub fn insert(&mut self, aura: Aura) { self.auras.insert(aura); }
171
172 pub fn remove(&mut self, key: AuraKey) { self.auras.remove(key); }
173}
174
175#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
176#[serde(deny_unknown_fields)]
177pub struct AuraBuffConstructor {
178 pub kind: BuffKind,
179 pub strength: f32,
180 pub duration: Option<Secs>,
181 pub category: BuffCategory,
182}
183
184impl AuraBuffConstructor {
185 pub fn to_aura(
186 &self,
187 entity_info: (&Uid, Option<ToolKind>),
188 radius: f32,
189 duration: Option<Secs>,
190 target: AuraTarget,
191 time: Time,
192 ) -> Aura {
193 let aura_kind = AuraKind::Buff {
194 kind: self.kind,
195 data: BuffData::new(self.strength, self.duration),
196 category: self.category.clone(),
197 source: BuffSource::Character {
198 by: *entity_info.0,
199 tool_kind: entity_info.1,
200 },
201 };
202 Aura::new(aura_kind, radius, duration, target, time)
203 }
204}
205
206#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
208pub struct EnteredAuras {
209 pub auras: HashMap<AuraKindVariant, HashSet<(Uid, AuraKey)>>,
212}
213
214impl EnteredAuras {
215 pub fn flatten(&self) -> impl Iterator<Item = (Uid, AuraKey)> + '_ {
216 self.auras.values().flat_map(|i| i.iter().copied())
217 }
218}
219
220impl Component for Auras {
221 type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
222}
223
224impl Component for EnteredAuras {
225 type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
226}