another one

This commit is contained in:
ntr 2019-03-25 13:45:23 +11:00
parent aa2832f4d8
commit c3beed3690
3 changed files with 215 additions and 172 deletions

View File

@ -9,7 +9,7 @@ use failure::err_msg;
use account::{Account}; use account::{Account};
use rpc::{CrypSpawnParams}; use rpc::{CrypSpawnParams};
use skill::{Skill, Cooldown, Effect, Cast, Category, Immunity, Disable, ResolutionResult}; use skill::{Skill, Cooldown, Effect, Cast, Category, Immunity, Disable, Event};
use spec::{Spec}; use spec::{Spec};
use game::{Log}; use game::{Log};
use vbox::Var; use vbox::Var;
@ -449,9 +449,9 @@ impl Cryp {
} }
} }
pub fn recharge(&mut self) -> ResolutionResult { pub fn recharge(&mut self) -> Event {
if let Some(immunity) = self.immune(Skill::Recharge) { if let Some(immunity) = self.immune(Skill::Recharge) {
return ResolutionResult::Immunity { return Event::Immunity {
immunity, immunity,
}; };
} }
@ -462,12 +462,12 @@ impl Cryp {
let blue = self.blue_shield.max.saturating_sub(self.blue_shield.value); let blue = self.blue_shield.max.saturating_sub(self.blue_shield.value);
self.blue_shield.value = self.blue_shield.max; self.blue_shield.value = self.blue_shield.max;
ResolutionResult::Recharge { red, blue } Event::Recharge { red, blue }
} }
pub fn deal_green_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { pub fn deal_green_damage(&mut self, skill: Skill, amount: u64) -> Event {
if let Some(immunity) = self.immune(skill) { if let Some(immunity) = self.immune(skill) {
return ResolutionResult::Immunity { return Event::Immunity {
immunity, immunity,
}; };
} }
@ -490,7 +490,7 @@ impl Cryp {
let healing = new_hp - current_hp; let healing = new_hp - current_hp;
let overhealing = modified_healing - healing; let overhealing = modified_healing - healing;
return ResolutionResult::Healing { return Event::Healing {
amount: healing, amount: healing,
overhealing, overhealing,
}; };
@ -501,7 +501,7 @@ impl Cryp {
self.reduce_hp(modified_healing); self.reduce_hp(modified_healing);
let delta = current_hp - self.hp(); let delta = current_hp - self.hp();
return ResolutionResult::Inversion { return Event::Inversion {
damage: delta, damage: delta,
healing: 0, healing: 0,
recharge: 0, recharge: 0,
@ -511,9 +511,9 @@ impl Cryp {
} }
} }
pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> Event {
if let Some(immunity) = self.immune(skill) { if let Some(immunity) = self.immune(skill) {
return ResolutionResult::Immunity { return Event::Immunity {
immunity, immunity,
}; };
} }
@ -544,7 +544,7 @@ impl Cryp {
self.reduce_hp(remainder); self.reduce_hp(remainder);
let delta = current_hp - self.hp(); let delta = current_hp - self.hp();
return ResolutionResult::Damage { return Event::Damage {
amount: delta, amount: delta,
mitigation, mitigation,
category: Category::RedDamage, category: Category::RedDamage,
@ -561,7 +561,7 @@ impl Cryp {
self.red_shield.increase(overhealing); self.red_shield.increase(overhealing);
let recharge = self.red_shield.value - current_shield; let recharge = self.red_shield.value - current_shield;
return ResolutionResult::Inversion { return Event::Inversion {
damage: 0, damage: 0,
healing, healing,
recharge, recharge,
@ -571,9 +571,9 @@ impl Cryp {
} }
} }
pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult { pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> Event {
if let Some(immunity) = self.immune(skill) { if let Some(immunity) = self.immune(skill) {
return ResolutionResult::Immunity { return Event::Immunity {
immunity, immunity,
}; };
} }
@ -597,7 +597,7 @@ impl Cryp {
self.reduce_hp(remainder); self.reduce_hp(remainder);
let delta = current_hp - self.hp(); let delta = current_hp - self.hp();
return ResolutionResult::Damage { return Event::Damage {
amount: delta, amount: delta,
mitigation, mitigation,
category: Category::BlueDamage, category: Category::BlueDamage,
@ -614,7 +614,7 @@ impl Cryp {
self.blue_shield.increase(overhealing); self.blue_shield.increase(overhealing);
let recharge = self.blue_shield.value - current_shield; let recharge = self.blue_shield.value - current_shield;
return ResolutionResult::Inversion { return Event::Inversion {
damage: 0, damage: 0,
healing, healing,
recharge, recharge,
@ -624,15 +624,15 @@ impl Cryp {
} }
} }
pub fn add_effect(&mut self, skill: Skill, effect: CrypEffect) -> ResolutionResult { pub fn add_effect(&mut self, skill: Skill, effect: CrypEffect) -> Event {
if let Some(immunity) = self.immune(skill) { if let Some(immunity) = self.immune(skill) {
return ResolutionResult::Immunity { return Event::Immunity {
immunity, immunity,
}; };
} }
// todo modified durations cause of buffs // todo modified durations cause of buffs
let result = ResolutionResult::Effect { let result = Event::Effect {
effect: effect.effect, effect: effect.effect,
duration: effect.effect.duration(), duration: effect.effect.duration(),
}; };
@ -643,7 +643,7 @@ impl Cryp {
return result; return result;
} }
pub fn evade(&self, skill: Skill) -> Option<ResolutionResult> { pub fn evade(&self, skill: Skill) -> Option<Event> {
if self.evasion.value == 0 { if self.evasion.value == 0 {
return None; return None;
} }
@ -655,7 +655,7 @@ impl Cryp {
println!("{:} < {:?}", roll, evasion_rating); println!("{:} < {:?}", roll, evasion_rating);
match roll < evasion_rating { match roll < evasion_rating {
true => Some(ResolutionResult::Evasion { true => Some(Event::Evasion {
skill, skill,
evasion_rating: evasion_rating, evasion_rating: evasion_rating,
}), }),

View File

@ -10,7 +10,7 @@ use failure::err_msg;
use account::Account; use account::Account;
use rpc::{GameStateParams, GameSkillParams}; use rpc::{GameStateParams, GameSkillParams};
use cryp::{Cryp}; use cryp::{Cryp};
use skill::{Skill, Cast, ResolutionResult}; use skill::{Skill, Cast, Resolution, Event};
use player::{Player}; use player::{Player};
use instance::{instance_game_finished, global_game_finished}; use instance::{instance_game_finished, global_game_finished};
@ -168,6 +168,17 @@ impl Game {
} }
} }
pub fn cryp_name(&mut self, id: Uuid) -> String {
match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == id)) {
Some(team) => {
let cryp = team.cryps.iter_mut().find(|c| c.id == id).expect("cryp not in team");
return cryp.name.clone();
}
None => panic!("{:?} not in game", id),
}
}
fn all_cryps(&self) -> Vec<Cryp> { fn all_cryps(&self) -> Vec<Cryp> {
self.teams.clone() self.teams.clone()
.into_iter() .into_iter()
@ -361,56 +372,61 @@ impl Game {
self.resolve_skills() self.resolve_skills()
} }
fn log_resolution(&mut self, cast: &Cast) -> &mut Game { // remove names from the cast
let source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone(); // put them in teh result
let target = self.cryp_by_id(cast.target_cryp_id).unwrap().clone(); // just add the results to the resolved vec
// try remove casts altogether
for result in cast.resolution.results.iter() { fn log_resolution(&mut self, cast: &Cast) -> &mut Game {
match result { for resolution in cast.resolutions.iter() {
ResolutionResult::Disable { disable } => let Resolution { source, target, event } = resolution;
match event {
Event::Disable { disable } =>
self.log.push(format!("{:} {:?} {:} disabled {:?}", self.log.push(format!("{:} {:?} {:} disabled {:?}",
source.name, cast.skill, target.name, disable)), source.name, cast.skill, target.name, disable)),
ResolutionResult::Immunity { immunity } => Event::Immunity { immunity } =>
self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
cast.resolution.speed, source.name, cast.skill, target.name, immunity)), cast.speed, source.name, cast.skill, target.name, immunity)),
ResolutionResult::TargetKo => Event::TargetKo =>
self.log.push(format!("[{:}] {:} {:?} {:} - KO", self.log.push(format!("[{:}] {:} {:?} {:} - KO",
cast.resolution.speed, source.name, cast.skill, target.name)), cast.speed, source.name, cast.skill, target.name)),
ResolutionResult::Damage { amount, mitigation, category: _ } => Event::Damage { amount, mitigation, category: _ } =>
self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)", self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)",
cast.resolution.speed, source.name, cast.skill, target.name, amount, mitigation)), cast.speed, source.name, cast.skill, target.name, amount, mitigation)),
ResolutionResult::Healing { amount, overhealing } => Event::Healing { amount, overhealing } =>
self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:}OH)", self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:}OH)",
cast.resolution.speed, source.name, cast.skill, target.name, amount, overhealing)), cast.speed, source.name, cast.skill, target.name, amount, overhealing)),
ResolutionResult::Inversion { healing, damage, recharge, category: _ } => { Event::Inversion { healing, damage, recharge, category: _ } => {
match *healing > 0 { match *healing > 0 {
true => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:} ({:} recharge)", true => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:} ({:} recharge)",
cast.resolution.speed, source.name, cast.skill, target.name, healing, recharge)), cast.speed, source.name, cast.skill, target.name, healing, recharge)),
false => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:}", false => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:}",
cast.resolution.speed, source.name, cast.skill, target.name, damage)), cast.speed, source.name, cast.skill, target.name, damage)),
} }
}, },
ResolutionResult::Effect { effect, duration } => Event::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.speed, source.name, cast.skill, target.name, effect, duration)),
ResolutionResult::Removal { effect } => Event::Removal { effect } =>
self.log.push(format!("[{:}] {:?} removed {:} {:?}", self.log.push(format!("[{:}] {:?} removed {:} {:?}",
cast.resolution.speed, source.name, target.name, effect)), cast.speed, source.name, target.name, effect)),
ResolutionResult::Recharge { red, blue } => Event::Recharge { red, blue } =>
self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B", self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B",
cast.resolution.speed, source.name, cast.skill, target.name, red, blue)), cast.speed, source.name, cast.skill, target.name, red, blue)),
ResolutionResult::Evasion { skill: _, evasion_rating } => Event::Evasion { skill: _, evasion_rating } =>
self.log.push(format!("[{:}] {:} {:?} {:} evaded ({:}%)", self.log.push(format!("[{:}] {:} {:?} {:} evaded ({:}%)",
cast.resolution.speed, source.name, cast.skill, target.name, evasion_rating)), cast.speed, source.name, cast.skill, target.name, evasion_rating)),
Event::Incomplete => panic!("incomplete resolution {:?}", resolution),
} }
} }

