the big boi

This commit is contained in:
ntr 2019-03-24 22:32:25 +11:00
parent d186feed6e
commit 24f3cb206a
3 changed files with 272 additions and 268 deletions

View File

@ -259,8 +259,9 @@ impl Cryp {
} }
pub fn immune(&self, skill: Skill) -> Option<Immunity> { pub fn immune(&self, skill: Skill) -> Option<Immunity> {
// also checked in resolve stage so shouldn't happen really
if self.is_ko() { if self.is_ko() {
return Some(Immunity { immune: true, effects: vec![Effect::Ko]}); return Some(vec![Effect::Ko]);
} }
let immunities = self.effects.iter() let immunities = self.effects.iter()
@ -269,15 +270,15 @@ impl Cryp {
.collect::<Vec<Effect>>(); .collect::<Vec<Effect>>();
if immunities.len() > 0 { if immunities.len() > 0 {
return Some(Immunity { immune: true, effects: immunities}); return Some(immunities);
} }
None None
} }
pub fn disabled(&self, skill: Skill) -> Disable { pub fn disabled(&self, skill: Skill) -> Option<Disable> {
if self.is_ko() && !skill.ko_castable() { 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() let disables = self.effects.iter()
@ -286,10 +287,10 @@ impl Cryp {
.collect::<Vec<Effect>>(); .collect::<Vec<Effect>>();
if disables.len() > 0 { 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> { pub fn available_skills(&self) -> Vec<&CrypSkill> {
self.skills.iter() self.skills.iter()
.filter(|s| s.cd.is_none()) .filter(|s| s.cd.is_none())
.filter(|s| !self.disabled(s.skill).disabled) .filter(|s| self.disabled(s.skill).is_none())
.collect() .collect()
} }
@ -428,6 +429,11 @@ impl Cryp {
self.speed().saturating_mul(s.speed() as u64) 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 { pub fn speed(&self) -> u64 {
let speed_mods = self.effects.iter() let speed_mods = self.effects.iter()
.filter(|e| e.effect.modifications().contains(&Stat::Speed)) .filter(|e| e.effect.modifications().contains(&Stat::Speed))

View File

@ -21,7 +21,7 @@ pub struct Team {
pub id: Uuid, pub id: Uuid,
pub player: Option<Uuid>, pub player: Option<Uuid>,
pub bot: bool, pub bot: bool,
cryps: Vec<Cryp>, pub cryps: Vec<Cryp>,
} }
impl Team { impl Team {
@ -154,14 +154,14 @@ impl Game {
} }
// handle missing team properly // 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) { match self.teams.iter_mut().find(|t| t.id == id) {
Some(t) => t, Some(t) => t,
None => panic!("id not in game {:}", id), 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)) { 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), Some(team) => team.cryps.iter_mut().find(|c| c.id == id),
None => None, None => None,
@ -309,9 +309,8 @@ impl Game {
} }
// check here as well so uncastable spells don't go on the stack // check here as well so uncastable spells don't go on the stack
let check = cryp.disabled(skill); if let Some(disable) = cryp.disabled(skill) {
if check.disabled { return Err(format_err!("skill disabled {:?}", disable));
return Err(format_err!("skill disabled {:?}", check.effects));
} }
} }
@ -356,19 +355,19 @@ impl Game {
let source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone(); let source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone();
let target = self.cryp_by_id(cast.target_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() { for result in cast.resolution.results.iter() {
match result { match result {
ResolutionResult::Disable { disable } =>
self.log.push(format!("{:} {:?} {:} disabled {:?}",
source.name, cast.skill, target.name, disable)),
ResolutionResult::Immunity { immunity } => ResolutionResult::Immunity { immunity } =>
self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", 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: _ } => ResolutionResult::Damage { amount, mitigation, category: _ } =>
self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)", self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)",
@ -386,6 +385,7 @@ impl Game {
cast.resolution.speed, source.name, cast.skill, target.name, damage)), cast.resolution.speed, source.name, cast.skill, target.name, damage)),
} }
}, },
ResolutionResult::Effect { effect, duration } => ResolutionResult::Effect { effect, duration } =>
self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T", self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T",
cast.resolution.speed, source.name, cast.skill, target.name, effect, duration)), 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 // because need to check cooldown use before pushing them into the complete list
let mut resolving = vec![]; let mut resolving = vec![];
while let Some(mut skill) = self.stack.pop() { while let Some(mut cast) = self.stack.pop() {
// println!("{:} resolving ", skill); // println!("{:} resolving ", cast);
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); 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 { // if target.is_ko() && !target.ko_logged {
self.log.push(format!("{:} KO", target.name)); // self.log.push(format!("{:} KO", target.name));
target.effects.clear(); // target.effects.clear();
target.ko_logged = true; // target.ko_logged = true;
} // }
if source.is_ko() && !source.ko_logged { // if source.is_ko() && !source.ko_logged {
self.log.push(format!("{:} KO", source.name)); // self.log.push(format!("{:} KO", source.name));
source.effects.clear(); // source.effects.clear();
source.ko_logged = true; // source.ko_logged = true;
} // }
self.update_cryp(&mut source); // self.update_cryp(&mut source);
self.update_cryp(&mut target); // self.update_cryp(&mut target);
self.stack_sort_speed(); self.stack_sort_speed();
}; };

