From 34d91391402a6a0c7c0364220844853bd0272d2e Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 16:41:36 +1100 Subject: [PATCH 1/8] simplify immunities --- server/WORKLOG.md | 1 - server/src/cryp.rs | 72 ++++++++++++-------------------------- server/src/game.rs | 85 +++++++++++++++++---------------------------- server/src/skill.rs | 61 ++++++++++++++++---------------- 4 files changed, 84 insertions(+), 135 deletions(-) diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 62a08067..5a8cdbef 100644 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -24,7 +24,6 @@ ensure all skills impl Skill::Ruin -> aoe stun on attack - Skill::Reflect -> reflect incoming attacks back to opponent Skill::Taunt -> redirect incomnig attacks to self Skill::Toxic -> apply debuff to attackers diff --git a/server/src/cryp.rs b/server/src/cryp.rs index aed04d03..b206fa17 100644 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -258,9 +258,9 @@ impl Cryp { self.hp.value == 0 } - pub fn immune(&self, skill: Skill) -> Immunity { + pub fn immune(&self, skill: Skill) -> Option { if self.is_ko() { - return Immunity { immune: true, effects: vec![Effect::Ko]}; + return Some(Immunity { immune: true, effects: vec![Effect::Ko]}); } let immunities = self.effects.iter() @@ -269,10 +269,10 @@ impl Cryp { .collect::>(); if immunities.len() > 0 { - return Immunity { immune: true, effects: immunities}; + return Some(Immunity { immune: true, effects: immunities}); } - return Immunity { immune: false, effects: vec![]}; + None } pub fn disabled(&self, skill: Skill) -> Disable { @@ -450,14 +450,9 @@ impl Cryp { } pub fn recharge(&mut self) -> ResolutionResult { - let immunity = self.immune(Skill::Recharge); - let immune = immunity.immune; - - if immune { - ResolutionResult::Recharge { - red: 0, - blue: 0, - immunity: immunity.clone(), + if let Some(immunity) = self.immune(Skill::Recharge) { + return ResolutionResult::Immunity { + immunity, }; } @@ -467,18 +462,13 @@ impl Cryp { let blue = self.blue_shield.max.saturating_sub(self.blue_shield.value); self.blue_shield.value = self.blue_shield.max; - ResolutionResult::Recharge { red, blue, immunity } + ResolutionResult::Recharge { red, blue } } pub fn deal_green_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { - let immunity = self.immune(skill); - let immune = immunity.immune; - - if immune { - return ResolutionResult::Healing { - amount: 0, - overhealing: 0, - immunity: immunity.clone(), + if let Some(immunity) = self.immune(skill) { + return ResolutionResult::Immunity { + immunity, }; } @@ -503,7 +493,6 @@ impl Cryp { return ResolutionResult::Healing { amount: healing, overhealing, - immunity, }; }, true => { @@ -517,21 +506,14 @@ impl Cryp { healing: 0, recharge: 0, category: Category::GreenDamage, - immunity, }; } } } pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { - let immunity = self.immune(skill); - let immune = immunity.immune; - - if immune { - return ResolutionResult::Damage { - amount: 0, - mitigation: 0, - category: Category::RedDamage, + if let Some(immunity) = self.immune(skill) { + return ResolutionResult::Immunity { immunity, }; } @@ -566,7 +548,6 @@ impl Cryp { amount: delta, mitigation, category: Category::RedDamage, - immunity, }; }, true => { @@ -584,7 +565,6 @@ impl Cryp { damage: 0, healing, recharge, - immunity, category: Category::RedDamage, }; } @@ -592,14 +572,8 @@ impl Cryp { } pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { - let immunity = self.immune(skill); - let immune = immunity.immune; - - if immune { - return ResolutionResult::Damage { - amount: 0, - mitigation: 0, - category: Category::BlueDamage, + if let Some(immunity) = self.immune(skill) { + return ResolutionResult::Immunity { immunity, }; } @@ -627,7 +601,6 @@ impl Cryp { amount: delta, mitigation, category: Category::BlueDamage, - immunity, }; }, true => { @@ -645,7 +618,6 @@ impl Cryp { damage: 0, healing, recharge, - immunity, category: Category::BlueDamage, }; } @@ -653,20 +625,20 @@ impl Cryp { } pub fn add_effect(&mut self, skill: Skill, effect: CrypEffect) -> ResolutionResult { - let immunity = self.immune(skill); - let immune = immunity.immune; + if let Some(immunity) = self.immune(skill) { + return ResolutionResult::Immunity { + immunity, + }; + } // todo modified durations cause of buffs let result = ResolutionResult::Effect { effect: effect.effect, duration: effect.effect.duration(), - immunity, }; - if !immune { - // println!("{:?} {:?} adding effect", self.name, effect.effect); - self.effects.push(effect); - } + // println!("{:?} {:?} adding effect", self.name, effect.effect); + self.effects.push(effect); return result; } diff --git a/server/src/game.rs b/server/src/game.rs index e0ba89d0..77da22ac 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -366,62 +366,41 @@ impl Game { for result in cast.resolution.results.iter() { match result { - ResolutionResult::Damage { amount, mitigation, category: _, immunity } => { - match immunity.immune { - true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", - cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), - false => self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)", - cast.resolution.speed, source.name, cast.skill, target.name, amount, mitigation)), + ResolutionResult::Immunity { immunity } => + self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", + cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), + + ResolutionResult::Damage { amount, mitigation, category: _ } => + self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)", + cast.resolution.speed, source.name, cast.skill, target.name, amount, mitigation)), + + ResolutionResult::Healing { amount, overhealing } => + self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:}OH)", + cast.resolution.speed, source.name, cast.skill, target.name, amount, overhealing)), + + ResolutionResult::Inversion { healing, damage, recharge, category: _ } => { + 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::Healing { amount, overhealing, immunity } => { - match immunity.immune { - true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", - cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), - false => self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:}OH)", - 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 {:?}", - cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), - false => self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T", - cast.resolution.speed, source.name, cast.skill, target.name, effect, duration)), - } - }, - ResolutionResult::Removal { effect, immunity } => { - match immunity.immune { - true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", - cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), - false => self.log.push(format!("[{:}] {:?} removed {:} {:?}", - cast.resolution.speed, source.name, target.name, effect)), - } - }, - ResolutionResult::Recharge { red, blue, immunity } => { - match immunity.immune { - true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", - cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), - false => self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B", - cast.resolution.speed, source.name, cast.skill, target.name, red, blue)), - } - }, - ResolutionResult::Evasion { skill: _, evasion_rating } => { + ResolutionResult::Effect { effect, duration } => + self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T", + cast.resolution.speed, source.name, cast.skill, target.name, effect, duration)), + + ResolutionResult::Removal { effect } => + self.log.push(format!("[{:}] {:?} removed {:} {:?}", + cast.resolution.speed, source.name, target.name, effect)), + + ResolutionResult::Recharge { red, blue } => + self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B", + cast.resolution.speed, source.name, cast.skill, target.name, red, blue)), + + ResolutionResult::Evasion { skill: _, evasion_rating } => self.log.push(format!("[{:}] {:} {:?} {:} evaded ({:}%)", - cast.resolution.speed, source.name, cast.skill, target.name, evasion_rating)); - }, + cast.resolution.speed, source.name, cast.skill, target.name, evasion_rating)), } } diff --git a/server/src/skill.rs b/server/src/skill.rs index f085a732..b004fb6c 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -60,12 +60,13 @@ impl Disable { #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] 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 }, + Immunity { immunity: Immunity }, + Damage { amount: u64, mitigation: u64, category: Category }, + Healing { amount: u64, overhealing: u64 }, + Recharge { red: u64, blue: u64 }, + Inversion { healing: u64, damage: u64, recharge: u64, category: Category }, + Effect { effect: Effect, duration: u8 }, + Removal { effect: Effect }, Evasion { skill: Skill, evasion_rating: u64 }, } @@ -909,10 +910,8 @@ fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) - resolution.results.push(siphon_damage.clone()); match siphon_damage { - ResolutionResult::Damage { amount, mitigation: _, category: _, immunity } => { - if !immunity.immune { - resolution.results.push(cryp.deal_green_damage(Skill::Heal, amount)); - } + ResolutionResult::Damage { amount, mitigation: _, category: _, } => { + resolution.results.push(cryp.deal_green_damage(Skill::Heal, amount)); }, _ => panic!("siphon tick damage not dealt {:?}", siphon_damage), } @@ -933,15 +932,15 @@ fn silence(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> R } fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { - let immunity = target.immune(Skill::Purge); - let immune = immunity.immune; + if let Some(immunity) = target.immune(Skill::Purge) { + resolution.results.push(ResolutionResult::Immunity { immunity }); + return resolution; + } - if !immune { - for (i, ce) in target.effects.clone().iter_mut().enumerate() { - if ce.effect.category() == Category::BlueBuff { - target.effects.remove(i); - resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() }); - } + for (i, ce) in target.effects.clone().iter_mut().enumerate() { + if ce.effect.category() == Category::BlueBuff { + target.effects.remove(i); + resolution.results.push(ResolutionResult::Removal { effect: ce.effect }); } } @@ -949,15 +948,15 @@ fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Res } fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { - let immunity = target.immune(Skill::Purify); - let immune = immunity.immune; + if let Some(immunity) = target.immune(Skill::Purify) { + resolution.results.push(ResolutionResult::Immunity { immunity }); + return resolution; + } - if !immune { - for (i, ce) in target.effects.clone().iter_mut().enumerate() { - if ce.effect.category() == Category::BlueDebuff { - target.effects.remove(i); - resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() }); - } + for (i, ce) in target.effects.clone().iter_mut().enumerate() { + if ce.effect.category() == Category::BlueDebuff { + target.effects.remove(i); + resolution.results.push(ResolutionResult::Removal { effect: ce.effect }); } } @@ -1032,7 +1031,7 @@ mod tests { let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack)); match res.results[0] { - ResolutionResult::Damage { amount, mitigation: _, category: _, immunity: _ } => assert_eq!(amount, 50), + ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 50), _ => panic!("not damage"), }; } @@ -1054,7 +1053,7 @@ mod tests { assert!(y.hp() == 1); match res.results[0] { - ResolutionResult::Damage { amount, mitigation: _, category: _, immunity: _ } => assert_eq!(amount, 1023), + ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 1023), _ => panic!("not damage"), }; } @@ -1084,7 +1083,7 @@ mod tests { assert!(y.hp() == 1024); match res.results[0] { - ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _, immunity: _ } => assert_eq!(recharge, 64), + ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _ } => assert_eq!(recharge, 64), _ => panic!("not inversion"), }; } @@ -1107,7 +1106,7 @@ mod tests { assert!(x.hp() == 768); match cast.resolution.results[0] { - ResolutionResult::Damage { amount, mitigation: _, category: _, immunity: _ } => assert_eq!(amount, 256), + ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256), _ => panic!("not damage"), }; } @@ -1160,7 +1159,7 @@ mod tests { res = recharge(&mut x, &mut y, res); match res.results[0] { - ResolutionResult::Recharge { red, blue, immunity: _ } => { + ResolutionResult::Recharge { red, blue } => { assert!(red == 5); assert!(blue == 5); } From 467db4838f31913a3ddb4a3d243e2e4a9af00fa7 Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 17:37:49 +1100 Subject: [PATCH 2/8] speeds based on colour and base item --- server/WORKLOG.md | 2 +- server/src/skill.rs | 61 ++++++++------------------------------------- server/src/vbox.rs | 23 +++++++++++++++++ 3 files changed, 34 insertions(+), 52 deletions(-) diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 5a8cdbef..95c9ff40 100644 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -19,6 +19,7 @@ cryp vbox ensure all skills impl ez Skill::Slay -> red attack with bonus somethingorother for blue / maim no healing + Hatred -> damage received converted into bonus dmg aoe Skill::Ruin -> aoe stun @@ -45,7 +46,6 @@ change to ownership pattern deal_damage(colour) resolutions.push(skill()).flatten() overkill in logs - immunity resolution type * confirm cryp without skill ready * iconography diff --git a/server/src/skill.rs b/server/src/skill.rs index b004fb6c..7bcde9c7 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -2,6 +2,7 @@ use rand::{thread_rng, Rng}; use uuid::Uuid; use cryp::{Cryp, CrypEffect, Stat}; +use vbox::{Var}; #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub struct Cast { @@ -550,57 +551,6 @@ impl Skill { pub fn speed(&self) -> u8 { match self { - - // defensive block - Skill::Block => 10, // reduce damage - Skill::Parry => 10, // avoid all damage - Skill::Snare => 10, - Skill::Shield => 10, // avoid magic damage, - - // fast phys combat - Skill::Attack => 5, - Skill::Strike => 10, - Skill::Banish => 5, - Skill::Blast => 5, - Skill::Decay => 5, // dot - - // magic combat trickery - Skill::Invert => 3, // hot - Skill::Triage => 3, // hot - Skill::Slow => 3, - Skill::Amplify => 3, - Skill::Curse => 3, - Skill::Empower => 3, - Skill::Haste => 3, - - // general combat - Skill::DecayTick => 2, // hot - Skill::Siphon => 2, - Skill::SiphonTick => 2, // hot - Skill::Hex => 2, - Skill::Silence => 2, - Skill::Stun => 2, - Skill::Throw => 2, // no damage stun, adds vulnerable - Skill::TriageTick => 2, // hot - - Skill::Heal => 1, - Skill::Purify => 1, - Skill::Purge => 1, - - Skill::Recharge => 1, - Skill::Reflect => 5, - Skill::Ruin => 1, - Skill::Slay => 1, - Skill::Strangle => 5, - Skill::StrangleTick => 5, - Skill::Clutch => 1, - Skill::Taunt => 1, - Skill::Toxic => 1, - - - // unimplemented - // Skill::Lag => 2, // - // ----------------- // Test // ----------------- @@ -609,6 +559,15 @@ impl Skill { Skill::TestBlock => 10, Skill::TestParry => 10, Skill::TestSiphon => 10, + + Skill::Strike => u8::max_value(), + + Skill::SiphonTick => Var::from(Skill::Siphon).speed(), + Skill::DecayTick => Var::from(Skill::Decay).speed(), + Skill::TriageTick => Var::from(Skill::Triage).speed(), + Skill::StrangleTick => Var::from(Skill::Strangle).speed(), + + _ => Var::from(*self).speed(), } } diff --git a/server/src/vbox.rs b/server/src/vbox.rs index b8a7c920..59fd7370 100644 --- a/server/src/vbox.rs +++ b/server/src/vbox.rs @@ -145,6 +145,27 @@ impl Var { } } + pub fn speed(&self) -> u8 { + match self { + Var::Red => 3, + Var::Green => 2, + Var::Blue => 1, + + Var::Attack => 1, + Var::Stun => 2, + Var::Block => 3, + Var::Buff => 4, + Var::Debuff => 4, + + _ => { + let combos = get_combos(); + let combo = combos.iter().find(|c| c.var == *self) + .unwrap_or_else(|| panic!("unable to find components for {:?}", self)); + return combo.units.iter().fold(0, |acc, c| acc + c.speed()); + }, + } + } + fn effect(&self) -> Option { if let Some(_skill) = self.into_skill() { return Some(VarEffect::Skill); @@ -163,6 +184,7 @@ impl Var { Var::Blast => Some(Skill::Blast), Var::Block => Some(Skill::Block), Var::Curse => Some(Skill::Curse), + Var::Decay => Some(Skill::Decay), Var::Empower => Some(Skill::Empower), Var::Haste => Some(Skill::Haste), Var::Heal => Some(Skill::Heal), @@ -250,6 +272,7 @@ impl From for Var { Skill::Triage => Var::Triage, Skill::Decay => Var::Decay, Skill::Reflect => Var::Reflect, + Skill::Recharge => Var::Recharge, Skill::TestTouch => Var::TestTouch, Skill::TestStun => Var::TestStun, From 0143849ec25f3fcb7d3e32534e970255080821cb Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 18:37:58 +1100 Subject: [PATCH 3/8] sort stack speed as resolving --- server/WORKLOG.md | 2 -- server/src/game.rs | 82 ++++++++++++++++++++---------------------- server/src/instance.rs | 4 +-- server/src/skill.rs | 26 +++++++------- 4 files changed, 53 insertions(+), 61 deletions(-) diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 95c9ff40..8d2d3e1f 100644 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -28,8 +28,6 @@ ensure all skills impl Skill::Taunt -> redirect incomnig attacks to self Skill::Toxic -> apply debuff to attackers -colour speeds - update speed of rest of stack on cryp speed change include target name in effect resolution eg strangle applies buff to self diff --git a/server/src/game.rs b/server/src/game.rs index 77da22ac..f09dd29f 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -196,14 +196,12 @@ impl Game { && self.teams.iter().all(|t| t.cryps.len() == self.team_size) } - pub fn start(&mut self) -> &mut Game { + pub fn start(mut self) -> Game { self.log.push("Game starting...".to_string()); - - self.skill_phase_start(); - self + self.skill_phase_start() } - fn skill_phase_start(&mut self) -> &mut Game { + fn skill_phase_start(mut self) -> Game { self.log.push("".to_string()); if ![Phase::Start, Phase::Resolve].contains(&self.phase) { @@ -212,11 +210,9 @@ impl Game { self.phase = Phase::Skill; - self.stack.clear(); - self.pve_add_skills(); if self.skill_phase_finished() { - self.resolve_phase_start(); + return self.resolve_phase_start() } self @@ -343,7 +339,7 @@ impl Game { // requires no input // just do it - fn resolve_phase_start(&mut self) -> &mut Game { + fn resolve_phase_start(mut self) -> Game { if self.phase != Phase::Skill { panic!("game not in skill phase"); } @@ -355,7 +351,10 @@ impl Game { self.resolve_skills() } - fn log_resolution(&mut self, source: &mut Cryp, target: &mut Cryp, cast: &Cast) -> &mut Game { + fn log_resolution(&mut self, cast: &Cast) -> &mut Game { + let source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone(); + let target = self.cryp_by_id(cast.target_cryp_id).unwrap().clone(); + match cast.resolution.disable.disabled { true => { self.log.push(format!("{:} {:?} {:} disabled {:?}", source.name, cast.skill, target.name, cast.resolution.disable.effects)); @@ -415,12 +414,11 @@ impl Game { }); self.stack = sorted; - self.stack.reverse(); self } - fn resolve_skills(&mut self) -> &mut Game { + fn resolve_skills(mut self) -> Game { if self.phase != Phase::Resolve { panic!("game not in Resolve phase"); } @@ -440,17 +438,20 @@ impl Game { self.stack_sort_speed(); - // update the stack with the resolved skills - for mut skill in self.stack.clone() { + // temp vec of this round's resolving skills + // because need to check cooldown use before pushing them into the complete list + let mut resolving = vec![]; + + while let Some(mut skill) = self.stack.pop() { // println!("{:} resolving ", skill); let mut source = self.cryp_by_id(skill.source_cryp_id).unwrap().clone(); let mut target = self.cryp_by_id(skill.target_cryp_id).unwrap().clone(); skill.set_resolution(&mut source, &mut target); - self.log_resolution(&mut source, &mut target, &skill); + self.log_resolution(&skill); - self.resolved.push(skill); + resolving.push(skill); if target.is_ko() && !target.ko_logged { self.log.push(format!("{:} KO", target.name)); @@ -467,17 +468,15 @@ 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(); + self.stack_sort_speed(); }; - // println!("{:#?}", self.resolved); + // println!("{:#?}", self.resolving); // now Resolve has all been assigned // handle cooldowns and statuses - self.progress_durations(); + self.progress_durations(&resolving); + self.resolved.append(&mut resolving); if self.finished() { return self.finish() @@ -486,7 +485,7 @@ impl Game { self.skill_phase_start() } - fn progress_durations(&mut self) -> &mut Game { + fn progress_durations(&mut self, resolved: &Vec) -> &mut Game { for mut cryp in self.all_cryps() { // println!("progressing durations for {:}", cryp.name); @@ -497,7 +496,7 @@ impl Game { // only reduce cooldowns if no cd was used // have to borrow self for the skill check { - if let Some(skill) = self.stack.iter_mut().find(|s| s.source_cryp_id == cryp.id) { + if let Some(skill) = resolved.iter().find(|s| s.source_cryp_id == cryp.id) { if skill.used_cooldown() { cryp.skill_set_cd(skill.skill); } else { @@ -524,10 +523,9 @@ impl Game { self.teams.iter().find(|t| t.cryps.iter().any(|c| !c.is_ko())) } - fn finish(&mut self) -> &mut Game { + fn finish(mut self) -> Game { self.phase = Phase::Finish; self.log.push(format!("Game finished.")); - self.stack.clear(); { let winner = self.teams.iter().find(|t| t.cryps.iter().any(|c| !c.is_ko())); @@ -567,7 +565,7 @@ pub fn game_skill(params: GameSkillParams, tx: &mut Transaction, account: &Accou game.add_skill(account.id, params.cryp_id, params.target_cryp_id, params.skill)?; if game.skill_phase_finished() { - game.resolve_phase_start(); + game = game.resolve_phase_start(); } game_update(&game, tx)?; @@ -843,7 +841,7 @@ pub fn game_instance_join(tx: &mut Transaction, player: Player, game_id: Uuid) - game.team_add(team)?; if game.can_start() { - game.start(); + game = game.start(); } println!("{:?} game joined", game.id); @@ -905,9 +903,7 @@ mod tests { assert!(game.can_start()); - game.start(); - - return game; + return game.start(); } fn create_2v2_test_game() -> Game { @@ -953,9 +949,7 @@ mod tests { assert!(game.can_start()); - game.start(); - - return game; + return game.start(); } #[test] @@ -973,7 +967,7 @@ mod tests { assert!(game.skill_phase_finished()); - game.resolve_phase_start(); + game = game.resolve_phase_start(); assert!([Phase::Skill, Phase::Finish].contains(&game.phase)); @@ -994,7 +988,7 @@ mod tests { game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap(); assert!(game.skill_phase_finished()); - game.resolve_phase_start(); + game = game.resolve_phase_start(); // should auto progress back to skill phase assert!(game.phase == Phase::Skill); @@ -1024,7 +1018,7 @@ mod tests { game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap(); assert!(game.skill_phase_finished()); - game.resolve_phase_start(); + game = game.resolve_phase_start(); assert!(!game.team_by_id(y_team.id).cryps[0].is_stunned()); assert!(game.phase == Phase::Finish); @@ -1050,7 +1044,7 @@ mod tests { let _x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestTouch).unwrap(); game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap(); - game.resolve_phase_start(); + game = game.resolve_phase_start(); // should auto progress back to skill phase assert!(game.phase == Phase::Skill); @@ -1061,7 +1055,7 @@ mod tests { let _x_block_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::Stun).unwrap(); let _y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap(); - game.resolve_phase_start(); + game = game.resolve_phase_start(); assert!(game.team_by_id(x_team.id).cryps[0].skill_on_cd(Skill::Stun).is_some()); assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_none()); @@ -1080,7 +1074,7 @@ mod tests { let _x_block_id = game.add_skill(x_team.id, x_cryp.id, None, Skill::TestParry).unwrap(); game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestStun).unwrap(); - game.resolve_phase_start(); + game = game.resolve_phase_start(); // should not be stunned because of parry assert!(game.team_by_id(x_team.id).cryps[0].is_stunned() == false); @@ -1099,12 +1093,12 @@ mod tests { let _x_siphon_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestSiphon).unwrap(); let _y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap(); - game.resolve_phase_start(); + game = game.resolve_phase_start(); game.add_skill(x_team.id, x_cryp.id, None, Skill::TestBlock).unwrap(); game.add_skill(y_team.id, y_cryp.id, None, Skill::TestBlock).unwrap(); - game.resolve_phase_start(); + game = game.resolve_phase_start(); assert!(game.resolved.iter().any(|r| r.skill == Skill::SiphonTick)); } @@ -1127,7 +1121,7 @@ mod tests { game.add_skill(x_team.id, y_cryp.id, Some(i_cryp.id), Skill::TestTouch).unwrap(); assert!(game.skill_phase_finished()); - game.resolve_phase_start(); + game = game.resolve_phase_start(); assert!([Phase::Skill, Phase::Finish].contains(&game.phase)); @@ -1144,7 +1138,7 @@ mod tests { assert!(game.add_skill(x_team.id, x_cryp.id, Some(i_cryp.id), Skill::TestTouch).is_err()); assert!(game.skill_phase_finished()); - game.resolve_phase_start(); + game = game.resolve_phase_start(); assert!(game.team_by_id(i_team.id).skills_required() == 1); assert!(game.team_by_id(x_team.id).skills_required() == 2); diff --git a/server/src/instance.rs b/server/src/instance.rs index 81e7d6d9..4cf3ddfc 100644 --- a/server/src/instance.rs +++ b/server/src/instance.rs @@ -133,7 +133,7 @@ impl Instance { .team_add(plr_team)? .team_add(bot_team)?; - game.start(); + game = game.start(); Ok(game) } @@ -253,7 +253,7 @@ impl Instance { .team_add(a_team).unwrap() .team_add(b_team).unwrap(); - game.start(); + game = game.start(); assert!(game.finished()); let winner = game.winner().unwrap(); diff --git a/server/src/skill.rs b/server/src/skill.rs index 7bcde9c7..d2ada432 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -577,24 +577,24 @@ impl Skill { let speed = source.skill_speed(*self); - let mut resolution = Resolution { skill: *self, results: vec![], disable: source.disabled(*self), speed }; - - if target.is_ko() { - return resolution; - } + let resolution = Resolution { skill: *self, results: vec![], disable: source.disabled(*self), speed }; if resolution.disable.disabled { return resolution; } - match self.category() == Category::Red { - true => { - if let Some(evasion) = target.evade(*self) { - resolution.results.push(evasion); - return resolution; - } - }, - false => (), + // match self.category() == Category::Red { + // true => { + // if let Some(evasion) = target.evade(*self) { + // resolution.results.push(evasion); + // return resolution; + // } + // }, + // false => (), + // } + + if target.is_ko() { + return resolution; } if target.is_reflecting() { From d186feed6e5c98c2d7cc4045063c6fe73a13281c Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 19:08:44 +1100 Subject: [PATCH 4/8] bit of clone cleaning --- server/WORKLOG.md | 2 +- server/src/game.rs | 21 +++++++++++---------- server/src/vbox.rs | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/server/WORKLOG.md b/server/WORKLOG.md index 8d2d3e1f..56c48404 100644 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -16,6 +16,7 @@ # WORK WORK ## NOW cryp vbox + ensure all skills impl ez Skill::Slay -> red attack with bonus somethingorother for blue / maim no healing @@ -28,7 +29,6 @@ ensure all skills impl Skill::Taunt -> redirect incomnig attacks to self Skill::Toxic -> apply debuff to attackers -update speed of rest of stack on cryp speed change include target name in effect resolution eg strangle applies buff to self diff --git a/server/src/game.rs b/server/src/game.rs index f09dd29f..4fa07015 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -219,12 +219,12 @@ impl Game { } fn pve_add_skills(&mut self) -> &mut Game { - for mobs in self.teams - .clone() - .into_iter() - .filter(|t| t.bot) { + let mut pve_skills = vec![]; - let player_team = self.teams.iter().find(|t| t.id != mobs.id).unwrap().clone(); + for mobs in self.teams + .iter() + .filter(|t| t.bot) { + let player_team = self.teams.iter().find(|t| t.id != mobs.id).unwrap(); for mob in mobs.cryps.iter() { let skill = mob.mob_select_skill(); @@ -248,16 +248,17 @@ impl Game { target = find_target(); } - match self.add_skill(mobs.id, mob.id, Some(target.id), s) { - Ok(_) => (), - Err(e) => println!("{:?} could not add pve skill", e), - } - // println!("{:?}", cast); + pve_skills.push((mobs.id, mob.id, Some(target.id), s)); }, None => continue, }; } } + + for (team_id, mob_id, target_id, s) in pve_skills { + self.add_skill(team_id, mob_id, target_id, s).expect("unable to add pve mob skill"); + } + self } diff --git a/server/src/vbox.rs b/server/src/vbox.rs index 59fd7370..044ae624 100644 --- a/server/src/vbox.rs +++ b/server/src/vbox.rs @@ -502,7 +502,7 @@ impl Vbox { self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?; let reclaimed = self.bound.remove(i); let refund = reclaimed.cost(); - println!("reclaiming {:?} for {:?}", refund, reclaimed); + // println!("reclaiming {:?} for {:?}", refund, reclaimed); self.balance_add(refund); Ok(self) } From 24f3cb206adadfdd66535c34a82c94fac0bb72da Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 22:32:25 +1100 Subject: [PATCH 5/8] the big boi --- server/src/cryp.rs | 20 +- server/src/game.rs | 66 ++++--- server/src/skill.rs | 454 ++++++++++++++++++++++---------------------- 3 files changed, 272 insertions(+), 268 deletions(-) diff --git a/server/src/cryp.rs b/server/src/cryp.rs index b206fa17..42af21ce 100644 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -259,8 +259,9 @@ impl Cryp { } pub fn immune(&self, skill: Skill) -> Option { + // also checked in resolve stage so shouldn't happen really if self.is_ko() { - return Some(Immunity { immune: true, effects: vec![Effect::Ko]}); + return Some(vec![Effect::Ko]); } let immunities = self.effects.iter() @@ -269,15 +270,15 @@ impl Cryp { .collect::>(); if immunities.len() > 0 { - return Some(Immunity { immune: true, effects: immunities}); + return Some(immunities); } None } - pub fn disabled(&self, skill: Skill) -> Disable { + pub fn disabled(&self, skill: Skill) -> Option { if self.is_ko() && !skill.ko_castable() { - return Disable { disabled: true, effects: vec![Effect::Ko]}; + return Some(vec![Effect::Ko]); } let disables = self.effects.iter() @@ -286,10 +287,10 @@ impl Cryp { .collect::>(); if disables.len() > 0 { - return Disable { disabled: true, effects: disables}; + return Some(disables); } - return Disable { disabled: false, effects: vec![]}; + None } @@ -312,7 +313,7 @@ impl Cryp { pub fn available_skills(&self) -> Vec<&CrypSkill> { self.skills.iter() .filter(|s| s.cd.is_none()) - .filter(|s| !self.disabled(s.skill).disabled) + .filter(|s| self.disabled(s.skill).is_none()) .collect() } @@ -428,6 +429,11 @@ impl Cryp { self.speed().saturating_mul(s.speed() as u64) } + // todo complete with specs + pub fn skill_is_aoe(&self, s: Skill) -> bool { + s.aoe() + } + pub fn speed(&self) -> u64 { let speed_mods = self.effects.iter() .filter(|e| e.effect.modifications().contains(&Stat::Speed)) diff --git a/server/src/game.rs b/server/src/game.rs index 4fa07015..0cf13834 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -21,7 +21,7 @@ pub struct Team { pub id: Uuid, pub player: Option, pub bot: bool, - cryps: Vec, + pub cryps: Vec, } impl Team { @@ -154,14 +154,14 @@ impl Game { } // handle missing team properly - fn team_by_id(&mut self, id: Uuid) -> &mut Team { + pub fn team_by_id(&mut self, id: Uuid) -> &mut Team { match self.teams.iter_mut().find(|t| t.id == id) { Some(t) => t, None => panic!("id not in game {:}", id), } } - fn cryp_by_id(&mut self, id: Uuid) -> Option<&mut Cryp> { + pub fn cryp_by_id(&mut self, id: Uuid) -> Option<&mut Cryp> { match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == id)) { Some(team) => team.cryps.iter_mut().find(|c| c.id == id), None => None, @@ -309,9 +309,8 @@ impl Game { } // check here as well so uncastable spells don't go on the stack - let check = cryp.disabled(skill); - if check.disabled { - return Err(format_err!("skill disabled {:?}", check.effects)); + if let Some(disable) = cryp.disabled(skill) { + return Err(format_err!("skill disabled {:?}", disable)); } } @@ -356,19 +355,19 @@ impl Game { let source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone(); let target = self.cryp_by_id(cast.target_cryp_id).unwrap().clone(); - match cast.resolution.disable.disabled { - true => { - self.log.push(format!("{:} {:?} {:} disabled {:?}", source.name, cast.skill, target.name, cast.resolution.disable.effects)); - return self; - }, - false => (), - }; - for result in cast.resolution.results.iter() { match result { + ResolutionResult::Disable { disable } => + self.log.push(format!("{:} {:?} {:} disabled {:?}", + source.name, cast.skill, target.name, disable)), + ResolutionResult::Immunity { immunity } => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", - cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)), + cast.resolution.speed, source.name, cast.skill, target.name, immunity)), + + ResolutionResult::TargetKo => + self.log.push(format!("[{:}] {:} {:?} {:} - KO", + cast.resolution.speed, source.name, cast.skill, target.name)), ResolutionResult::Damage { amount, mitigation, category: _ } => self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)", @@ -386,6 +385,7 @@ impl Game { cast.resolution.speed, source.name, cast.skill, target.name, damage)), } }, + ResolutionResult::Effect { effect, duration } => self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T", cast.resolution.speed, source.name, cast.skill, target.name, effect, duration)), @@ -443,31 +443,29 @@ impl Game { // because need to check cooldown use before pushing them into the complete list let mut resolving = vec![]; - while let Some(mut skill) = self.stack.pop() { - // println!("{:} resolving ", skill); - let mut source = self.cryp_by_id(skill.source_cryp_id).unwrap().clone(); - let mut target = self.cryp_by_id(skill.target_cryp_id).unwrap().clone(); + while let Some(mut cast) = self.stack.pop() { + // println!("{:} resolving ", cast); - skill.set_resolution(&mut source, &mut target); + cast.finalise(&mut self); - self.log_resolution(&skill); + self.log_resolution(&cast); - resolving.push(skill); + resolving.push(cast); - if target.is_ko() && !target.ko_logged { - self.log.push(format!("{:} KO", target.name)); - target.effects.clear(); - target.ko_logged = true; - } + // if target.is_ko() && !target.ko_logged { + // self.log.push(format!("{:} KO", target.name)); + // target.effects.clear(); + // target.ko_logged = true; + // } - if source.is_ko() && !source.ko_logged { - self.log.push(format!("{:} KO", source.name)); - source.effects.clear(); - source.ko_logged = true; - } + // if source.is_ko() && !source.ko_logged { + // self.log.push(format!("{:} KO", source.name)); + // source.effects.clear(); + // source.ko_logged = true; + // } - self.update_cryp(&mut source); - self.update_cryp(&mut target); + // self.update_cryp(&mut source); + // self.update_cryp(&mut target); self.stack_sort_speed(); }; diff --git a/server/src/skill.rs b/server/src/skill.rs index d2ada432..63dfe5f0 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -3,6 +3,7 @@ use uuid::Uuid; use cryp::{Cryp, CrypEffect, Stat}; use vbox::{Var}; +use game::{Game}; #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub struct Cast { @@ -30,8 +31,32 @@ impl Cast { Cast::new(source.id, source.account, target.id, skill) } - pub fn set_resolution(&mut self, cryp: &mut Cryp, target: &mut Cryp) -> &mut Cast { - self.resolution = self.skill.resolve(cryp, target); + pub fn finalise(&mut self, game: &mut Game) -> &mut Cast { + let mut results = vec![]; + let mut source = game.cryp_by_id(self.source_cryp_id).unwrap().clone(); + + let targets = match source.skill_is_aoe(self.skill) { + true => game.teams.iter() + .find(|t| t.cryps.iter().any(|c| c.id == self.target_cryp_id)) + .unwrap() + .cryps + .iter() + .map(|c| c.id) + .collect(), + false => vec![self.target_cryp_id], + }; + + for target_id in targets { + // let mut source = game.cryp_by_id(self.source_cryp_id).unwrap(); + let mut target = game.cryp_by_id(target_id).unwrap(); + + results.append(&mut self.skill.resolve(&mut source, target)); + + // self.update_cryp(&mut source); + // self.update_cryp(&mut target); + } + + self.resolution.results = results; self } @@ -40,27 +65,13 @@ impl Cast { } } - -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] -pub struct Immunity { - pub immune: bool, - pub effects: Vec -} - -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] -pub struct Disable { - pub disabled: bool, - pub effects: Vec -} - -impl Disable { - fn new() -> Disable { - Disable { disabled: false, effects: vec![] } - } -} +pub type Disable = Vec; +pub type Immunity = Vec; #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub enum ResolutionResult { + TargetKo, + Disable { disable: Disable }, Immunity { immunity: Immunity }, Damage { amount: u64, mitigation: u64, category: Category }, Healing { amount: u64, overhealing: u64 }, @@ -74,14 +85,13 @@ pub enum ResolutionResult { #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub struct Resolution { pub skill: Skill, - pub disable: Disable, pub speed: u64, pub results: Vec, } impl Resolution { fn new(skill: Skill) -> Resolution { - Resolution { skill, results: vec![], disable: Disable::new(), speed: 0 } + Resolution { skill, results: vec![], speed: 0 } } } @@ -571,22 +581,28 @@ impl Skill { } } - pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp) -> Resolution { + pub fn aoe(&self) -> bool { + match self { + Skill::Ruin => true, + _ => false, + } + } + + pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp) -> Vec { let mut rng = thread_rng(); let _base: u64 = rng.gen(); - let speed = source.skill_speed(*self); + let mut results = vec![]; - let resolution = Resolution { skill: *self, results: vec![], disable: source.disabled(*self), speed }; - - if resolution.disable.disabled { - return resolution; + if let Some(disable) = source.disabled(*self) { + results.push(ResolutionResult::Disable { disable }); + return results; } // match self.category() == Category::Red { // true => { // if let Some(evasion) = target.evade(*self) { - // resolution.results.push(evasion); + // results.push(evasion); // return resolution; // } // }, @@ -594,52 +610,53 @@ impl Skill { // } if target.is_ko() { - return resolution; + results.push(ResolutionResult::TargetKo); + return results; } - if target.is_reflecting() { - // guard against overflow - if source.is_reflecting() { - return resolution; - } - let mut copy = source.clone(); - return self.resolve(&mut copy, source); - } + // if target.is_reflecting() { + // // guard against overflow + // if source.is_reflecting() { + // return results; + // } + // let mut copy = source.clone(); + // return self.resolve(&mut copy, source); + // } match self { - Skill::Amplify => amplify(source, target, resolution), // increase magic damage - Skill::Attack => attack(source, target, resolution), - Skill::Banish => banish(source, target, resolution), // TODO prevent all actions - Skill::Blast => blast(source, target, resolution), - Skill::Block => block(source, target, resolution), - Skill::Curse => curse(source, target, resolution), - Skill::Decay => decay(source, target, resolution), // dot - Skill::DecayTick => decay_tick(source, target, resolution), // dot - Skill::Empower => empower(source, target, resolution), // increased phys damage - Skill::Haste => haste(source, target, resolution), // speed slow - Skill::Heal => heal(source, target, resolution), - Skill::Hex => hex(source, target, resolution), // todo prevent casting - Skill::Invert => invert(source, target, resolution), // todo prevent casting - Skill::Parry => parry(source, target, resolution), - Skill::Purge => purge(source, target, resolution), // dispel all buffs - Skill::Purify => purify(source, target, resolution), // dispel all debuffs - Skill::Recharge => recharge(source, target, resolution), // target is immune to magic damage and fx - Skill::Shield => shield(source, target, resolution), // target is immune to magic damage and fx - Skill::Silence => silence(source, target, resolution), // target cannot cast spells - Skill::Siphon => siphon(source, target, resolution), - Skill::SiphonTick => siphon_tick(source, target, resolution), // hot - Skill::Slow => slow(source, target, resolution), // speed slow - Skill::Snare => snare(source, target, resolution), // TODO prevent physical moves - Skill::Strike => strike(source, target, resolution), - Skill::Stun => stun(source, target, resolution), - Skill::Throw => throw(source, target, resolution), // no damage stun, adds vulnerable - Skill::Triage => triage(source, target, resolution), // hot - Skill::TriageTick => triage_tick(source, target, resolution), // hot - Skill::Clutch => clutch(source, target, resolution), - Skill::Strangle => strangle(source, target, resolution), - Skill::StrangleTick => strangle_tick(source, target, resolution), + Skill::Amplify => amplify(source, target, results), // increase magic damage + Skill::Attack => attack(source, target, results), + Skill::Banish => banish(source, target, results), // TODO prevent all actions + Skill::Blast => blast(source, target, results), + Skill::Block => block(source, target, results), + Skill::Curse => curse(source, target, results), + Skill::Decay => decay(source, target, results), // dot + Skill::DecayTick => decay_tick(source, target, results), // dot + Skill::Empower => empower(source, target, results), // increased phys damage + Skill::Haste => haste(source, target, results), // speed slow + Skill::Heal => heal(source, target, results), + Skill::Hex => hex(source, target, results), // todo prevent casting + Skill::Invert => invert(source, target, results), // todo prevent casting + Skill::Parry => parry(source, target, results), + Skill::Purge => purge(source, target, results), // dispel all buffs + Skill::Purify => purify(source, target, results), // dispel all debuffs + Skill::Recharge => recharge(source, target, results), // target is immune to magic damage and fx + Skill::Shield => shield(source, target, results), // target is immune to magic damage and fx + Skill::Silence => silence(source, target, results), // target cannot cast spells + Skill::Siphon => siphon(source, target, results), + Skill::SiphonTick => siphon_tick(source, target, results), // hot + Skill::Slow => slow(source, target, results), // speed slow + Skill::Snare => snare(source, target, results), // TODO prevent physical moves + Skill::Strike => strike(source, target, results), + Skill::Stun => stun(source, target, results), + Skill::Throw => throw(source, target, results), // no damage stun, adds vulnerable + Skill::Triage => triage(source, target, results), // hot + Skill::TriageTick => triage_tick(source, target, results), // hot + Skill::Clutch => clutch(source, target, results), + Skill::Strangle => strangle(source, target, results), + Skill::StrangleTick => strangle_tick(source, target, results), - Skill::Reflect => reflect(source, target, resolution), + Skill::Reflect => reflect(source, target, results), Skill::Ruin => unimplemented!(), Skill::Slay => unimplemented!(), Skill::Taunt => unimplemented!(), @@ -648,11 +665,11 @@ impl Skill { // ----------------- // Test // ----------------- - Skill::TestTouch => Resolution { skill: Skill::TestTouch, results: vec![], disable: Disable::new(), speed: 0 }, - Skill::TestStun => stun(source, target, resolution), - Skill::TestBlock => block(source, target, resolution), - Skill::TestParry => parry(source, target, resolution), - Skill::TestSiphon => siphon(source, target, resolution), + Skill::TestTouch => results, + Skill::TestStun => stun(source, target, results), + Skill::TestBlock => block(source, target, results), + Skill::TestParry => parry(source, target, results), + Skill::TestSiphon => siphon(source, target, results), } } @@ -680,35 +697,35 @@ impl Skill { } } -fn attack(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn attack(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amount = cryp.red_damage(); - resolution.results.push(target.deal_red_damage(Skill::Attack, amount)); - return resolution; + results.push(target.deal_red_damage(Skill::Attack, amount)); + return results; } -fn stun(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn stun(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Stun, effect)); - return resolution; + results.push(target.add_effect(Skill::Stun, effect)); + return results; } -fn clutch(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn clutch(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Clutch, duration: Effect::Clutch.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Clutch, effect)); - return resolution; + results.push(target.add_effect(Skill::Clutch, effect)); + return results; } -fn throw(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn throw(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let stun = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None }; let vulnerable = CrypEffect { effect: Effect::Vulnerable, duration: Effect::Vulnerable.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Throw, stun)); - resolution.results.push(target.add_effect(Skill::Throw, vulnerable)); + results.push(target.add_effect(Skill::Throw, stun)); + results.push(target.add_effect(Skill::Throw, vulnerable)); - return resolution; + return results; } -fn strangle(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn strangle(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let target_stun = CrypEffect { effect: Effect::Strangle, duration: Effect::Strangle.duration(), @@ -716,14 +733,14 @@ fn strangle(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> R }; let attacker_immunity = CrypEffect { effect: Effect::Strangling, duration: Effect::Strangling.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Strangle, target_stun)); - resolution.results.push(cryp.add_effect(Skill::Strangle, attacker_immunity)); - return strangle_tick(cryp, target, resolution); + results.push(target.add_effect(Skill::Strangle, target_stun)); + results.push(cryp.add_effect(Skill::Strangle, attacker_immunity)); + return strangle_tick(cryp, target, results); } -fn strangle_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn strangle_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amount = cryp.red_damage(); - resolution.results.push(target.deal_red_damage(Skill::StrangleTick, amount)); + results.push(target.deal_red_damage(Skill::StrangleTick, amount)); // remove immunity if target ko if target.is_ko() { @@ -734,204 +751,194 @@ fn strangle_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) cryp.effects.remove(i); } - return resolution; + return results; } -fn block(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn block(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let block = CrypEffect { effect: Effect::Block, duration: Effect::Block.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Block, block)); - return resolution; + results.push(target.add_effect(Skill::Block, block)); + return results; } -fn parry(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn parry(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Parry, duration: Effect::Parry.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Parry, effect)); - return resolution; + results.push(target.add_effect(Skill::Parry, effect)); + return results; } -fn snare(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn snare(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let snare = CrypEffect { effect: Effect::Snare, duration: Effect::Snare.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Snare, snare)); - return resolution; + results.push(target.add_effect(Skill::Snare, snare)); + return results; } -fn empower(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn empower(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let empower = CrypEffect { effect: Effect::Empower, duration: Effect::Empower.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Empower, empower)); - return resolution; + results.push(target.add_effect(Skill::Empower, empower)); + return results; } -fn heal(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn heal(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amount = cryp.green_damage(); - resolution.results.push(target.deal_green_damage(Skill::Heal, amount)); - return resolution; + results.push(target.deal_green_damage(Skill::Heal, amount)); + return results; } -fn triage(cryp: &mut Cryp, target: &mut Cryp, resolution: Resolution) -> Resolution { +fn triage(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Triage, duration: Effect::Triage.duration(), tick: Some(Cast::new_tick(cryp, target, Skill::TriageTick)), }; target.add_effect(Skill::Triage, effect); - return triage_tick(cryp, target, resolution); + return triage_tick(cryp, target, results); } -fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amount = cryp.blue_damage().wrapping_div(2); - resolution.results.push(target.deal_green_damage(Skill::TriageTick, amount)); - return resolution; + results.push(target.deal_green_damage(Skill::TriageTick, amount)); + return results; } -fn blast(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn blast(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amount = cryp.blue_damage(); - resolution.results.push(target.deal_blue_damage(Skill::Blast, amount)); - return resolution; + results.push(target.deal_blue_damage(Skill::Blast, amount)); + return results; } -fn amplify(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn amplify(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amplify = CrypEffect { effect: Effect::Amplify, duration: Effect::Amplify.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Amplify, amplify)); - return resolution;; + results.push(target.add_effect(Skill::Amplify, amplify)); + return results;; } -fn haste(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn haste(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Haste, duration: Effect::Haste.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Haste, effect)); - return resolution;; + results.push(target.add_effect(Skill::Haste, effect)); + return results;; } -fn slow(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn slow(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Slow, duration: Effect::Slow.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Slow, effect)); - return resolution;; + results.push(target.add_effect(Skill::Slow, effect)); + return results;; } -fn decay(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn decay(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let decay = CrypEffect { effect: Effect::Decay, duration: Effect::Decay.duration(), tick: Some(Cast::new_tick(cryp, target, Skill::DecayTick)), }; - resolution.results.push(target.add_effect(Skill::Decay, decay)); - return decay_tick(cryp, target, resolution); + results.push(target.add_effect(Skill::Decay, decay)); + return decay_tick(cryp, target, results); } -fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amount = cryp.blue_damage(); - resolution.results.push(target.deal_blue_damage(Skill::DecayTick, amount)); - return resolution; + results.push(target.deal_blue_damage(Skill::DecayTick, amount)); + return results; } -fn hex(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn hex(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let hex = CrypEffect { effect: Effect::Hex, duration: Effect::Hex.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Hex, hex)); - return resolution;; + results.push(target.add_effect(Skill::Hex, hex)); + return results;; } -fn curse(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn curse(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let curse = CrypEffect { effect: Effect::Curse, duration: Effect::Curse.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Curse, curse)); - return resolution;; + results.push(target.add_effect(Skill::Curse, curse)); + return results;; } -fn invert(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn invert(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Invert, duration: Effect::Invert.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Invert, effect)); - return resolution;; + results.push(target.add_effect(Skill::Invert, effect)); + return results;; } -fn reflect(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn reflect(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let effect = CrypEffect { effect: Effect::Reflect, duration: Effect::Reflect.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Reflect, effect)); - return resolution;; + results.push(target.add_effect(Skill::Reflect, effect)); + return results;; } -fn recharge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { - resolution.results.push(target.recharge()); - return resolution; +fn recharge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { + results.push(target.recharge()); + return results; } -fn siphon(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn siphon(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let siphon = CrypEffect { effect: Effect::Siphon, duration: Effect::Siphon.duration(), tick: Some(Cast::new_tick(cryp, target, Skill::SiphonTick)), }; - resolution.results.push(target.add_effect(Skill::Siphon, siphon)); - return siphon_tick(cryp, target, resolution); + results.push(target.add_effect(Skill::Siphon, siphon)); + return siphon_tick(cryp, target, results); } -fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let amount = cryp.blue_damage(); let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount); - resolution.results.push(siphon_damage.clone()); + results.push(siphon_damage.clone()); match siphon_damage { ResolutionResult::Damage { amount, mitigation: _, category: _, } => { - resolution.results.push(cryp.deal_green_damage(Skill::Heal, amount)); + results.push(cryp.deal_green_damage(Skill::Heal, amount)); }, _ => panic!("siphon tick damage not dealt {:?}", siphon_damage), } - return resolution; + return results; } -fn shield(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn shield(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let shield = CrypEffect { effect: Effect::Shield, duration: Effect::Shield.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Shield, shield)); - return resolution; + results.push(target.add_effect(Skill::Shield, shield)); + return results; } -fn silence(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn silence(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let silence = CrypEffect { effect: Effect::Silence, duration: Effect::Silence.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Silence, silence)); - return resolution; + results.push(target.add_effect(Skill::Silence, silence)); + return results; } -fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { - if let Some(immunity) = target.immune(Skill::Purge) { - resolution.results.push(ResolutionResult::Immunity { immunity }); - return resolution; - } - +fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { for (i, ce) in target.effects.clone().iter_mut().enumerate() { if ce.effect.category() == Category::BlueBuff { target.effects.remove(i); - resolution.results.push(ResolutionResult::Removal { effect: ce.effect }); + results.push(ResolutionResult::Removal { effect: ce.effect }); } } - return resolution; + return results; } -fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { - if let Some(immunity) = target.immune(Skill::Purify) { - resolution.results.push(ResolutionResult::Immunity { immunity }); - return resolution; - } - +fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { for (i, ce) in target.effects.clone().iter_mut().enumerate() { if ce.effect.category() == Category::BlueDebuff { target.effects.remove(i); - resolution.results.push(ResolutionResult::Removal { effect: ce.effect }); + results.push(ResolutionResult::Removal { effect: ce.effect }); } } - return resolution; + return results; } -fn banish(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn banish(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let banish = CrypEffect { effect: Effect::Banish, duration: Effect::Banish.duration(), tick: None }; - resolution.results.push(target.add_effect(Skill::Banish, banish)); - return resolution; + results.push(target.add_effect(Skill::Banish, banish)); + return results; } -fn strike(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { +fn strike(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec) -> Vec { let _amount = cryp.red_damage(); - resolution.results.push(target.deal_red_damage(Skill::Attack, u64::max_value())); - return resolution; + results.push(target.deal_red_damage(Skill::Attack, u64::max_value())); + return results; } @@ -951,7 +958,7 @@ mod tests { x.deal_red_damage(Skill::Attack, 5); - heal(&mut y, &mut x, Resolution::new(Skill::Heal)); + heal(&mut y, &mut x, vec![]); } #[test] @@ -963,7 +970,7 @@ mod tests { .named(&"camel".to_string()); let mut log = vec![]; - decay(&mut x, &mut y, Resolution::new(Skill::Triage)); + decay(&mut x, &mut y, vec![]); assert!(y.effects.iter().any(|e| e.effect == Effect::Decay)); @@ -984,12 +991,12 @@ mod tests { x.red_damage.force(100); y.hp.force(500); - block(&mut y.clone(), &mut y, Resolution::new(Skill::Block)); + block(&mut y.clone(), &mut y, vec![]); assert!(y.effects.iter().any(|e| e.effect == Effect::Block)); - let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack)); + let results = attack(&mut x, &mut y, vec![]); - match res.results[0] { + match results[0] { ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 50), _ => panic!("not damage"), }; @@ -1005,13 +1012,13 @@ mod tests { x.red_damage.force(u64::max_value()); - clutch(&mut y.clone(), &mut y, Resolution::new(Skill::Clutch)); + clutch(&mut y.clone(), &mut y, vec![]); assert!(y.is_clutch()); - let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack)); + let results = attack(&mut x, &mut y, vec![]); assert!(y.hp() == 1); - match res.results[0] { + match results[0] { ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 1023), _ => panic!("not damage"), }; @@ -1030,45 +1037,45 @@ mod tests { y.red_shield.reduce(64); x.red_damage.force(256 + 64); - invert(&mut y.clone(), &mut y, Resolution::new(Skill::Invert)); + invert(&mut y.clone(), &mut y, vec![]); assert!(y.is_inverted()); // heal should deal green damage - heal(&mut x, &mut y, Resolution::new(Skill::Heal)); + heal(&mut x, &mut y, vec![]); assert!(y.hp() == 768); // attack should heal and recharge red shield - let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack)); + let results = attack(&mut x, &mut y, vec![]); assert!(y.hp() == 1024); - match res.results[0] { + match results[0] { ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _ } => assert_eq!(recharge, 64), _ => panic!("not inversion"), }; } - #[test] - fn reflect_test() { - let mut x = Cryp::new() - .named(&"muji".to_string()); + // #[test] + // fn reflect_test() { + // let mut x = Cryp::new() + // .named(&"muji".to_string()); - let mut y = Cryp::new() - .named(&"camel".to_string()); + // let mut y = Cryp::new() + // .named(&"camel".to_string()); - reflect(&mut y.clone(), &mut y, Resolution::new(Skill::Reflect)); - assert!(y.is_reflecting()); + // reflect(&mut y.clone(), &mut y, vec![]); + // assert!(y.is_reflecting()); - // heal should deal green damage - let mut cast = Cast::new(Uuid::nil(), Uuid::nil(), Uuid::nil(), Skill::Attack); - cast.set_resolution(&mut x, &mut y); + // // heal should deal green damage + // let mut cast = Cast::new(Uuid::nil(), Uuid::nil(), Uuid::nil(), Skill::Attack); + // cast.resolve(&mut x, &mut y); - assert!(x.hp() == 768); + // assert!(x.hp() == 768); - match cast.resolution.results[0] { - ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256), - _ => panic!("not damage"), - }; - } + // match cast.results[0] { + // ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256), + // _ => panic!("not damage"), + // }; + // } #[test] fn triage_test() { @@ -1088,15 +1095,9 @@ mod tests { y.deal_red_damage(Skill::Attack, 5); let prev_hp = y.hp(); - let res = Resolution::new(Skill::Triage); - - triage(&mut x, &mut y, res); + let results = triage(&mut x, &mut y, vec![]); assert!(y.effects.iter().any(|e| e.effect == Effect::Triage)); - - let res = Resolution::new(Skill::TriageTick); - triage_tick(&mut x, &mut y, res); - assert!(y.hp() > prev_hp); } @@ -1114,10 +1115,9 @@ mod tests { y.deal_red_damage(Skill::Attack, 5); y.deal_blue_damage(Skill::Blast, 5); - let mut res = Resolution::new(Skill::Recharge); - res = recharge(&mut x, &mut y, res); + let results = recharge(&mut x, &mut y, vec![]); - match res.results[0] { + match results[0] { ResolutionResult::Recharge { red, blue } => { assert!(red == 5); assert!(blue == 5); @@ -1132,9 +1132,9 @@ mod tests { let mut x = Cryp::new() .named(&"muji".to_string()); - silence(&mut x.clone(), &mut x, Resolution::new(Skill::Silence)); + silence(&mut x.clone(), &mut x, vec![]); assert!(x.effects.iter().any(|e| e.effect == Effect::Silence)); - assert!(x.disabled(Skill::Silence).disabled); + assert!(x.disabled(Skill::Silence).is_some()); } #[test] @@ -1144,7 +1144,7 @@ mod tests { x.blue_damage.force(50); - amplify(&mut x.clone(), &mut x, Resolution::new(Skill::Amplify)); + amplify(&mut x.clone(), &mut x, vec![]); assert!(x.effects.iter().any(|e| e.effect == Effect::Amplify)); assert_eq!(x.blue_damage(), 100); } @@ -1154,10 +1154,10 @@ mod tests { let mut x = Cryp::new() .named(&"muji".to_string()); - decay(&mut x.clone(), &mut x, Resolution::new(Skill::Decay)); + decay(&mut x.clone(), &mut x, vec![]); assert!(x.effects.iter().any(|e| e.effect == Effect::Decay)); - purify(&mut x.clone(), &mut x, Resolution::new(Skill::Purify)); + purify(&mut x.clone(), &mut x, vec![]); assert!(!x.effects.iter().any(|e| e.effect == Effect::Decay)); } } From d002e3c58b5a46da4646a74002ad78d6309bd322 Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 22:43:14 +1100 Subject: [PATCH 6/8] util fn for aoe targets --- server/src/game.rs | 10 ++++++++++ server/src/skill.rs | 15 +++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/server/src/game.rs b/server/src/game.rs index 0cf13834..71399bfa 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -177,6 +177,16 @@ impl Game { .collect::>() } + pub fn cryp_aoe_targets(&self, cryp_id: Uuid) -> Vec { + self.teams.iter() + .find(|t| t.cryps.iter().any(|c| c.id == cryp_id)) + .unwrap() + .cryps + .iter() + .map(|c| c.id) + .collect() + } + fn update_cryp(&mut self, cryp: &mut Cryp) -> &mut Game { match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == cryp.id)) { Some(team) => { diff --git a/server/src/skill.rs b/server/src/skill.rs index 63dfe5f0..6d33505c 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -34,26 +34,17 @@ impl Cast { pub fn finalise(&mut self, game: &mut Game) -> &mut Cast { let mut results = vec![]; let mut source = game.cryp_by_id(self.source_cryp_id).unwrap().clone(); + self.resolution.speed = source.skill_speed(self.skill); let targets = match source.skill_is_aoe(self.skill) { - true => game.teams.iter() - .find(|t| t.cryps.iter().any(|c| c.id == self.target_cryp_id)) - .unwrap() - .cryps - .iter() - .map(|c| c.id) - .collect(), + true => game.cryp_aoe_targets(self.target_cryp_id), false => vec![self.target_cryp_id], }; for target_id in targets { // let mut source = game.cryp_by_id(self.source_cryp_id).unwrap(); let mut target = game.cryp_by_id(target_id).unwrap(); - results.append(&mut self.skill.resolve(&mut source, target)); - - // self.update_cryp(&mut source); - // self.update_cryp(&mut target); } self.resolution.results = results; @@ -791,7 +782,7 @@ fn triage(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec duration: Effect::Triage.duration(), tick: Some(Cast::new_tick(cryp, target, Skill::TriageTick)), }; - target.add_effect(Skill::Triage, effect); + results.push(target.add_effect(Skill::Triage, effect)); return triage_tick(cryp, target, results); } From 3a20de13e8cc75bc3f65d69f2f6d4784defaffbd Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 22:47:47 +1100 Subject: [PATCH 7/8] frontend fixes --- client/src/scenes/combat.render.resolutions.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/src/scenes/combat.render.resolutions.js b/client/src/scenes/combat.render.resolutions.js index 29eeeb61..ea1bc8be 100644 --- a/client/src/scenes/combat.render.resolutions.js +++ b/client/src/scenes/combat.render.resolutions.js @@ -46,7 +46,10 @@ function calculateTweenParams(sourceSpawn, targetSpawn, account) { function animatePhase(scene, game, resolution, cb) { // return early for disabled skills - if (resolution.resolution.disable.disabled) return cb(); + const { resolution: { results } } = resolution; + if (results.length === 0) return cb(); + if (results[0][0] === 'Disable') return cb(); + const group = scene.scene.get('CombatCryps').cryps; const animations = new CombatAnimations(scene); const account = scene.registry.get('account'); @@ -65,10 +68,6 @@ function animatePhase(scene, game, resolution, cb) { }; const castLocation = castParams(); - const { resolution: { results } } = resolution; - - if (results.length === 0) return cb(); - // Move cryps into position if (moveSourceBattle) scene.tweens.add(moveSourceBattle); scene.tweens.add(moveTargetBattle); From aa2832f4d89df807f36f4ca1fa186f92aa227699 Mon Sep 17 00:00:00 2001 From: ntr Date: Sun, 24 Mar 2019 23:01:59 +1100 Subject: [PATCH 8/8] reflect is back --- server/src/cryp.rs | 6 ------ server/src/skill.rs | 47 +++++++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/server/src/cryp.rs b/server/src/cryp.rs index 42af21ce..a128204a 100644 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -388,11 +388,6 @@ impl Cryp { self } - // pub fn rez(&mut self) -> &mut Cryp { - // self.hp.set(self.hp.base); - // self - // } - // Stats pub fn red_damage(&self) -> u64 { let red_damage_mods = self.effects.iter() @@ -424,7 +419,6 @@ impl Cryp { return modified_green_damage; } - pub fn skill_speed(&self, s: Skill) -> u64 { self.speed().saturating_mul(s.speed() as u64) } diff --git a/server/src/skill.rs b/server/src/skill.rs index 6d33505c..ffe15237 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -605,14 +605,13 @@ impl Skill { return results; } - // if target.is_reflecting() { - // // guard against overflow - // if source.is_reflecting() { - // return results; - // } - // let mut copy = source.clone(); - // return self.resolve(&mut copy, source); - // } + if target.is_reflecting() { + // guard against overflow + if source.is_reflecting() { + return results; + } + return self.resolve(target, source); + } match self { Skill::Amplify => amplify(source, target, results), // increase magic damage @@ -1045,28 +1044,26 @@ mod tests { }; } - // #[test] - // fn reflect_test() { - // let mut x = Cryp::new() - // .named(&"muji".to_string()); + #[test] + fn reflect_test() { + let mut x = Cryp::new() + .named(&"muji".to_string()); - // let mut y = Cryp::new() - // .named(&"camel".to_string()); + let mut y = Cryp::new() + .named(&"camel".to_string()); - // reflect(&mut y.clone(), &mut y, vec![]); - // assert!(y.is_reflecting()); + reflect(&mut y.clone(), &mut y, vec![]); + assert!(y.is_reflecting()); - // // heal should deal green damage - // let mut cast = Cast::new(Uuid::nil(), Uuid::nil(), Uuid::nil(), Skill::Attack); - // cast.resolve(&mut x, &mut y); + let results = Skill::Attack.resolve(&mut x, &mut y); - // assert!(x.hp() == 768); + assert!(x.hp() == 768); - // match cast.results[0] { - // ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256), - // _ => panic!("not damage"), - // }; - // } + match results[0] { + ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256), + _ => panic!("not damage"), + }; + } #[test] fn triage_test() {