From a65d62c86ac48c3f03e6c20fc30120d11e8394bd Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 22 Mar 2019 15:58:24 +1100 Subject: [PATCH] invert --- server/WORKLOG.md | 7 +++ server/src/cryp.rs | 142 ++++++++++++++++++++++++++++++++------------ server/src/game.rs | 12 ++++ server/src/skill.rs | 33 ++++++++++ server/src/spec.rs | 22 +++---- 5 files changed, 167 insertions(+), 49 deletions(-) diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 5e85983e..e7151270 100644 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -34,6 +34,13 @@ change to ownership pattern ## SOON * vbox drops chances * 50% spec, 25% colour etc + +* rework damage and resolutions + deal_damage(colour) + resolutions.push(skill()).flatten() + overkill in logs + immunity resolution type + * confirm cryp without skill ready * iconography * aoe skills diff --git a/server/src/cryp.rs b/server/src/cryp.rs index c9505cce..64d499d5 100644 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -297,6 +297,10 @@ impl Cryp { self.effects.iter().any(|s| s.effect == Effect::Stun) } + pub fn is_inverted(&self) -> bool { + self.effects.iter().any(|s| s.effect == Effect::Invert) + } + pub fn available_skills(&self) -> Vec<&CrypSkill> { self.skills.iter() .filter(|s| s.cd.is_none()) @@ -456,7 +460,7 @@ impl Cryp { let immune = immunity.immune; if immune { - ResolutionResult::Healing { + return ResolutionResult::Healing { amount: 0, overhealing: 0, immunity: immunity.clone(), @@ -472,18 +476,34 @@ impl Cryp { let modified_healing = healing_mods.iter().fold(amount, |acc, m| m.apply(acc)); - let current_hp = self.hp(); - self.hp.increase(modified_healing); - let new_hp = self.hp.value; + match self.is_inverted() { + false => { + let current_hp = self.hp(); + self.hp.increase(modified_healing); + let new_hp = self.hp.value; - let healing = new_hp - current_hp; - let overhealing = modified_healing - healing; + let healing = new_hp - current_hp; + let overhealing = modified_healing - healing; - return ResolutionResult::Healing { - amount: healing, - overhealing, - immunity, - }; + return ResolutionResult::Healing { + amount: healing, + overhealing, + immunity, + }; + }, + true => { + // there is no green shield (yet) + self.hp.reduce(modified_healing); + + return ResolutionResult::Inversion { + damage: modified_healing, + healing: 0, + recharge: 0, + category: Category::GreenDamage, + immunity, + }; + } + } } pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { @@ -508,25 +528,48 @@ impl Cryp { let modified_damage = red_damage_mods.iter().fold(amount, |acc, m| m.apply(acc)); - // calculate amount of damage red_shield will not absorb - // eg 50 red_shield 25 damage -> 0 remainder 25 mitigation - // 50 red_shield 100 damage -> 50 remainder 50 mitigation - // 50 red_shield 5 damage -> 0 remainder 5 mitigation - let remainder = modified_damage.saturating_sub(self.red_shield.value); - let mitigation = modified_damage.saturating_sub(remainder); + match self.is_inverted() { + false => { + // calculate amount of damage red_shield will not absorb + // eg 50 red_shield 25 damage -> 0 remainder 25 mitigation + // 50 red_shield 100 damage -> 50 remainder 50 mitigation + // 50 red_shield 5 damage -> 0 remainder 5 mitigation + let remainder = modified_damage.saturating_sub(self.red_shield.value); + let mitigation = modified_damage.saturating_sub(remainder); - // reduce red_shield by mitigation amount - self.red_shield.reduce(mitigation); + // reduce red_shield by mitigation amount + self.red_shield.reduce(mitigation); - // deal remainder to hp - self.hp.reduce(remainder); + // deal remainder to hp + self.hp.reduce(remainder); - return ResolutionResult::Damage { - amount: remainder, - mitigation, - category: Category::RedDamage, - immunity, - }; + return ResolutionResult::Damage { + amount: remainder, + mitigation, + category: Category::RedDamage, + immunity, + }; + }, + true => { + let current_hp = self.hp(); + self.hp.increase(modified_damage); + let new_hp = self.hp.value; + let healing = new_hp - current_hp; + let overhealing = modified_damage - healing; + + let current_shield = self.red_shield.value; + self.red_shield.increase(overhealing); + let recharge = self.red_shield.value - current_shield; + + return ResolutionResult::Inversion { + damage: 0, + healing, + recharge, + immunity, + category: Category::RedDamage, + }; + } + } } pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { @@ -548,20 +591,43 @@ impl Cryp { .collect::>(); // println!("{:?}", blue_damage_mods); - let modified_damage = blue_damage_mods.iter().fold(amount, |acc, m| m.apply(acc)); - let remainder = modified_damage.saturating_sub(self.blue_shield.value); - let mitigation = modified_damage.saturating_sub(remainder); - self.blue_shield.reduce(mitigation); - self.hp.reduce(remainder); + match self.is_inverted() { + false => { + let remainder = modified_damage.saturating_sub(self.blue_shield.value); + let mitigation = modified_damage.saturating_sub(remainder); - return ResolutionResult::Damage { - amount: remainder, - mitigation, - category: Category::BlueDamage, - immunity, - }; + self.blue_shield.reduce(mitigation); + self.hp.reduce(remainder); + + return ResolutionResult::Damage { + amount: remainder, + mitigation, + category: Category::BlueDamage, + immunity, + }; + }, + true => { + let current_hp = self.hp(); + self.hp.increase(modified_damage); + let new_hp = self.hp.value; + let healing = new_hp - current_hp; + let overhealing = modified_damage - healing; + + let current_shield = self.blue_shield.value; + self.blue_shield.increase(overhealing); + let recharge = self.blue_shield.value - current_shield; + + return ResolutionResult::Inversion { + damage: 0, + healing, + recharge, + immunity, + category: Category::BlueDamage, + }; + } + } } pub fn add_effect(&mut self, skill: Skill, effect: CrypEffect) -> ResolutionResult { diff --git a/server/src/game.rs b/server/src/game.rs index b4fbb175..e0ba89d0 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -382,6 +382,18 @@ impl Game { cast.resolution.speed, source.name, cast.skill, target.name, amount, overhealing)), } }, + ResolutionResult::Inversion { healing, damage, recharge, category: _, immunity } => { + match immunity.immune { + true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", + cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), + false => match *healing > 0 { + true => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:} ({:} recharge)", + cast.resolution.speed, source.name, cast.skill, target.name, healing, recharge)), + false => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:}", + cast.resolution.speed, source.name, cast.skill, target.name, damage)), + } + } + }, ResolutionResult::Effect { effect, duration, immunity } => { match immunity.immune { true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", diff --git a/server/src/skill.rs b/server/src/skill.rs index cce686a3..ef950824 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -63,6 +63,7 @@ pub enum ResolutionResult { Damage { amount: u64, mitigation: u64, category: Category , immunity: Immunity }, Healing { amount: u64, overhealing: u64, immunity: Immunity }, Recharge { red: u64, blue: u64, immunity: Immunity }, + Inversion { healing: u64, damage: u64, recharge: u64, category: Category, immunity: Immunity }, Effect { effect: Effect, duration: u8, immunity: Immunity }, Removal { effect: Effect, immunity: Immunity }, Evasion { skill: Skill, evasion_rating: u64 }, @@ -305,6 +306,7 @@ pub enum Category { BlueBuff, BlueTick, Green, + GreenDamage, GreenBuff, Ko, } @@ -959,6 +961,37 @@ mod tests { }; } + #[test] + fn invert_test() { + let mut x = Cryp::new() + .named(&"muji".to_string()); + + let mut y = Cryp::new() + .named(&"camel".to_string()); + + // give red shield but reduce to 0 + y.red_shield.force(64); + y.red_shield.reduce(64); + x.red_damage.force(256 + 64); + + invert(&mut y.clone(), &mut y, Resolution::new(Skill::Invert)); + assert!(y.is_inverted()); + + // heal should deal green damage + heal(&mut x, &mut y, Resolution::new(Skill::Heal)); + assert!(y.hp() == 768); + + // attack should heal and recharge red shield + let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack)); + assert!(y.hp() == 1024); + + match res.results[0] { + ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _, immunity: _ } => assert_eq!(recharge, 64), + _ => panic!("not inversion"), + }; + } + + #[test] fn triage_test() { let mut x = Cryp::new() diff --git a/server/src/spec.rs b/server/src/spec.rs index ceb0d7a4..b4128eef 100644 --- a/server/src/spec.rs +++ b/server/src/spec.rs @@ -60,7 +60,7 @@ impl Spec { let i_min = 32; let i_max = 64; - + fn apply_bonus(base: u64, colours: Vec, reqs: Vec, bonuses: Vec) -> u64 { base + bonuses.iter().enumerate().fold(0, |acc, (i, b)| { acc + match (colours.iter().all(|colour| colour >= &reqs[i])) { @@ -72,27 +72,27 @@ impl Spec { match *self { Spec::RedDamageI => modified + { - apply_bonus(base.pct(5), vec![team_colours.red], vec![5, 10, 20], + apply_bonus(base.pct(5), vec![team_colours.red], vec![5, 10, 20], vec![base.pct(5), base.pct(10), base.pct(20)]) }, Spec::GreenDamageI => modified + { - apply_bonus(base.pct(5), vec![team_colours.green], vec![5, 10, 20], + apply_bonus(base.pct(5), vec![team_colours.green], vec![5, 10, 20], vec![base.pct(5), base.pct(10), base.pct(20)]) }, Spec::BlueDamageI => modified + { - apply_bonus(base.pct(5), vec![team_colours.blue], vec![5, 10, 20], + apply_bonus(base.pct(5), vec![team_colours.blue], vec![5, 10, 20], vec![base.pct(5), base.pct(10), base.pct(20)]) }, Spec::GRDI => modified + { - apply_bonus(base.pct(5), vec![team_colours.green, team_colours.red], + apply_bonus(base.pct(5), vec![team_colours.green, team_colours.red], vec![2, 5, 10], vec![base.pct(5), base.pct(10), base.pct(20)]) }, Spec::GBDI => modified + { - apply_bonus(base.pct(5), vec![team_colours.green, team_colours.blue], + apply_bonus(base.pct(5), vec![team_colours.green, team_colours.blue], vec![2, 5, 10], vec![base.pct(5), base.pct(10), base.pct(20)]) }, Spec::RBDI => modified + { - apply_bonus(base.pct(5), vec![team_colours.red, team_colours.blue], + apply_bonus(base.pct(5), vec![team_colours.red, team_colours.blue], vec![2, 5, 10], vec![base.pct(5), base.pct(10), base.pct(20)]) }, @@ -109,20 +109,20 @@ impl Spec { Spec::BlueShieldI => modified + { let bonus = 10 * team_colours.blue as u64; apply_bonus(bonus, vec![team_colours.blue], vec![5, 10, 20], vec![bonus, bonus * 2, bonus * 3]) - }, + }, Spec::LRSI => modified + { let bonus = 5 * (team_colours.green + team_colours.red) as u64; - apply_bonus(bonus, vec![team_colours.green, team_colours.red], + apply_bonus(bonus, vec![team_colours.green, team_colours.red], vec![2, 5, 10], vec![bonus, bonus * 2, bonus * 3]) }, Spec::LBSI => modified + { let bonus = 5 * (team_colours.green + team_colours.blue) as u64; - apply_bonus(bonus, vec![team_colours.green, team_colours.blue], + apply_bonus(bonus, vec![team_colours.green, team_colours.blue], vec![2, 5, 10], vec![bonus, bonus * 2, bonus * 3]) }, Spec::RBSI => modified + { let bonus = 5 * (team_colours.red + team_colours.blue) as u64; - apply_bonus(bonus, vec![team_colours.red, team_colours.blue], + apply_bonus(bonus, vec![team_colours.red, team_colours.blue], vec![2, 5, 10], vec![bonus, bonus * 2, bonus * 3]) }, }