1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
//! Skills are used to track a meta-progression of a player's abilities.
//!
//! Skills keep track of both the experience points and the level of the skill.
//!
//! Skills are able to be leveled up, and have no level cap but do have a
//! soft cap that makes it harder to level up the higher the skill is (this is
//! automatically handled by the [`game_library::Xp`] component).
use bevy::{
ecs::{component::Component, system::Resource},
reflect::Reflect,
utils::HashMap,
};
use bevy_inspector_egui::inspector_options::{InspectorOptions, ReflectInspectorOptions};
use serde::{Deserialize, Serialize};
use crate::{enums::Skill, Xp};
/// Skills are used to track a meta-progression of a player's abilities.
///
/// Skills are able to be leveled up, and have no level cap but do have a
/// soft cap that makes it harder to level up the higher the skill is.
///
/// Skill levels allocate points to the skill's attributes, which are
/// used when playing the game, making some schools of magic more powerful
/// than others.
///
/// Skills are also used to gate spells, so that a player must have a certain
/// level in a skill before they can unlock a spell. All of that is built on top
/// of this skill system.
#[derive(
Resource,
Component,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
Reflect,
InspectorOptions,
)]
#[reflect(InspectorOptions)]
#[allow(clippy::module_name_repetitions)]
pub struct Skills {
/// Skill tracks for each of the different skills.
pub tracks: HashMap<Skill, Xp>,
}
impl Skills {
/// Get xp for a skill.
#[must_use]
pub fn get_xp(&self, skill: Skill) -> Option<&Xp> {
self.tracks.get(&skill)
}
/// Get the level for a skill.
#[must_use]
pub fn get_level(&self, skill: Skill) -> Option<u32> {
self.get_xp(skill).map(|xp| xp.current_level)
}
/// Get the percentage to the next level for a skill.
#[must_use]
pub fn get_percentage_to_next_level(&self, skill: Skill) -> Option<f32> {
self.get_xp(skill).map(Xp::next_level_progress)
}
/// Add xp to a skill.
pub fn add_xp(&mut self, skill: Skill, xp: u32) {
if let Some(skill_xp) = self.tracks.get_mut(&skill) {
skill_xp.add(xp);
}
}
/// Level-up a skill.
pub fn level_up(&mut self, skill: Skill) {
if let Some(skill_xp) = self.tracks.get_mut(&skill) {
skill_xp.level_up();
}
}
}