View File

@ -3,6 +3,7 @@ use uuid::Uuid;
use cryp::{Cryp, CrypEffect, Stat}; use cryp::{Cryp, CrypEffect, Stat};
use vbox::{Var}; use vbox::{Var};
use game::{Game};
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub struct Cast { pub struct Cast {
@ -30,8 +31,32 @@ impl Cast {
Cast::new(source.id, source.account, target.id, skill) Cast::new(source.id, source.account, target.id, skill)
} }
pub fn set_resolution(&mut self, cryp: &mut Cryp, target: &mut Cryp) -> &mut Cast { pub fn finalise(&mut self, game: &mut Game) -> &mut Cast {
self.resolution = self.skill.resolve(cryp, target); 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 self
} }
@ -40,27 +65,13 @@ impl Cast {
} }
} }
pub type Disable = Vec<Effect>;
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub type Immunity = Vec<Effect>;
pub struct Immunity {
pub immune: bool,
pub effects: Vec<Effect>
}
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub struct Disable {
pub disabled: bool,
pub effects: Vec<Effect>
}
impl Disable {
fn new() -> Disable {
Disable { disabled: false, effects: vec![] }
}
}
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub enum ResolutionResult { pub enum ResolutionResult {
TargetKo,
Disable { disable: Disable },
Immunity { immunity: Immunity }, Immunity { immunity: Immunity },
Damage { amount: u64, mitigation: u64, category: Category }, Damage { amount: u64, mitigation: u64, category: Category },
Healing { amount: u64, overhealing: u64 }, Healing { amount: u64, overhealing: u64 },
@ -74,14 +85,13 @@ pub enum ResolutionResult {
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub struct Resolution { pub struct Resolution {
pub skill: Skill, pub skill: Skill,
pub disable: Disable,
pub speed: u64, pub speed: u64,
pub results: Vec<ResolutionResult>, pub results: Vec<ResolutionResult>,
} }
impl Resolution { impl Resolution {
fn new(skill: Skill) -> 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<ResolutionResult> {
let mut rng = thread_rng(); let mut rng = thread_rng();
let _base: u64 = rng.gen(); 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 let Some(disable) = source.disabled(*self) {
results.push(ResolutionResult::Disable { disable });
if resolution.disable.disabled { return results;
return resolution;
} }
// match self.category() == Category::Red { // match self.category() == Category::Red {
// true => { // true => {
// if let Some(evasion) = target.evade(*self) { // if let Some(evasion) = target.evade(*self) {
// resolution.results.push(evasion); // results.push(evasion);
// return resolution; // return resolution;
// } // }
// }, // },
@ -594,52 +610,53 @@ impl Skill {
// } // }
if target.is_ko() { if target.is_ko() {
return resolution; results.push(ResolutionResult::TargetKo);
return results;
} }
if target.is_reflecting() { // if target.is_reflecting() {
// guard against overflow // // guard against overflow
if source.is_reflecting() { // if source.is_reflecting() {
return resolution; // return results;
} // }
let mut copy = source.clone(); // let mut copy = source.clone();
return self.resolve(&mut copy, source); // return self.resolve(&mut copy, source);
} // }
match self { match self {
Skill::Amplify => amplify(source, target, resolution), // increase magic damage Skill::Amplify => amplify(source, target, results), // increase magic damage
Skill::Attack => attack(source, target, resolution), Skill::Attack => attack(source, target, results),
Skill::Banish => banish(source, target, resolution), // TODO prevent all actions Skill::Banish => banish(source, target, results), // TODO prevent all actions
Skill::Blast => blast(source, target, resolution), Skill::Blast => blast(source, target, results),
Skill::Block => block(source, target, resolution), Skill::Block => block(source, target, results),
Skill::Curse => curse(source, target, resolution), Skill::Curse => curse(source, target, results),
Skill::Decay => decay(source, target, resolution), // dot Skill::Decay => decay(source, target, results), // dot
Skill::DecayTick => decay_tick(source, target, resolution), // dot Skill::DecayTick => decay_tick(source, target, results), // dot
Skill::Empower => empower(source, target, resolution), // increased phys damage Skill::Empower => empower(source, target, results), // increased phys damage
Skill::Haste => haste(source, target, resolution), // speed slow Skill::Haste => haste(source, target, results), // speed slow
Skill::Heal => heal(source, target, resolution), Skill::Heal => heal(source, target, results),
Skill::Hex => hex(source, target, resolution), // todo prevent casting Skill::Hex => hex(source, target, results), // todo prevent casting
Skill::Invert => invert(source, target, resolution), // todo prevent casting Skill::Invert => invert(source, target, results), // todo prevent casting
Skill::Parry => parry(source, target, resolution), Skill::Parry => parry(source, target, results),
Skill::Purge => purge(source, target, resolution), // dispel all buffs Skill::Purge => purge(source, target, results), // dispel all buffs
Skill::Purify => purify(source, target, resolution), // dispel all debuffs Skill::Purify => purify(source, target, results), // dispel all debuffs
Skill::Recharge => recharge(source, target, resolution), // target is immune to magic damage and fx Skill::Recharge => recharge(source, target, results), // target is immune to magic damage and fx
Skill::Shield => shield(source, target, resolution), // 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, resolution), // target cannot cast spells Skill::Silence => silence(source, target, results), // target cannot cast spells
Skill::Siphon => siphon(source, target, resolution), Skill::Siphon => siphon(source, target, results),
Skill::SiphonTick => siphon_tick(source, target, resolution), // hot Skill::SiphonTick => siphon_tick(source, target, results), // hot
Skill::Slow => slow(source, target, resolution), // speed slow Skill::Slow => slow(source, target, results), // speed slow
Skill::Snare => snare(source, target, resolution), // TODO prevent physical moves Skill::Snare => snare(source, target, results), // TODO prevent physical moves
Skill::Strike => strike(source, target, resolution), Skill::Strike => strike(source, target, results),
Skill::Stun => stun(source, target, resolution), Skill::Stun => stun(source, target, results),
Skill::Throw => throw(source, target, resolution), // no damage stun, adds vulnerable Skill::Throw => throw(source, target, results), // no damage stun, adds vulnerable
Skill::Triage => triage(source, target, resolution), // hot Skill::Triage => triage(source, target, results), // hot
Skill::TriageTick => triage_tick(source, target, resolution), // hot Skill::TriageTick => triage_tick(source, target, results), // hot
Skill::Clutch => clutch(source, target, resolution), Skill::Clutch => clutch(source, target, results),
Skill::Strangle => strangle(source, target, resolution), Skill::Strangle => strangle(source, target, results),
Skill::StrangleTick => strangle_tick(source, target, resolution), Skill::StrangleTick => strangle_tick(source, target, results),
Skill::Reflect => reflect(source, target, resolution), Skill::Reflect => reflect(source, target, results),
Skill::Ruin => unimplemented!(), Skill::Ruin => unimplemented!(),
Skill::Slay => unimplemented!(), Skill::Slay => unimplemented!(),
Skill::Taunt => unimplemented!(), Skill::Taunt => unimplemented!(),
@ -648,11 +665,11 @@ impl Skill {
// ----------------- // -----------------
// Test // Test
// ----------------- // -----------------
Skill::TestTouch => Resolution { skill: Skill::TestTouch, results: vec![], disable: Disable::new(), speed: 0 }, Skill::TestTouch => results,
Skill::TestStun => stun(source, target, resolution), Skill::TestStun => stun(source, target, results),
Skill::TestBlock => block(source, target, resolution), Skill::TestBlock => block(source, target, results),
Skill::TestParry => parry(source, target, resolution), Skill::TestParry => parry(source, target, results),
Skill::TestSiphon => siphon(source, target, resolution), 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amount = cryp.red_damage(); let amount = cryp.red_damage();
resolution.results.push(target.deal_red_damage(Skill::Attack, amount)); results.push(target.deal_red_damage(Skill::Attack, amount));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Stun, effect)); results.push(target.add_effect(Skill::Stun, effect));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { effect: Effect::Clutch, duration: Effect::Clutch.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Clutch, duration: Effect::Clutch.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Clutch, effect)); results.push(target.add_effect(Skill::Clutch, effect));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let stun = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None }; let stun = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None };
let vulnerable = CrypEffect { effect: Effect::Vulnerable, duration: Effect::Vulnerable.duration(), tick: None }; let vulnerable = CrypEffect { effect: Effect::Vulnerable, duration: Effect::Vulnerable.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Throw, stun)); results.push(target.add_effect(Skill::Throw, stun));
resolution.results.push(target.add_effect(Skill::Throw, vulnerable)); 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<ResolutionResult>) -> Vec<ResolutionResult> {
let target_stun = CrypEffect { let target_stun = CrypEffect {
effect: Effect::Strangle, effect: Effect::Strangle,
duration: Effect::Strangle.duration(), 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 }; let attacker_immunity = CrypEffect { effect: Effect::Strangling, duration: Effect::Strangling.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Strangle, target_stun)); results.push(target.add_effect(Skill::Strangle, target_stun));
resolution.results.push(cryp.add_effect(Skill::Strangle, attacker_immunity)); results.push(cryp.add_effect(Skill::Strangle, attacker_immunity));
return strangle_tick(cryp, target, resolution); 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amount = cryp.red_damage(); 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 // remove immunity if target ko
if target.is_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); 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<ResolutionResult>) -> Vec<ResolutionResult> {
let block = CrypEffect { effect: Effect::Block, duration: Effect::Block.duration(), tick: None }; let block = CrypEffect { effect: Effect::Block, duration: Effect::Block.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Block, block)); results.push(target.add_effect(Skill::Block, block));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { effect: Effect::Parry, duration: Effect::Parry.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Parry, duration: Effect::Parry.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Parry, effect)); results.push(target.add_effect(Skill::Parry, effect));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let snare = CrypEffect { effect: Effect::Snare, duration: Effect::Snare.duration(), tick: None }; let snare = CrypEffect { effect: Effect::Snare, duration: Effect::Snare.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Snare, snare)); results.push(target.add_effect(Skill::Snare, snare));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let empower = CrypEffect { effect: Effect::Empower, duration: Effect::Empower.duration(), tick: None }; let empower = CrypEffect { effect: Effect::Empower, duration: Effect::Empower.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Empower, empower)); results.push(target.add_effect(Skill::Empower, empower));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amount = cryp.green_damage(); let amount = cryp.green_damage();
resolution.results.push(target.deal_green_damage(Skill::Heal, amount)); results.push(target.deal_green_damage(Skill::Heal, amount));
return resolution; return results;
} }
fn triage(cryp: &mut Cryp, target: &mut Cryp, resolution: Resolution) -> Resolution { fn triage(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { let effect = CrypEffect {
effect: Effect::Triage, effect: Effect::Triage,
duration: Effect::Triage.duration(), duration: Effect::Triage.duration(),
tick: Some(Cast::new_tick(cryp, target, Skill::TriageTick)), tick: Some(Cast::new_tick(cryp, target, Skill::TriageTick)),
}; };
target.add_effect(Skill::Triage, effect); 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amount = cryp.blue_damage().wrapping_div(2); let amount = cryp.blue_damage().wrapping_div(2);
resolution.results.push(target.deal_green_damage(Skill::TriageTick, amount)); results.push(target.deal_green_damage(Skill::TriageTick, amount));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amount = cryp.blue_damage(); let amount = cryp.blue_damage();
resolution.results.push(target.deal_blue_damage(Skill::Blast, amount)); results.push(target.deal_blue_damage(Skill::Blast, amount));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amplify = CrypEffect { effect: Effect::Amplify, duration: Effect::Amplify.duration(), tick: None }; let amplify = CrypEffect { effect: Effect::Amplify, duration: Effect::Amplify.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Amplify, amplify)); results.push(target.add_effect(Skill::Amplify, amplify));
return resolution;; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { effect: Effect::Haste, duration: Effect::Haste.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Haste, duration: Effect::Haste.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Haste, effect)); results.push(target.add_effect(Skill::Haste, effect));
return resolution;; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { effect: Effect::Slow, duration: Effect::Slow.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Slow, duration: Effect::Slow.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Slow, effect)); results.push(target.add_effect(Skill::Slow, effect));
return resolution;; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let decay = CrypEffect { let decay = CrypEffect {
effect: Effect::Decay, effect: Effect::Decay,
duration: Effect::Decay.duration(), duration: Effect::Decay.duration(),
tick: Some(Cast::new_tick(cryp, target, Skill::DecayTick)), tick: Some(Cast::new_tick(cryp, target, Skill::DecayTick)),
}; };
resolution.results.push(target.add_effect(Skill::Decay, decay)); results.push(target.add_effect(Skill::Decay, decay));
return decay_tick(cryp, target, resolution); 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amount = cryp.blue_damage(); let amount = cryp.blue_damage();
resolution.results.push(target.deal_blue_damage(Skill::DecayTick, amount)); results.push(target.deal_blue_damage(Skill::DecayTick, amount));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let hex = CrypEffect { effect: Effect::Hex, duration: Effect::Hex.duration(), tick: None }; let hex = CrypEffect { effect: Effect::Hex, duration: Effect::Hex.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Hex, hex)); results.push(target.add_effect(Skill::Hex, hex));
return resolution;; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let curse = CrypEffect { effect: Effect::Curse, duration: Effect::Curse.duration(), tick: None }; let curse = CrypEffect { effect: Effect::Curse, duration: Effect::Curse.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Curse, curse)); results.push(target.add_effect(Skill::Curse, curse));
return resolution;; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { effect: Effect::Invert, duration: Effect::Invert.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Invert, duration: Effect::Invert.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Invert, effect)); results.push(target.add_effect(Skill::Invert, effect));
return resolution;; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let effect = CrypEffect { effect: Effect::Reflect, duration: Effect::Reflect.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Reflect, duration: Effect::Reflect.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Reflect, effect)); results.push(target.add_effect(Skill::Reflect, effect));
return resolution;; return results;;
} }
fn recharge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { fn recharge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
resolution.results.push(target.recharge()); results.push(target.recharge());
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let siphon = CrypEffect { let siphon = CrypEffect {
effect: Effect::Siphon, effect: Effect::Siphon,
duration: Effect::Siphon.duration(), duration: Effect::Siphon.duration(),
tick: Some(Cast::new_tick(cryp, target, Skill::SiphonTick)), tick: Some(Cast::new_tick(cryp, target, Skill::SiphonTick)),
}; };
resolution.results.push(target.add_effect(Skill::Siphon, siphon)); results.push(target.add_effect(Skill::Siphon, siphon));
return siphon_tick(cryp, target, resolution); 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<ResolutionResult>) -> Vec<ResolutionResult> {
let amount = cryp.blue_damage(); let amount = cryp.blue_damage();
let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount); let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount);
resolution.results.push(siphon_damage.clone()); results.push(siphon_damage.clone());
match siphon_damage { match siphon_damage {
ResolutionResult::Damage { amount, mitigation: _, category: _, } => { 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), _ => 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<ResolutionResult>) -> Vec<ResolutionResult> {
let shield = CrypEffect { effect: Effect::Shield, duration: Effect::Shield.duration(), tick: None }; let shield = CrypEffect { effect: Effect::Shield, duration: Effect::Shield.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Shield, shield)); results.push(target.add_effect(Skill::Shield, shield));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let silence = CrypEffect { effect: Effect::Silence, duration: Effect::Silence.duration(), tick: None }; let silence = CrypEffect { effect: Effect::Silence, duration: Effect::Silence.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Silence, silence)); results.push(target.add_effect(Skill::Silence, silence));
return resolution; return results;
} }
fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution { fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
if let Some(immunity) = target.immune(Skill::Purge) {
resolution.results.push(ResolutionResult::Immunity { immunity });
return resolution;
}
for (i, ce) in target.effects.clone().iter_mut().enumerate() { for (i, ce) in target.effects.clone().iter_mut().enumerate() {
if ce.effect.category() == Category::BlueBuff { if ce.effect.category() == Category::BlueBuff {
target.effects.remove(i); 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 { fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
if let Some(immunity) = target.immune(Skill::Purify) {
resolution.results.push(ResolutionResult::Immunity { immunity });
return resolution;
}
for (i, ce) in target.effects.clone().iter_mut().enumerate() { for (i, ce) in target.effects.clone().iter_mut().enumerate() {
if ce.effect.category() == Category::BlueDebuff { if ce.effect.category() == Category::BlueDebuff {
target.effects.remove(i); 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<ResolutionResult>) -> Vec<ResolutionResult> {
let banish = CrypEffect { effect: Effect::Banish, duration: Effect::Banish.duration(), tick: None }; let banish = CrypEffect { effect: Effect::Banish, duration: Effect::Banish.duration(), tick: None };
resolution.results.push(target.add_effect(Skill::Banish, banish)); results.push(target.add_effect(Skill::Banish, banish));
return resolution; 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<ResolutionResult>) -> Vec<ResolutionResult> {
let _amount = cryp.red_damage(); let _amount = cryp.red_damage();
resolution.results.push(target.deal_red_damage(Skill::Attack, u64::max_value())); results.push(target.deal_red_damage(Skill::Attack, u64::max_value()));
return resolution; return results;
} }
@ -951,7 +958,7 @@ mod tests {
x.deal_red_damage(Skill::Attack, 5); x.deal_red_damage(Skill::Attack, 5);
heal(&mut y, &mut x, Resolution::new(Skill::Heal)); heal(&mut y, &mut x, vec![]);
} }
#[test] #[test]
@ -963,7 +970,7 @@ mod tests {
.named(&"camel".to_string()); .named(&"camel".to_string());
let mut log = vec![]; 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)); assert!(y.effects.iter().any(|e| e.effect == Effect::Decay));
@ -984,12 +991,12 @@ mod tests {
x.red_damage.force(100); x.red_damage.force(100);
y.hp.force(500); 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)); 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), ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 50),
_ => panic!("not damage"), _ => panic!("not damage"),
}; };
@ -1005,13 +1012,13 @@ mod tests {
x.red_damage.force(u64::max_value()); 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()); 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); assert!(y.hp() == 1);
match res.results[0] { match results[0] {
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 1023), ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 1023),
_ => panic!("not damage"), _ => panic!("not damage"),
}; };
@ -1030,45 +1037,45 @@ mod tests {
y.red_shield.reduce(64); y.red_shield.reduce(64);
x.red_damage.force(256 + 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()); assert!(y.is_inverted());
// heal should deal green damage // heal should deal green damage
heal(&mut x, &mut y, Resolution::new(Skill::Heal)); heal(&mut x, &mut y, vec![]);
assert!(y.hp() == 768); assert!(y.hp() == 768);
// attack should heal and recharge red shield // 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); assert!(y.hp() == 1024);
match res.results[0] { match results[0] {
ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _ } => assert_eq!(recharge, 64), ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _ } => assert_eq!(recharge, 64),
_ => panic!("not inversion"), _ => panic!("not inversion"),
}; };
} }
#[test] // #[test]
fn reflect_test() { // fn reflect_test() {
let mut x = Cryp::new() // let mut x = Cryp::new()
.named(&"muji".to_string()); // .named(&"muji".to_string());
let mut y = Cryp::new() // let mut y = Cryp::new()
.named(&"camel".to_string()); // .named(&"camel".to_string());
reflect(&mut y.clone(), &mut y, Resolution::new(Skill::Reflect)); // reflect(&mut y.clone(), &mut y, vec![]);
assert!(y.is_reflecting()); // assert!(y.is_reflecting());
// heal should deal green damage // // heal should deal green damage
let mut cast = Cast::new(Uuid::nil(), Uuid::nil(), Uuid::nil(), Skill::Attack); // let mut cast = Cast::new(Uuid::nil(), Uuid::nil(), Uuid::nil(), Skill::Attack);
cast.set_resolution(&mut x, &mut y); // cast.resolve(&mut x, &mut y);
assert!(x.hp() == 768); // assert!(x.hp() == 768);
match cast.resolution.results[0] { // match cast.results[0] {
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256), // ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256),
_ => panic!("not damage"), // _ => panic!("not damage"),
}; // };
} // }
#[test] #[test]
fn triage_test() { fn triage_test() {
@ -1088,15 +1095,9 @@ mod tests {
y.deal_red_damage(Skill::Attack, 5); y.deal_red_damage(Skill::Attack, 5);
let prev_hp = y.hp(); let prev_hp = y.hp();
let res = Resolution::new(Skill::Triage); let results = triage(&mut x, &mut y, vec![]);
triage(&mut x, &mut y, res);
assert!(y.effects.iter().any(|e| e.effect == Effect::Triage)); 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); assert!(y.hp() > prev_hp);
} }
@ -1114,10 +1115,9 @@ mod tests {
y.deal_red_damage(Skill::Attack, 5); y.deal_red_damage(Skill::Attack, 5);
y.deal_blue_damage(Skill::Blast, 5); y.deal_blue_damage(Skill::Blast, 5);
let mut res = Resolution::new(Skill::Recharge); let results = recharge(&mut x, &mut y, vec![]);
res = recharge(&mut x, &mut y, res);
match res.results[0] { match results[0] {
ResolutionResult::Recharge { red, blue } => { ResolutionResult::Recharge { red, blue } => {
assert!(red == 5); assert!(red == 5);
assert!(blue == 5); assert!(blue == 5);
@ -1132,9 +1132,9 @@ mod tests {
let mut x = Cryp::new() let mut x = Cryp::new()
.named(&"muji".to_string()); .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.effects.iter().any(|e| e.effect == Effect::Silence));
assert!(x.disabled(Skill::Silence).disabled); assert!(x.disabled(Skill::Silence).is_some());
} }
#[test] #[test]
@ -1144,7 +1144,7 @@ mod tests {
x.blue_damage.force(50); 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!(x.effects.iter().any(|e| e.effect == Effect::Amplify));
assert_eq!(x.blue_damage(), 100); assert_eq!(x.blue_damage(), 100);
} }
@ -1154,10 +1154,10 @@ mod tests {
let mut x = Cryp::new() let mut x = Cryp::new()
.named(&"muji".to_string()); .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)); 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)); assert!(!x.effects.iter().any(|e| e.effect == Effect::Decay));
} }
} }