diff --git a/server/src/game.rs b/server/src/game.rs index 27784734..69bba67f 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -429,7 +429,7 @@ impl Game { for target_id in targets { // let mut source = game.cryp_by_id(self.source_cryp_id).unwrap(); let mut target = self.cryp_by_id(target_id).unwrap(); - resolutions.append(&mut cast.skill.resolve(&mut source, target)); + resolutions = cast.skill.resolve(&mut source, target, resolutions); } resolutions.reverse(); @@ -513,7 +513,7 @@ impl Game { speed, source.name, skill, target.name, amount, mitigation)), Event::Healing { skill, amount, overhealing } => - self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:}OH)", + self.log.push(format!("[{:}] {:} {:?} {:} {:} healing ({:}OH)", speed, source.name, skill, target.name, amount, overhealing)), Event::Inversion { skill } => diff --git a/server/src/skill.rs b/server/src/skill.rs index eef09f13..7ab5532e 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -610,114 +610,112 @@ impl Skill { } } - pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp) -> Resolutions { + pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp, mut resolutions: Vec) -> Resolutions { let mut rng = thread_rng(); let _base: u64 = rng.gen(); - let mut results = vec![]; - if let Some(disable) = source.disabled(*self) { - results.push(Resolution::new(source, target).event(Event::Disable { disable, skill: *self })); - return results; + resolutions.push(Resolution::new(source, target).event(Event::Disable { disable, skill: *self })); + return resolutions; } if target.is_ko() { - results.push(Resolution::new(source, target).event(Event::TargetKo { skill: *self })); - return results; + resolutions.push(Resolution::new(source, target).event(Event::TargetKo { skill: *self })); + return resolutions; } if target.affected(Effect::Reflect) { // guard against overflow if source.affected(Effect::Reflect) { - return results; + return resolutions; } - results.push(Resolution::new(source, target).event(Event::Reflection { skill: *self })); - return self.resolve(target, source); + resolutions.push(Resolution::new(source, target).event(Event::Reflection { skill: *self })); + return self.resolve(target, source, resolutions); } // match self.category() == Category::Red { // true => { // if let Some(evasion) = target.evade(*self) { - // results.push(evasion); + // resolutions.push(evasion); // return Event; // } // }, // false => (), // } - results = match self { - 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), + resolutions = match self { + Skill::Amplify => amplify(source, target, resolutions), // increase magic damage + Skill::Attack => attack(source, target, resolutions), + Skill::Banish => banish(source, target, resolutions), // TODO prevent all actions + Skill::Blast => blast(source, target, resolutions), + Skill::Block => block(source, target, resolutions), + Skill::Curse => curse(source, target, resolutions), + Skill::Decay => decay(source, target, resolutions), // dot + Skill::DecayTick => decay_tick(source, target, resolutions), // dot + Skill::Empower => empower(source, target, resolutions), // increased phys damage + Skill::Haste => haste(source, target, resolutions), // speed slow + Skill::Heal => heal(source, target, resolutions), + Skill::Hex => hex(source, target, resolutions), // todo prevent casting + Skill::Invert => invert(source, target, resolutions), // todo prevent casting + Skill::Parry => parry(source, target, resolutions), + Skill::Purge => purge(source, target, resolutions), // dispel all buffs + Skill::Purify => purify(source, target, resolutions), // dispel all debuffs + Skill::Recharge => recharge(source, target, resolutions), // target is immune to magic damage and fx + Skill::Shield => shield(source, target, resolutions), // target is immune to magic damage and fx + Skill::Silence => silence(source, target, resolutions), // target cannot cast spells + Skill::Siphon => siphon(source, target, resolutions), + Skill::SiphonTick => siphon_tick(source, target, resolutions), // hot + Skill::Slow => slow(source, target, resolutions), // speed slow + Skill::Snare => snare(source, target, resolutions), // TODO prevent physical moves + Skill::Strike => strike(source, target, resolutions), + Skill::Stun => stun(source, target, resolutions), + Skill::Throw => throw(source, target, resolutions), // no damage stun, adds vulnerable + Skill::Triage => triage(source, target, resolutions), // hot + Skill::TriageTick => triage_tick(source, target, resolutions), // hot + Skill::Clutch => clutch(source, target, resolutions), + Skill::Strangle => strangle(source, target, resolutions), + Skill::StrangleTick => strangle_tick(source, target, resolutions), - Skill::Reflect => reflect(source, target, results), - Skill::Ruin => ruin(source, target, results), + Skill::Reflect => reflect(source, target, resolutions), + Skill::Ruin => ruin(source, target, resolutions), Skill::Slay => unimplemented!(), - Skill::Taunt => taunt(source, target, results), + Skill::Taunt => taunt(source, target, resolutions), - Skill::Corrupt => corrupt(source, target, results), + Skill::Corrupt => corrupt(source, target, resolutions), Skill::Corruption => panic!("corruption should not be castable"), - Skill::CorruptionTick => corruption_tick(source, target, results), + Skill::CorruptionTick => corruption_tick(source, target, resolutions), // ----------------- // Test // ----------------- - Skill::TestTouch => touch(source, target, 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), + Skill::TestTouch => touch(source, target, resolutions), + Skill::TestStun => stun(source, target, resolutions), + Skill::TestBlock => block(source, target, resolutions), + Skill::TestParry => parry(source, target, resolutions), + Skill::TestSiphon => siphon(source, target, resolutions), }; // if any event dealt damage to target cryp // hit them with corruption - results = match target.affected(Effect::Corrupt) { - true => match results.iter().any(|r| + resolutions = match target.affected(Effect::Corrupt) { + true => match resolutions.iter().any(|r| match r.event { Event::Damage { amount: _, mitigation: _, category: _, skill: _ } => true, _ => false, }) { - true => corruption(target, source, results), - false => results, + true => corruption(target, source, resolutions), + false => resolutions, }, - false => results, + false => resolutions, }; // i don't think we need to check the source being ko if target.is_ko() { - results.push(Resolution::new(source, target).event(Event::Ko)); + resolutions.push(Resolution::new(source, target).event(Event::Ko)); target.effects.clear(); } - return results; + return resolutions; } pub fn self_targeting(&self) -> bool { @@ -1195,10 +1193,17 @@ mod tests { reflect(&mut y.clone(), &mut y, vec![]); assert!(y.affected(Effect::Reflect)); - let mut results = Skill::Attack.resolve(&mut x, &mut y); + let mut results = vec![]; + results = Skill::Attack.resolve(&mut x, &mut y, results); assert!(x.hp() == 768); + let Resolution { source: _, target: _, event } = results.remove(0); + match event { + Event::Reflection { skill } => assert_eq!(skill, Skill::Attack), + _ => panic!("not reflection"), + }; + let Resolution { source: _, target: _, event } = results.remove(0); match event { Event::Damage { amount, mitigation: _, category: _, skill: _ } => assert_eq!(amount, 256), @@ -1217,7 +1222,7 @@ mod tests { corrupt(&mut y.clone(), &mut y, vec![]); assert!(y.affected(Effect::Corrupt)); - let _results = Skill::Attack.resolve(&mut x, &mut y); + Skill::Attack.resolve(&mut x, &mut y, vec![]); assert!(x.affected(Effect::Corruption)); } @@ -1240,7 +1245,7 @@ mod tests { y.deal_red_damage(Skill::Attack, 5); let prev_hp = y.hp(); - let _results = triage(&mut x, &mut y, vec![]); + triage(&mut x, &mut y, vec![]); assert!(y.effects.iter().any(|e| e.effect == Effect::Triage)); assert!(y.hp() > prev_hp);