diff --git a/server/src/cryp.rs b/server/src/cryp.rs index 42a45a5f..86b0521a 100644 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -42,6 +42,7 @@ pub enum Stat { Agi, Int, Hp, + Speed, Stamina, PhysicalDamage, PhysicalDamageTaken, @@ -91,6 +92,7 @@ pub struct Cryp { pub phys_dmg: CrypStat, pub spell_dmg: CrypStat, pub stamina: CrypStat, + pub speed: CrypStat, pub hp: CrypStat, pub xp: u64, pub lvl: u8, @@ -113,6 +115,7 @@ impl Cryp { account: id, phys_dmg: CrypStat { base: 0, stat: Stat::PhysicalDamage }, spell_dmg: CrypStat { base: 0, stat: Stat::SpellDamage }, + speed: CrypStat { base: 0, stat: Stat::SpellDamage }, stamina: CrypStat { base: 0, stat: Stat::Stamina }, hp: CrypStat { base: 0, stat: Stat::Hp }, lvl: 0, @@ -193,6 +196,7 @@ impl Cryp { match stat { Stat::PhysicalDamage => self.phys_dmg.set(rng.gen_range(other_min, other_max)), Stat::SpellDamage => self.spell_dmg.set(rng.gen_range(other_min, other_max)), + Stat::Speed => self.speed.set(rng.gen_range(other_min, other_max)), Stat::Stamina => { self.stamina.set(rng.gen_range(stam_min, stam_max)); self.hp.set(self.stamina.base) @@ -213,6 +217,7 @@ impl Cryp { self.roll_stat(Stat::PhysicalDamage); self.roll_stat(Stat::SpellDamage); + self.roll_stat(Stat::Speed); self.roll_stat(Stat::Stamina); self @@ -366,6 +371,16 @@ impl Cryp { return modified_spell_dmg; } + pub fn speed(&self) -> u64 { + let speed_mods = self.effects.iter() + .filter(|e| e.effect.modifications().contains(&Stat::Speed)) + .map(|cryp_effect| cryp_effect.effect) + .collect::>(); + + let modified_speed = speed_mods.iter().fold(self.speed.base, |acc, m| m.apply(acc)); + return modified_speed; + } + pub fn hp(&self) -> u64 { self.hp.base } diff --git a/server/src/game.rs b/server/src/game.rs index 13f7da41..3f24382b 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -377,6 +377,19 @@ impl Game { self } + fn stack_sort_speed(&mut self) -> &mut Game { + let mut sorted = self.stack.clone(); + sorted.sort_unstable_by_key(|s| -> u64 { + let caster = self.cryp_by_id(s.source_cryp_id).unwrap(); + caster.speed().saturating_mul(s.skill.speed() as u64) + }); + + self.stack = sorted; + self.stack.reverse(); + + self + } + fn resolve_skills(&mut self) -> &mut Game { if self.phase != Phase::Resolve { panic!("game not in Resolve phase"); @@ -395,8 +408,7 @@ impl Game { // add them to the stack self.stack.append(&mut ticks); - self.stack.sort_unstable_by_key(|s| s.skill.speed()); - self.stack.reverse(); + self.stack_sort_speed(); // update the stack with the resolved skills self.stack = self.stack.clone().iter_mut().map(|skill| { @@ -425,6 +437,11 @@ impl Game { self.update_cryp(&mut source); self.update_cryp(&mut target); + // find a way to + // resort the stack after each cast because + // the cryp speed may have changed + // self.stack_sort_speed(); + return skill.clone(); }).collect::>(); @@ -961,6 +978,7 @@ mod tests { let y_cryp = y_team.cryps[0].clone(); game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().phys_dmg.set(u64::max_value()); + game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().speed.set(u64::max_value()); let _x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestStun).unwrap(); game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();