veloren_common/comp/skillset/
skills.rs

1use crate::comp::skillset::{
2    SKILL_GROUP_LOOKUP, SKILL_MAX_LEVEL, SKILL_PREREQUISITES, SkillGroupKind, SkillPrerequisite,
3};
4use serde::{Deserialize, Serialize};
5
6/// Represents a skill that a player can unlock, that either grants them some
7/// kind of active ability, or a passive effect etc. Obviously because this is
8/// an enum it doesn't describe what the skill actually -does-, this will be
9/// handled by dedicated ECS systems.
10// NOTE: if skill does use some constant, add it to corresponding
11// SkillTree Modifiers below.
12#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
13pub enum Skill {
14    Sword(SwordSkill),
15    Axe(AxeSkill),
16    Hammer(HammerSkill),
17    Bow(BowSkill),
18    Staff(StaffSkill),
19    Sceptre(SceptreSkill),
20    Climb(ClimbSkill),
21    Swim(SwimSkill),
22    Pick(MiningSkill),
23    UnlockGroup(SkillGroupKind),
24}
25
26#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
27pub enum SwordSkill {
28    CrescentSlash,
29    FellStrike,
30    Skewer,
31    Cascade,
32    CrossCut,
33    Finisher,
34    HeavySweep,
35    HeavyPommelStrike,
36    HeavyFortitude,
37    HeavyPillarThrust,
38    AgileQuickDraw,
39    AgileFeint,
40    AgileDancingEdge,
41    AgileFlurry,
42    DefensiveRiposte,
43    DefensiveDisengage,
44    DefensiveDeflect,
45    DefensiveStalwartSword,
46    CripplingGouge,
47    CripplingHamstring,
48    CripplingBloodyGash,
49    CripplingEviscerate,
50    CleavingWhirlwindSlice,
51    CleavingEarthSplitter,
52    CleavingSkySplitter,
53    CleavingBladeFever,
54}
55
56#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
57pub enum AxeSkill {
58    BrutalSwing,
59    Berserk,
60    RisingTide,
61    SavageSense,
62    AdrenalineRush,
63    Execute,
64    Maelstrom,
65    Rake,
66    Bloodfeast,
67    FierceRaze,
68    Furor,
69    Fracture,
70    Lacerate,
71    Riptide,
72    SkullBash,
73    Sunder,
74    Plunder,
75    Defiance,
76    Keelhaul,
77    Bulkhead,
78    Capsize,
79}
80
81#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
82pub enum HammerSkill {
83    ScornfulSwipe,
84    Tremor,
85    VigorousBash,
86    Retaliate,
87    SpineCracker,
88    Breach,
89    IronTempest,
90    Upheaval,
91    Thunderclap,
92    SeismicShock,
93    HeavyWhorl,
94    Intercept,
95    PileDriver,
96    LungPummel,
97    HelmCrusher,
98    Rampart,
99    Tenacity,
100    Earthshaker,
101    Judgement,
102}
103
104#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
105pub enum BowSkill {
106    // Passives
107    ProjSpeed,
108    // Charged upgrades
109    CDamage,
110    CRegen,
111    CKnockback,
112    CSpeed,
113    CMove,
114    // Repeater upgrades
115    RDamage,
116    RCost,
117    RSpeed,
118    // Shotgun upgrades
119    UnlockShotgun,
120    SDamage,
121    SCost,
122    SArrows,
123    SSpread,
124}
125
126#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
127pub enum StaffSkill {
128    // Basic ranged upgrades
129    BDamage,
130    BRegen,
131    BRadius,
132    // Flamethrower upgrades
133    FDamage,
134    FRange,
135    FDrain,
136    FVelocity,
137    // Shockwave upgrades
138    UnlockShockwave,
139    SDamage,
140    SKnockback,
141    SRange,
142    SCost,
143}
144
145#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
146pub enum SceptreSkill {
147    // Lifesteal beam upgrades
148    LDamage,
149    LRange,
150    LLifesteal,
151    LRegen,
152    // Healing aura upgrades
153    HHeal,
154    HRange,
155    HDuration,
156    HCost,
157    // Warding aura upgrades
158    UnlockAura,
159    AStrength,
160    ADuration,
161    ARange,
162    ACost,
163}
164
165#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
166pub enum ClimbSkill {
167    Cost,
168    Speed,
169}
170
171#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
172pub enum SwimSkill {
173    Speed,
174}
175
176#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
177pub enum MiningSkill {
178    Speed,
179    OreGain,
180    GemGain,
181}
182
183impl Skill {
184    /// Is unable to detect cyclic dependencies, so ensure that there are no
185    /// cycles if you modify the prerequisite map.
186    pub fn prerequisite_skills(&self) -> Option<&SkillPrerequisite> {
187        SKILL_PREREQUISITES.get(self)
188    }
189
190    /// Returns the cost in skill points of unlocking a particular skill
191    pub fn skill_cost(&self, level: u16) -> u16 { level }
192
193    /// Returns the maximum level a skill can reach, returns None if the skill
194    /// doesn't level
195    pub fn max_level(&self) -> u16 { SKILL_MAX_LEVEL.get(self).copied().unwrap_or(1) }
196
197    /// Returns the skill group type for a skill from the static skill group
198    /// definitions.
199    pub fn skill_group_kind(&self) -> Option<SkillGroupKind> {
200        SKILL_GROUP_LOOKUP.get(self).copied()
201    }
202}
203
204/// Tree of modifiers that represent how stats are
205/// changed per each skill level.
206///
207/// It's used as bridge between ECS systems
208/// and voxygen Diary for skill descriptions and helps to sync them.
209///
210/// NOTE: Just adding constant does nothing, you need to use it in both
211/// ECS systems and Diary.
212// TODO: make it lazy_static and move to .ron?
213pub const SKILL_MODIFIERS: SkillTreeModifiers = SkillTreeModifiers::get();
214
215pub struct SkillTreeModifiers {
216    pub bow_tree: BowTreeModifiers,
217    pub staff_tree: StaffTreeModifiers,
218    pub sceptre_tree: SceptreTreeModifiers,
219    pub mining_tree: MiningTreeModifiers,
220    pub general_tree: GeneralTreeModifiers,
221}
222
223impl SkillTreeModifiers {
224    const fn get() -> Self {
225        Self {
226            bow_tree: BowTreeModifiers::get(),
227            staff_tree: StaffTreeModifiers::get(),
228            sceptre_tree: SceptreTreeModifiers::get(),
229            mining_tree: MiningTreeModifiers::get(),
230            general_tree: GeneralTreeModifiers::get(),
231        }
232    }
233}
234
235pub struct BowTreeModifiers {
236    pub universal: BowUniversalModifiers,
237    pub charged: BowChargedModifiers,
238    pub repeater: BowRepeaterModifiers,
239    pub shotgun: BowShotgunModifiers,
240}
241
242pub struct BowUniversalModifiers {
243    // TODO: split per abilities?
244    pub projectile_speed: f32,
245}
246
247pub struct BowChargedModifiers {
248    pub damage_scaling: f32,
249    pub regen_scaling: f32,
250    pub knockback_scaling: f32,
251    pub charge_rate: f32,
252    pub move_speed: f32,
253}
254
255pub struct BowRepeaterModifiers {
256    pub power: f32,
257    pub energy_cost: f32,
258    pub max_speed: f32,
259}
260
261pub struct BowShotgunModifiers {
262    pub power: f32,
263    pub energy_cost: f32,
264    pub num_projectiles: u32,
265    pub spread: f32,
266}
267
268impl BowTreeModifiers {
269    const fn get() -> Self {
270        Self {
271            universal: BowUniversalModifiers {
272                projectile_speed: 1.05,
273            },
274            charged: BowChargedModifiers {
275                damage_scaling: 1.05,
276                regen_scaling: 1.05,
277                knockback_scaling: 1.05,
278                charge_rate: 1.05,
279                move_speed: 1.05,
280            },
281            repeater: BowRepeaterModifiers {
282                power: 1.05,
283                energy_cost: 0.95,
284                max_speed: 1.1,
285            },
286            shotgun: BowShotgunModifiers {
287                power: 1.05,
288                energy_cost: 0.95,
289                num_projectiles: 1,
290                spread: 0.95,
291            },
292        }
293    }
294}
295
296pub struct StaffTreeModifiers {
297    pub fireball: StaffFireballModifiers,
298    pub flamethrower: StaffFlamethrowerModifiers,
299    pub shockwave: StaffShockwaveModifiers,
300}
301
302pub struct StaffFireballModifiers {
303    pub power: f32,
304    pub regen: f32,
305    pub range: f32,
306}
307
308pub struct StaffFlamethrowerModifiers {
309    pub damage: f32,
310    pub range: f32,
311    pub energy_drain: f32,
312    pub velocity: f32,
313}
314
315pub struct StaffShockwaveModifiers {
316    pub damage: f32,
317    pub knockback: f32,
318    pub duration: f32,
319    pub energy_cost: f32,
320}
321
322impl StaffTreeModifiers {
323    const fn get() -> Self {
324        Self {
325            fireball: StaffFireballModifiers {
326                power: 1.05,
327                regen: 1.05,
328                range: 1.05,
329            },
330            flamethrower: StaffFlamethrowerModifiers {
331                damage: 1.1,
332                range: 1.05,
333                energy_drain: 0.95,
334                velocity: 1.05,
335            },
336            shockwave: StaffShockwaveModifiers {
337                damage: 1.1,
338                knockback: 1.05,
339                duration: 1.05,
340                energy_cost: 0.95,
341            },
342        }
343    }
344}
345
346pub struct SceptreTreeModifiers {
347    pub beam: SceptreBeamModifiers,
348    pub healing_aura: SceptreHealingAuraModifiers,
349    pub warding_aura: SceptreWardingAuraModifiers,
350}
351
352pub struct SceptreBeamModifiers {
353    pub damage: f32,
354    pub range: f32,
355    pub energy_regen: f32,
356    pub lifesteal: f32,
357}
358
359pub struct SceptreHealingAuraModifiers {
360    pub strength: f32,
361    pub duration: f32,
362    pub range: f32,
363    pub energy_cost: f32,
364}
365
366pub struct SceptreWardingAuraModifiers {
367    pub strength: f32,
368    pub duration: f32,
369    pub range: f32,
370    pub energy_cost: f32,
371}
372
373impl SceptreTreeModifiers {
374    const fn get() -> Self {
375        Self {
376            beam: SceptreBeamModifiers {
377                damage: 1.05,
378                range: 1.05,
379                energy_regen: 1.05,
380                lifesteal: 1.05,
381            },
382            healing_aura: SceptreHealingAuraModifiers {
383                strength: 1.05,
384                duration: 1.05,
385                range: 1.05,
386                energy_cost: 0.95,
387            },
388            warding_aura: SceptreWardingAuraModifiers {
389                strength: 1.05,
390                duration: 1.05,
391                range: 1.05,
392                energy_cost: 0.95,
393            },
394        }
395    }
396}
397
398pub struct MiningTreeModifiers {
399    pub speed: f32,
400    pub gem_gain: f32,
401    pub ore_gain: f32,
402}
403
404impl MiningTreeModifiers {
405    const fn get() -> Self {
406        Self {
407            speed: 1.1,
408            gem_gain: 0.1,
409            ore_gain: 0.1,
410        }
411    }
412}
413
414pub struct GeneralTreeModifiers {
415    pub swim: SwimTreeModifiers,
416    pub climb: ClimbTreeModifiers,
417}
418
419pub struct SwimTreeModifiers {
420    pub speed: f32,
421}
422
423pub struct ClimbTreeModifiers {
424    pub energy_cost: f32,
425    pub speed: f32,
426}
427
428impl GeneralTreeModifiers {
429    const fn get() -> Self {
430        Self {
431            swim: SwimTreeModifiers { speed: 1.25 },
432            climb: ClimbTreeModifiers {
433                energy_cost: 0.8,
434                speed: 1.2,
435            },
436        }
437    }
438}