View File

@ -8,11 +8,12 @@ use game::{Game};
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub struct Cast { pub struct Cast {
pub id: Uuid, pub id: Uuid,
pub skill: Skill,
pub source_team_id: Uuid, pub source_team_id: Uuid,
pub source_cryp_id: Uuid, pub source_cryp_id: Uuid,
pub target_cryp_id: Uuid, pub target_cryp_id: Uuid,
pub resolution: Resolution, pub skill: Skill,
pub speed: u64,
pub resolutions: Resolutions,
} }
impl Cast { impl Cast {
@ -23,7 +24,8 @@ impl Cast {
source_team_id, source_team_id,
target_cryp_id, target_cryp_id,
skill, skill,
resolution: Resolution::new(skill), speed: 0,
resolutions: vec![],
}; };
} }
@ -34,7 +36,7 @@ impl Cast {
pub fn finalise(&mut self, game: &mut Game) -> &mut Cast { pub fn finalise(&mut self, game: &mut Game) -> &mut Cast {
let mut results = vec![]; let mut results = vec![];
let mut source = game.cryp_by_id(self.source_cryp_id).unwrap().clone(); let mut source = game.cryp_by_id(self.source_cryp_id).unwrap().clone();
self.resolution.speed = source.skill_speed(self.skill); self.speed = source.skill_speed(self.skill);
let targets = match source.skill_is_aoe(self.skill) { let targets = match source.skill_is_aoe(self.skill) {
true => game.cryp_aoe_targets(self.target_cryp_id), true => game.cryp_aoe_targets(self.target_cryp_id),
@ -47,7 +49,7 @@ impl Cast {
results.append(&mut self.skill.resolve(&mut source, target)); results.append(&mut self.skill.resolve(&mut source, target));
} }
self.resolution.results = results; self.resolutions = results;
self self
} }
@ -60,7 +62,36 @@ pub type Disable = Vec<Effect>;
pub type Immunity = Vec<Effect>; pub type Immunity = Vec<Effect>;
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub enum ResolutionResult { pub struct LogCryp {
pub id: Uuid,
pub name: String,
}
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub struct Resolution {
pub source: LogCryp,
pub target: LogCryp,
pub event: Event,
}
impl Resolution {
fn new(source: &Cryp, target: &Cryp) -> Resolution {
Resolution {
source: LogCryp { id: source.id, name: source.name.clone() },
target: LogCryp { id: target.id, name: target.name.clone() },
event: Event::Incomplete,
}
}
fn event(mut self, e: Event) -> Resolution {
self.event = e;
self
}
}
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub enum Event {
TargetKo, TargetKo,
Disable { disable: Disable }, Disable { disable: Disable },
Immunity { immunity: Immunity }, Immunity { immunity: Immunity },
@ -71,21 +102,11 @@ pub enum ResolutionResult {
Effect { effect: Effect, duration: u8 }, Effect { effect: Effect, duration: u8 },
Removal { effect: Effect }, Removal { effect: Effect },
Evasion { skill: Skill, evasion_rating: u64 }, Evasion { skill: Skill, evasion_rating: u64 },
Incomplete,
} }
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] type Resolutions = Vec<Resolution>;
pub struct Resolution {
pub skill: Skill,
pub speed: u64,
pub results: Vec<ResolutionResult>,
}
impl Resolution {
fn new(skill: Skill) -> Resolution {
Resolution { skill, results: vec![], speed: 0 }
}
}
pub type Cooldown = Option<u8>; pub type Cooldown = Option<u8>;
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
@ -579,14 +600,14 @@ impl Skill {
} }
} }
pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp) -> Vec<ResolutionResult> { pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp) -> Resolutions {
let mut rng = thread_rng(); let mut rng = thread_rng();
let _base: u64 = rng.gen(); let _base: u64 = rng.gen();
let mut results = vec![]; let mut results = vec![];
if let Some(disable) = source.disabled(*self) { if let Some(disable) = source.disabled(*self) {
results.push(ResolutionResult::Disable { disable }); results.push(Resolution::new(source, target).event(Event::Disable { disable }));
return results; return results;
} }
@ -594,14 +615,14 @@ impl Skill {
// true => { // true => {
// if let Some(evasion) = target.evade(*self) { // if let Some(evasion) = target.evade(*self) {
// results.push(evasion); // results.push(evasion);
// return resolution; // return Event;
// } // }
// }, // },
// false => (), // false => (),
// } // }
if target.is_ko() { if target.is_ko() {
results.push(ResolutionResult::TargetKo); results.push(Resolution::new(source, target).event(Event::TargetKo));
return results; return results;
} }
@ -687,197 +708,198 @@ impl Skill {
} }
} }
fn attack(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn attack(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amount = cryp.red_damage(); let amount = source.red_damage();
results.push(target.deal_red_damage(Skill::Attack, amount)); results.push(Resolution::new(source, target).event(target.deal_red_damage(Skill::Attack, amount)));
return results; return results;
} }
fn stun(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn stun(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let effect = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None };
results.push(target.add_effect(Skill::Stun, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Stun, effect)));
return results; return results;
} }
fn clutch(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn clutch(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let effect = CrypEffect { effect: Effect::Clutch, duration: Effect::Clutch.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Clutch, duration: Effect::Clutch.duration(), tick: None };
results.push(target.add_effect(Skill::Clutch, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Clutch, effect)));
return results; return results;
} }
fn throw(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn throw(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
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 };
results.push(target.add_effect(Skill::Throw, stun)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Throw, stun)));
results.push(target.add_effect(Skill::Throw, vulnerable)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Throw, vulnerable)));
return results; return results;
} }
fn strangle(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn strangle(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let target_stun = CrypEffect { let target_stun = CrypEffect {
effect: Effect::Strangle, effect: Effect::Strangle,
duration: Effect::Strangle.duration(), duration: Effect::Strangle.duration(),
tick: Some(Cast::new_tick(cryp, target, Skill::StrangleTick)) tick: Some(Cast::new_tick(source, target, Skill::StrangleTick))
}; };
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 };
results.push(target.add_effect(Skill::Strangle, target_stun)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Strangle, target_stun)));
results.push(cryp.add_effect(Skill::Strangle, attacker_immunity)); results.push(Resolution::new(source, source).event(source.add_effect(Skill::Strangle, attacker_immunity)));
return strangle_tick(cryp, target, results); return strangle_tick(source, target, results);
} }
fn strangle_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn strangle_tick(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amount = cryp.red_damage(); let amount = source.red_damage();
results.push(target.deal_red_damage(Skill::StrangleTick, amount)); results.push(Resolution::new(source, target).event(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() {
let i = cryp.effects let i = source.effects
.iter() .iter()
.position(|e| e.effect == Effect::Strangling) .position(|e| e.effect == Effect::Strangling)
.expect("no strangling on cryp"); .expect("no strangling on cryp");
cryp.effects.remove(i); source.effects.remove(i);
results.push(Resolution::new(source, source).event(Event::Removal { effect: Effect::Strangling }));
} }
return results; return results;
} }
fn block(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn block(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let block = CrypEffect { effect: Effect::Block, duration: Effect::Block.duration(), tick: None }; let block = CrypEffect { effect: Effect::Block, duration: Effect::Block.duration(), tick: None };
results.push(target.add_effect(Skill::Block, block)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Block, block)));
return results; return results;
} }
fn parry(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn parry(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let effect = CrypEffect { effect: Effect::Parry, duration: Effect::Parry.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Parry, duration: Effect::Parry.duration(), tick: None };
results.push(target.add_effect(Skill::Parry, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Parry, effect)));
return results; return results;
} }
fn snare(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn snare(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let snare = CrypEffect { effect: Effect::Snare, duration: Effect::Snare.duration(), tick: None }; let snare = CrypEffect { effect: Effect::Snare, duration: Effect::Snare.duration(), tick: None };
results.push(target.add_effect(Skill::Snare, snare)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Snare, snare)));
return results; return results;
} }
fn empower(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn empower(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let empower = CrypEffect { effect: Effect::Empower, duration: Effect::Empower.duration(), tick: None }; let empower = CrypEffect { effect: Effect::Empower, duration: Effect::Empower.duration(), tick: None };
results.push(target.add_effect(Skill::Empower, empower)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Empower, empower)));
return results; return results;
} }
fn heal(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn heal(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amount = cryp.green_damage(); let amount = source.green_damage();
results.push(target.deal_green_damage(Skill::Heal, amount)); results.push(Resolution::new(source, target).event(target.deal_green_damage(Skill::Heal, amount)));
return results; return results;
} }
fn triage(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn triage(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
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(source, target, Skill::TriageTick)),
}; };
results.push(target.add_effect(Skill::Triage, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Triage, effect)));
return triage_tick(cryp, target, results); return triage_tick(source, target, results);
} }
fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn triage_tick(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amount = cryp.blue_damage().wrapping_div(2); let amount = source.green_damage().wrapping_div(2);
results.push(target.deal_green_damage(Skill::TriageTick, amount)); results.push(Resolution::new(source, target).event(target.deal_green_damage(Skill::TriageTick, amount)));
return results; return results;
} }
fn blast(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn blast(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amount = cryp.blue_damage(); let amount = source.blue_damage();
results.push(target.deal_blue_damage(Skill::Blast, amount)); results.push(Resolution::new(source, target).event(target.deal_blue_damage(Skill::Blast, amount)));
return results; return results;
} }
fn amplify(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn amplify(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amplify = CrypEffect { effect: Effect::Amplify, duration: Effect::Amplify.duration(), tick: None }; let amplify = CrypEffect { effect: Effect::Amplify, duration: Effect::Amplify.duration(), tick: None };
results.push(target.add_effect(Skill::Amplify, amplify)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Amplify, amplify)));
return results;; return results;;
} }
fn haste(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn haste(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let effect = CrypEffect { effect: Effect::Haste, duration: Effect::Haste.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Haste, duration: Effect::Haste.duration(), tick: None };
results.push(target.add_effect(Skill::Haste, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Haste, effect)));
return results;; return results;;
} }
fn slow(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn slow(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let effect = CrypEffect { effect: Effect::Slow, duration: Effect::Slow.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Slow, duration: Effect::Slow.duration(), tick: None };
results.push(target.add_effect(Skill::Slow, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Slow, effect)));
return results;; return results;;
} }
fn decay(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn decay(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
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(source, target, Skill::DecayTick)),
}; };
results.push(target.add_effect(Skill::Decay, decay)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Decay, decay)));
return decay_tick(cryp, target, results); return decay_tick(source, target, results);
} }
fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn decay_tick(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amount = cryp.blue_damage(); let amount = source.blue_damage();
results.push(target.deal_blue_damage(Skill::DecayTick, amount)); results.push(Resolution::new(source, target).event(target.deal_blue_damage(Skill::DecayTick, amount)));
return results; return results;
} }
fn hex(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn hex(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let hex = CrypEffect { effect: Effect::Hex, duration: Effect::Hex.duration(), tick: None }; let hex = CrypEffect { effect: Effect::Hex, duration: Effect::Hex.duration(), tick: None };
results.push(target.add_effect(Skill::Hex, hex)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Hex, hex)));
return results;; return results;;
} }
fn curse(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn curse(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let curse = CrypEffect { effect: Effect::Curse, duration: Effect::Curse.duration(), tick: None }; let curse = CrypEffect { effect: Effect::Curse, duration: Effect::Curse.duration(), tick: None };
results.push(target.add_effect(Skill::Curse, curse)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Curse, curse)));
return results;; return results;;
} }
fn invert(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn invert(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let effect = CrypEffect { effect: Effect::Invert, duration: Effect::Invert.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Invert, duration: Effect::Invert.duration(), tick: None };
results.push(target.add_effect(Skill::Invert, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Invert, effect)));
return results;; return results;;
} }
fn reflect(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn reflect(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let effect = CrypEffect { effect: Effect::Reflect, duration: Effect::Reflect.duration(), tick: None }; let effect = CrypEffect { effect: Effect::Reflect, duration: Effect::Reflect.duration(), tick: None };
results.push(target.add_effect(Skill::Reflect, effect)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Reflect, effect)));
return results;; return results;;
} }
fn recharge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn recharge(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
results.push(target.recharge()); results.push(Resolution::new(source, target).event(target.recharge()));
return results; return results;
} }
fn siphon(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn siphon(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
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(source, target, Skill::SiphonTick)),
}; };
results.push(target.add_effect(Skill::Siphon, siphon)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Siphon, siphon)));
return siphon_tick(cryp, target, results); return siphon_tick(source, target, results);
} }
fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn siphon_tick(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let amount = cryp.blue_damage(); let amount = source.blue_damage();
let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount); let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount);
results.push(siphon_damage.clone()); results.push(Resolution::new(source, target).event(siphon_damage.clone()));
match siphon_damage { match siphon_damage {
ResolutionResult::Damage { amount, mitigation: _, category: _, } => { Event::Damage { amount, mitigation: _, category: _, } => {
results.push(cryp.deal_green_damage(Skill::Heal, amount)); results.push(Resolution::new(source, source).event(source.deal_green_damage(Skill::Heal, amount)));
}, },
_ => panic!("siphon tick damage not dealt {:?}", siphon_damage), _ => panic!("siphon tick damage not dealt {:?}", siphon_damage),
} }
@ -885,49 +907,49 @@ fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionRe
return results; return results;
} }
fn shield(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn shield(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let shield = CrypEffect { effect: Effect::Shield, duration: Effect::Shield.duration(), tick: None }; let shield = CrypEffect { effect: Effect::Shield, duration: Effect::Shield.duration(), tick: None };
results.push(target.add_effect(Skill::Shield, shield)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Shield, shield)));
return results; return results;
} }
fn silence(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn silence(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let silence = CrypEffect { effect: Effect::Silence, duration: Effect::Silence.duration(), tick: None }; let silence = CrypEffect { effect: Effect::Silence, duration: Effect::Silence.duration(), tick: None };
results.push(target.add_effect(Skill::Silence, silence)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Silence, silence)));
return results; return results;
} }
fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn purge(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
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);
results.push(ResolutionResult::Removal { effect: ce.effect }); results.push(Resolution::new(source, target).event(Event::Removal { effect: ce.effect }));
} }
} }
return results; return results;
} }
fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn purify(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
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);
results.push(ResolutionResult::Removal { effect: ce.effect }); results.push(Resolution::new(source, target).event(Event::Removal { effect: ce.effect }));
} }
} }
return results; return results;
} }
fn banish(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn banish(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let banish = CrypEffect { effect: Effect::Banish, duration: Effect::Banish.duration(), tick: None }; let banish = CrypEffect { effect: Effect::Banish, duration: Effect::Banish.duration(), tick: None };
results.push(target.add_effect(Skill::Banish, banish)); results.push(Resolution::new(source, target).event(target.add_effect(Skill::Banish, banish)));
return results; return results;
} }
fn strike(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> { fn strike(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
let _amount = cryp.red_damage(); let _amount = source.red_damage();
results.push(target.deal_red_damage(Skill::Attack, u64::max_value())); results.push(Resolution::new(source, target).event(target.deal_red_damage(Skill::Attack, u64::max_value())));
return results; return results;
} }
@ -984,10 +1006,11 @@ mod tests {
block(&mut y.clone(), &mut y, vec![]); 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 results = attack(&mut x, &mut y, vec![]); let mut results = attack(&mut x, &mut y, vec![]);
match results[0] { let Resolution { source: _, target: _, event } = results.remove(0);
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 50), match event {
Event::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 50),
_ => panic!("not damage"), _ => panic!("not damage"),
}; };
} }
@ -1005,11 +1028,12 @@ mod tests {
clutch(&mut y.clone(), &mut y, vec![]); clutch(&mut y.clone(), &mut y, vec![]);
assert!(y.is_clutch()); assert!(y.is_clutch());
let results = attack(&mut x, &mut y, vec![]); let mut results = attack(&mut x, &mut y, vec![]);
assert!(y.hp() == 1); assert!(y.hp() == 1);
match results[0] { let Resolution { source: _, target: _, event } = results.remove(0);
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 1023), match event {
Event::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 1023),
_ => panic!("not damage"), _ => panic!("not damage"),
}; };
} }
@ -1035,11 +1059,12 @@ mod tests {
assert!(y.hp() == 768); assert!(y.hp() == 768);
// attack should heal and recharge red shield // attack should heal and recharge red shield
let results = attack(&mut x, &mut y, vec![]); let mut results = attack(&mut x, &mut y, vec![]);
assert!(y.hp() == 1024); assert!(y.hp() == 1024);
match results[0] { let Resolution { source: _, target: _, event } = results.remove(0);
ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _ } => assert_eq!(recharge, 64), match event {
Event::Inversion { damage: _, healing: _, recharge, category: _ } => assert_eq!(recharge, 64),
_ => panic!("not inversion"), _ => panic!("not inversion"),
}; };
} }
@ -1055,12 +1080,13 @@ mod tests {
reflect(&mut y.clone(), &mut y, vec![]); reflect(&mut y.clone(), &mut y, vec![]);
assert!(y.is_reflecting()); assert!(y.is_reflecting());
let results = Skill::Attack.resolve(&mut x, &mut y); let mut results = Skill::Attack.resolve(&mut x, &mut y);
assert!(x.hp() == 768); assert!(x.hp() == 768);
match results[0] { let Resolution { source: _, target: _, event } = results.remove(0);
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256), match event {
Event::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256),
_ => panic!("not damage"), _ => panic!("not damage"),
}; };
} }
@ -1083,7 +1109,7 @@ 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 results = triage(&mut x, &mut y, vec![]); let _results = triage(&mut x, &mut y, vec![]);
assert!(y.effects.iter().any(|e| e.effect == Effect::Triage)); assert!(y.effects.iter().any(|e| e.effect == Effect::Triage));
assert!(y.hp() > prev_hp); assert!(y.hp() > prev_hp);
@ -1103,10 +1129,11 @@ 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 results = recharge(&mut x, &mut y, vec![]); let mut results = recharge(&mut x, &mut y, vec![]);
match results[0] { let Resolution { source: _, target: _, event } = results.remove(0);
ResolutionResult::Recharge { red, blue } => { match event {
Event::Recharge { red, blue } => {
assert!(red == 5); assert!(red == 5);
assert!(blue == 5); assert!(blue == 5);
} }