Skill groups now only persist earned_exp instead of available_exp, earned_sp, and available_sp.

This commit is contained in:
Sam 2021-10-13 10:44:28 -04:00
parent 0cf0399a47
commit fe45a158ed
11 changed files with 76 additions and 51 deletions

View File

@ -659,7 +659,7 @@ pub enum SkillGroupKind {
impl SkillGroupKind {
/// Gets the cost in experience of earning a skill point
pub fn skill_point_cost(self, level: u16) -> u16 {
pub fn skill_point_cost(self, level: u16) -> u32 {
const EXP_INCREMENT: f32 = 10.0;
const STARTING_EXP: f32 = 70.0;
const EXP_CEILING: f32 = 1000.0;
@ -670,7 +670,7 @@ impl SkillGroupKind {
/ (1.0
+ std::f32::consts::E.powf(-SCALING_FACTOR * level as f32)
* (EXP_CEILING / STARTING_EXP - 1.0)))
.floor()) as u16
.floor()) as u32
}
/// Gets the total amount of skill points that can be spent in a particular
@ -694,7 +694,10 @@ impl SkillGroupKind {
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct SkillGroup {
pub skill_group_kind: SkillGroupKind,
pub exp: u16,
// How much exp has been used for skill points
pub spent_exp: u32,
// How much exp has been earned in total
pub earned_exp: u32,
pub available_sp: u16,
pub earned_sp: u16,
}
@ -703,11 +706,29 @@ impl SkillGroup {
fn new(skill_group_kind: SkillGroupKind) -> SkillGroup {
SkillGroup {
skill_group_kind,
exp: 0,
spent_exp: 0,
earned_exp: 0,
available_sp: 0,
earned_sp: 0,
}
}
/// Returns the available experience that could be used to earn another
/// skill point in a particular skill group.
pub fn available_experience(&self) -> u32 { self.earned_exp - self.spent_exp }
/// Adds a skill point while subtracting the necessary amount of experience
pub fn earn_skill_point(&mut self) -> Result<(), SpRewardError> {
let sp_cost = self.skill_group_kind.skill_point_cost(self.earned_sp);
if self.available_experience() >= sp_cost {
self.spent_exp = self.spent_exp.saturating_add(sp_cost);
self.available_sp = self.available_sp.saturating_add(1);
self.earned_sp = self.earned_sp.saturating_add(1);
Ok(())
} else {
Err(SpRewardError::InsufficientExp)
}
}
}
/// Contains all of a player's skill groups and skills. Provides methods for
@ -882,12 +903,14 @@ impl SkillSet {
}
/// Adds a skill point while subtracting the necessary amount of experience
pub fn earn_skill_point(&mut self, skill_group_kind: SkillGroupKind) {
let sp_cost = self.skill_point_cost(skill_group_kind);
if let Some(mut skill_group) = self.skill_group_mut(skill_group_kind) {
skill_group.exp = skill_group.exp.saturating_sub(sp_cost);
skill_group.available_sp = skill_group.available_sp.saturating_add(1);
skill_group.earned_sp = skill_group.earned_sp.saturating_add(1);
pub fn earn_skill_point(
&mut self,
skill_group_kind: SkillGroupKind,
) -> Result<(), SpRewardError> {
if let Some(skill_group) = self.skill_group_mut(skill_group_kind) {
skill_group.earn_skill_point()
} else {
Err(SpRewardError::UnavailableSkillGroup)
}
}
@ -901,9 +924,9 @@ impl SkillSet {
/// Adds/subtracts experience to the skill group within an entity's skill
/// set
pub fn change_experience(&mut self, skill_group_kind: SkillGroupKind, amount: i32) {
pub fn add_experience(&mut self, skill_group_kind: SkillGroupKind, amount: u32) {
if let Some(mut skill_group) = self.skill_group_mut(skill_group_kind) {
skill_group.exp = (skill_group.exp as i32 + amount) as u16;
skill_group.earned_exp = skill_group.earned_exp.saturating_add(amount);
} else {
warn!("Tried to add experience to a skill group that player does not have");
}
@ -943,8 +966,9 @@ impl SkillSet {
}
/// Gets the available experience for a particular skill group
pub fn experience(&self, skill_group: SkillGroupKind) -> u16 {
self.skill_group(skill_group).map_or(0, |s_g| s_g.exp)
pub fn available_experience(&self, skill_group: SkillGroupKind) -> u32 {
self.skill_group(skill_group)
.map_or(0, |s_g| s_g.available_experience())
}
/// Gets skill point cost to purchase skill of next level
@ -980,7 +1004,7 @@ impl SkillSet {
}
/// Checks how much experience is needed for the next skill point in a tree
pub fn skill_point_cost(&self, skill_group: SkillGroupKind) -> u16 {
pub fn skill_point_cost(&self, skill_group: SkillGroupKind) -> u32 {
if let Some(level) = self.skill_group(skill_group).map(|sg| sg.earned_sp) {
skill_group.skill_point_cost(level)
} else {
@ -1056,6 +1080,11 @@ impl Skill {
}
}
pub enum SpRewardError {
InsufficientExp,
UnavailableSkillGroup,
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -36,7 +36,7 @@ pub enum Outcome {
},
ExpChange {
uid: Uid,
exp: i32,
exp: u32,
xp_pools: HashSet<SkillGroupKind>,
},
SkillPointGain {

View File

@ -16,6 +16,7 @@ use hashbrown::HashSet;
use specs::{
shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, World, Write, WriteStorage,
};
use tracing::warn;
use vek::Vec3;
const ENERGY_REGEN_ACCEL: f32 = 1.0;
@ -132,14 +133,18 @@ impl<'a> System<'a> for Sys {
.skill_groups
.iter()
.filter_map(|s_g| {
(s_g.exp >= skill_set.skill_point_cost(s_g.skill_group_kind))
(s_g.available_experience() >= skill_set.skill_point_cost(s_g.skill_group_kind))
.then(|| s_g.skill_group_kind)
})
.collect::<HashSet<_>>();
if !skills_to_level.is_empty() {
for skill_group in skills_to_level {
skill_set.earn_skill_point(skill_group);
if skill_set.earn_skill_point(skill_group).is_err() {
warn!(
"Attempted to add skill point to group which is inelgible to earn one"
);
}
outcomes.push(Outcome::SkillPointGain {
uid: *uid,
skill_tree: skill_group,

View File

@ -1117,11 +1117,11 @@ fn handle_exp_gain(
add_tool_from_slot(EquipSlot::InactiveOffhand);
let num_pools = xp_pools.len() as f32;
for pool in xp_pools.iter() {
skill_set.change_experience(*pool, (exp_reward / num_pools).ceil() as i32);
skill_set.add_experience(*pool, (exp_reward / num_pools).ceil() as u32);
}
outcomes.push(Outcome::ExpChange {
uid: *uid,
exp: exp_reward as i32,
exp: exp_reward as u32,
xp_pools,
});
}

View File

@ -301,7 +301,7 @@ fn within_mounting_range(player_position: Option<&Pos>, mount_position: Option<&
}
#[derive(Deserialize)]
struct ResourceExperienceManifest(HashMap<String, i32>);
struct ResourceExperienceManifest(HashMap<String, u32>);
impl assets::Asset for ResourceExperienceManifest {
type Loader = assets::RonLoader;
@ -339,7 +339,7 @@ pub fn handle_mine_block(
.0
.get(item.item_definition_id()),
) {
skillset.change_experience(SkillGroupKind::Weapon(tool), *exp_reward);
skillset.add_experience(SkillGroupKind::Weapon(tool), *exp_reward);
state
.ecs()
.write_resource::<Vec<Outcome>>()

View File

@ -0,0 +1 @@
-- Do skill group change of storing (available_exp, available_sp, and earned_sp) to earned_exp

View File

@ -196,9 +196,7 @@ pub fn load_character_data(
Ok(SkillGroup {
entity_id: char_id,
skill_group_kind: row.get(0)?,
exp: row.get(1)?,
available_sp: row.get(2)?,
earned_sp: row.get(3)?,
earned_exp: row.get(1)?,
})
})?
.filter_map(Result::ok)
@ -442,19 +440,15 @@ pub fn create_character(
"
INSERT INTO skill_group (entity_id,
skill_group_kind,
exp,
available_sp,
earned_sp)
VALUES (?1, ?2, ?3, ?4, ?5)",
earned_exp)
VALUES (?1, ?2, ?3)",
)?;
for skill_group in db_skill_groups {
stmt.execute(&[
&character_id as &dyn ToSql,
&skill_group.skill_group_kind,
&skill_group.exp,
&skill_group.available_sp,
&skill_group.earned_sp,
&skill_group.earned_exp,
])?;
}
drop(stmt);
@ -1023,19 +1017,15 @@ pub fn update(
REPLACE
INTO skill_group (entity_id,
skill_group_kind,
exp,
available_sp,
earned_sp)
VALUES (?1, ?2, ?3, ?4, ?5)",
earned_exp)
VALUES (?1, ?2, ?3)",
)?;
for skill_group in db_skill_groups {
stmt.execute(&[
&skill_group.entity_id as &dyn ToSql,
&skill_group.skill_group_kind,
&skill_group.exp,
&skill_group.available_sp,
&skill_group.earned_sp,
&skill_group.earned_exp,
])?;
}

View File

@ -525,12 +525,16 @@ fn convert_skill_groups_from_database(skill_groups: &[SkillGroup]) -> Vec<skills
let mut new_skill_groups = Vec::new();
for skill_group in skill_groups.iter() {
let skill_group_kind = json_models::db_string_to_skill_group(&skill_group.skill_group_kind);
let new_skill_group = skills::SkillGroup {
let mut new_skill_group = skills::SkillGroup {
skill_group_kind,
exp: skill_group.exp as u16,
available_sp: skill_group.available_sp as u16,
earned_sp: skill_group.earned_sp as u16,
earned_exp: skill_group.earned_exp as u32,
spent_exp: 0,
available_sp: 0,
earned_sp: 0,
};
while new_skill_group.earn_skill_point().is_ok() {}
new_skill_groups.push(new_skill_group);
}
new_skill_groups
@ -554,9 +558,7 @@ pub fn convert_skill_groups_to_database(
.map(|sg| SkillGroup {
entity_id,
skill_group_kind: json_models::skill_group_to_db_string(sg.skill_group_kind),
exp: sg.exp as i32,
available_sp: sg.available_sp as i32,
earned_sp: sg.earned_sp as i32,
earned_exp: sg.earned_exp as i32,
})
.collect()
}

View File

@ -29,9 +29,7 @@ pub struct Skill {
pub struct SkillGroup {
pub entity_id: i64,
pub skill_group_kind: String,
pub exp: i32,
pub available_sp: i32,
pub earned_sp: i32,
pub earned_exp: i32,
}
pub struct Pet {

View File

@ -464,7 +464,7 @@ impl<'a> Widget for Diary<'a> {
}
// Exp Bars and Rank Display
let current_exp = self.skill_set.experience(*sel_tab) as f64;
let current_exp = self.skill_set.available_experience(*sel_tab) as f64;
let max_exp = self.skill_set.skill_point_cost(*sel_tab) as f64;
let exp_percentage = current_exp / max_exp;
let rank = self.skill_set.earned_sp(*sel_tab);

View File

@ -435,7 +435,7 @@ pub struct BuffInfo {
pub struct ExpFloater {
pub owner: Uid,
pub exp_change: i32,
pub exp_change: u32,
pub timer: f32,
pub rand_offset: (f32, f32),
pub xp_pools: HashSet<SkillGroupKind>,