Merge branch 'resolution-steps'
This commit is contained in:
commit
bffba488d8
@ -64,6 +64,7 @@ impl CrypSkill {
|
|||||||
pub enum EffectMeta {
|
pub enum EffectMeta {
|
||||||
TickAmount(u64),
|
TickAmount(u64),
|
||||||
AddedDamage(u64),
|
AddedDamage(u64),
|
||||||
|
ScatterTarget(Uuid),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
@ -470,7 +471,7 @@ impl Cryp {
|
|||||||
.fold(self.speed.value, |acc, fx| fx.0.apply(acc, fx.1));
|
.fold(self.speed.value, |acc, fx| fx.0.apply(acc, fx.1));
|
||||||
return modified_speed;
|
return modified_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn red_life(&self) -> u64 {
|
pub fn red_life(&self) -> u64 {
|
||||||
self.red_life.value
|
self.red_life.value
|
||||||
}
|
}
|
||||||
@ -563,6 +564,11 @@ impl Cryp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.is_ko() {
|
||||||
|
events.push(Event::Ko { skill });
|
||||||
|
self.effects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,6 +642,12 @@ impl Cryp {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.is_ko() {
|
||||||
|
events.push(Event::Ko { skill });
|
||||||
|
self.effects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,6 +717,11 @@ impl Cryp {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.is_ko() {
|
||||||
|
events.push(Event::Ko { skill });
|
||||||
|
self.effects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,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, Effect, Cast, Resolution, Event, resolve};
|
use skill::{Skill, Effect, Cast, Resolution, Event, resolution_steps};
|
||||||
use player::{Player};
|
use player::{Player};
|
||||||
use instance::{instance_game_finished, global_game_finished};
|
use instance::{instance_game_finished, global_game_finished};
|
||||||
use util::{IntPct};
|
use util::{IntPct};
|
||||||
@ -133,7 +133,7 @@ impl Game {
|
|||||||
.collect::<Vec<Cryp>>()
|
.collect::<Vec<Cryp>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_cryp(&mut self, cryp: &mut Cryp) -> &mut Game {
|
pub fn update_cryp(&mut self, cryp: &mut Cryp) -> &mut Game {
|
||||||
match self.players.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == cryp.id)) {
|
match self.players.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == cryp.id)) {
|
||||||
Some(player) => {
|
Some(player) => {
|
||||||
let index = player.cryps.iter().position(|t| t.id == cryp.id).unwrap();
|
let index = player.cryps.iter().position(|t| t.id == cryp.id).unwrap();
|
||||||
@ -373,7 +373,7 @@ impl Game {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_targets(&self, skill: Skill, source: &Cryp, target_cryp_id: Uuid) -> Vec<Uuid> {
|
pub fn get_targets(&self, skill: Skill, source: &Cryp, target_cryp_id: Uuid) -> Vec<Uuid> {
|
||||||
let target_player = self.players.iter()
|
let target_player = self.players.iter()
|
||||||
.find(|t| t.cryps.iter().any(|c| c.id == target_cryp_id))
|
.find(|t| t.cryps.iter().any(|c| c.id == target_cryp_id))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -415,19 +415,7 @@ impl Game {
|
|||||||
while let Some(cast) = self.stack.pop() {
|
while let Some(cast) = self.stack.pop() {
|
||||||
// println!("{:} casts ", cast);
|
// println!("{:} casts ", cast);
|
||||||
|
|
||||||
let mut resolutions = vec![];
|
let mut resolutions = resolution_steps(&cast, &mut self);
|
||||||
let mut source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone();
|
|
||||||
|
|
||||||
let targets = self.get_targets(cast.skill, &source, cast.target_cryp_id);
|
|
||||||
for target_id in targets {
|
|
||||||
let mut source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone();
|
|
||||||
let mut target = self.cryp_by_id(target_id).unwrap().clone();
|
|
||||||
resolutions = resolve(cast.skill, &mut source, &mut target, resolutions);
|
|
||||||
// save the clones
|
|
||||||
self.update_cryp(&mut source);
|
|
||||||
self.update_cryp(&mut target);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolutions.reverse();
|
resolutions.reverse();
|
||||||
while let Some(resolution) = resolutions.pop() {
|
while let Some(resolution) = resolutions.pop() {
|
||||||
self.log_resolution(cast.speed, &resolution);
|
self.log_resolution(cast.speed, &resolution);
|
||||||
@ -1175,9 +1163,124 @@ mod tests {
|
|||||||
// should not be stunned because of parry
|
// should not be stunned because of parry
|
||||||
assert!(game.player_by_id(x_player.id).unwrap().cryps[0].is_stunned() == false);
|
assert!(game.player_by_id(x_player.id).unwrap().cryps[0].is_stunned() == false);
|
||||||
// riposte
|
// riposte
|
||||||
assert!(game.player_by_id(y_player.id).unwrap().cryps[0].green_life() == (1024 - x_cryp.red_damage().pct(Skill::Riposte.multiplier())));
|
assert_eq!(game.player_by_id(y_player.id).unwrap().cryps[0].green_life(), (1024 - x_cryp.red_damage().pct(Skill::Riposte.multiplier())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn corrupt_test() {
|
||||||
|
let mut game = create_test_game();
|
||||||
|
|
||||||
|
let x_player = game.players[0].clone();
|
||||||
|
let y_player = game.players[1].clone();
|
||||||
|
|
||||||
|
let x_cryp = x_player.cryps[0].clone();
|
||||||
|
let y_cryp = y_player.cryps[0].clone();
|
||||||
|
|
||||||
|
game.cryp_by_id(x_cryp.id).unwrap().learn_mut(Skill::Corrupt);
|
||||||
|
|
||||||
|
while game.cryp_by_id(x_cryp.id).unwrap().skill_on_cd(Skill::Corrupt).is_some() {
|
||||||
|
game.cryp_by_id(x_cryp.id).unwrap().reduce_cooldowns();
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply buff
|
||||||
|
game.add_skill(x_player.id, x_cryp.id, None, Skill::Corrupt).unwrap();
|
||||||
|
game.player_ready(x_player.id).unwrap();
|
||||||
|
game.player_ready(y_player.id).unwrap();
|
||||||
|
game = game.resolve_phase_start();
|
||||||
|
assert!(game.cryp_by_id(x_cryp.id).unwrap().affected(Effect::Corrupt));
|
||||||
|
|
||||||
|
// attack and receive debuff
|
||||||
|
game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
||||||
|
game.player_ready(x_player.id).unwrap();
|
||||||
|
game.player_ready(y_player.id).unwrap();
|
||||||
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
|
assert!(game.cryp_by_id(y_cryp.id).unwrap().affected(Effect::Corruption));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scatter_test() {
|
||||||
|
let mut game = create_test_game();
|
||||||
|
|
||||||
|
let x_player = game.players[0].clone();
|
||||||
|
let y_player = game.players[1].clone();
|
||||||
|
|
||||||
|
let x_cryp = x_player.cryps[0].clone();
|
||||||
|
let y_cryp = y_player.cryps[0].clone();
|
||||||
|
|
||||||
|
game.cryp_by_id(x_cryp.id).unwrap().learn_mut(Skill::Scatter);
|
||||||
|
|
||||||
|
while game.cryp_by_id(x_cryp.id).unwrap().skill_on_cd(Skill::Scatter).is_some() {
|
||||||
|
game.cryp_by_id(x_cryp.id).unwrap().reduce_cooldowns();
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply buff
|
||||||
|
game.add_skill(x_player.id, x_cryp.id, Some(y_cryp.id), Skill::Scatter).unwrap();
|
||||||
|
game.player_ready(x_player.id).unwrap();
|
||||||
|
game.player_ready(y_player.id).unwrap();
|
||||||
|
game = game.resolve_phase_start();
|
||||||
|
assert!(game.cryp_by_id(x_cryp.id).unwrap().affected(Effect::Scatter));
|
||||||
|
|
||||||
|
let Resolution { source: _, target: _, event } = game.resolved.pop().unwrap();
|
||||||
|
match event {
|
||||||
|
Event::Effect { effect, skill: _, duration: _ } => assert_eq!(effect, Effect::Scatter),
|
||||||
|
_ => panic!("not siphon"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let Resolution { source: _, target: _, event } = game.resolved.pop().unwrap();
|
||||||
|
match event {
|
||||||
|
Event::Recharge { red: _, blue: _, skill: _ } => (),
|
||||||
|
_ => panic!("scatter result was not recharge"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// attack and receive scatter hit
|
||||||
|
game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();
|
||||||
|
game.player_ready(x_player.id).unwrap();
|
||||||
|
game.player_ready(y_player.id).unwrap();
|
||||||
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
|
let Resolution { source: _, target, event } = game.resolved.pop().unwrap();
|
||||||
|
assert_eq!(target.id, y_cryp.id);
|
||||||
|
match event {
|
||||||
|
Event::Damage { amount, skill: _, mitigation: _, colour: _} =>
|
||||||
|
assert_eq!(amount, 256.pct(Skill::Attack.multiplier()) >> 1),
|
||||||
|
_ => panic!("not damage scatter"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn hatred_test() {
|
||||||
|
// let mut game = create_test_game();
|
||||||
|
|
||||||
|
// let x_player = game.players[0].clone();
|
||||||
|
// let y_player = game.players[1].clone();
|
||||||
|
|
||||||
|
// let x_cryp = x_player.cryps[0].clone();
|
||||||
|
// let y_cryp = y_player.cryps[0].clone();
|
||||||
|
|
||||||
|
// game.cryp_by_id(x_cryp.id).unwrap().learn_mut(Skill::Hostility);
|
||||||
|
|
||||||
|
// while game.cryp_by_id(x_cryp.id).unwrap().skill_on_cd(Skill::Hostility).is_some() {
|
||||||
|
// game.cryp_by_id(x_cryp.id).unwrap().reduce_cooldowns();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // apply buff
|
||||||
|
// game.add_skill(x_player.id, x_cryp.id, Some(x_cryp.id), Skill::Hostility).unwrap();
|
||||||
|
// game.player_ready(x_player.id).unwrap();
|
||||||
|
// game.player_ready(y_player.id).unwrap();
|
||||||
|
// game = game.resolve_phase_start();
|
||||||
|
// assert!(game.cryp_by_id(x_cryp.id).unwrap().affected(Effect::Hostility));
|
||||||
|
|
||||||
|
// // attack and receive debuff
|
||||||
|
// game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::TestAttack).unwrap();
|
||||||
|
// game.player_ready(x_player.id).unwrap();
|
||||||
|
// game.player_ready(y_player.id).unwrap();
|
||||||
|
// game = game.resolve_phase_start();
|
||||||
|
|
||||||
|
// println!("{:#?}", game);
|
||||||
|
// assert!(game.cryp_by_id(y_cryp.id).unwrap().affected(Effect::Hatred));
|
||||||
|
// }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn aoe_test() {
|
fn aoe_test() {
|
||||||
let mut game = create_2v2_test_game();
|
let mut game = create_2v2_test_game();
|
||||||
|
|||||||
@ -5,6 +5,37 @@ use util::{IntPct};
|
|||||||
use cryp::{Cryp, CrypEffect, EffectMeta, Stat};
|
use cryp::{Cryp, CrypEffect, EffectMeta, Stat};
|
||||||
use vbox::{Var};
|
use vbox::{Var};
|
||||||
|
|
||||||
|
use game::{Game};
|
||||||
|
|
||||||
|
pub fn resolution_steps(cast: &Cast, game: &mut Game) -> Resolutions {
|
||||||
|
let mut resolutions = vec![];
|
||||||
|
|
||||||
|
resolutions = pre_resolve(cast, game, resolutions);
|
||||||
|
|
||||||
|
return resolutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pre_resolve(cast: &Cast, game: &mut Game, mut resolutions: Resolutions) -> Resolutions {
|
||||||
|
let skill = cast.skill;
|
||||||
|
let source = game.cryp_by_id(cast.source_cryp_id).unwrap().clone();
|
||||||
|
let targets = game.get_targets(cast.skill, &source, cast.target_cryp_id);
|
||||||
|
|
||||||
|
for target_id in targets {
|
||||||
|
let mut source = game.cryp_by_id(cast.source_cryp_id).unwrap().clone();
|
||||||
|
let mut target = game.cryp_by_id(target_id).unwrap().clone();
|
||||||
|
resolutions = resolve(cast.skill, &mut source, &mut target, resolutions);
|
||||||
|
|
||||||
|
// save the clones
|
||||||
|
game.update_cryp(&mut source);
|
||||||
|
game.update_cryp(&mut target);
|
||||||
|
|
||||||
|
// do additional steps
|
||||||
|
resolutions = post_resolve(cast.skill, game, resolutions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolutions;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolve(skill: Skill, source: &mut Cryp, target: &mut Cryp, mut resolutions: Vec<Resolution>) -> Resolutions {
|
pub fn resolve(skill: Skill, source: &mut Cryp, target: &mut Cryp, mut resolutions: Vec<Resolution>) -> Resolutions {
|
||||||
if let Some(disable) = source.disabled(skill) {
|
if let Some(disable) = source.disabled(skill) {
|
||||||
resolutions.push(Resolution::new(source, target).event(Event::Disable { disable, skill }));
|
resolutions.push(Resolution::new(source, target).event(Event::Disable { disable, skill }));
|
||||||
@ -126,36 +157,43 @@ pub fn resolve(skill: Skill, source: &mut Cryp, target: &mut Cryp, mut resolutio
|
|||||||
Skill::TestSiphon => siphon(source, target, resolutions, Skill::Siphon),
|
Skill::TestSiphon => siphon(source, target, resolutions, Skill::Siphon),
|
||||||
};
|
};
|
||||||
|
|
||||||
// if any event dealt damage to target cryp
|
return resolutions;
|
||||||
// hit them with corruption
|
}
|
||||||
|
|
||||||
// on damage events
|
fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) -> Resolutions {
|
||||||
// todo not sure if this fucks up with multiple calls to resolve
|
for Resolution { source, target, event } in resolutions.clone() {
|
||||||
// have to think
|
let mut source = game.cryp_by_id(source.id).unwrap().clone();
|
||||||
for r in resolutions.clone() {
|
let mut target = game.cryp_by_id(target.id).unwrap().clone();
|
||||||
match r.event {
|
|
||||||
|
match event {
|
||||||
Event::Damage { amount, skill, mitigation: _, colour: _ } => {
|
Event::Damage { amount, skill, mitigation: _, colour: _ } => {
|
||||||
if target.affected(Effect::Corrupt) {
|
if target.affected(Effect::Corrupt) {
|
||||||
resolutions = corruption(target, source, resolutions, Skill::Corrupt);
|
resolutions = corruption(&mut target, &mut source, resolutions, Skill::Corrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.affected(Effect::Hostility) {
|
if target.affected(Effect::Hostility) {
|
||||||
resolutions = hatred(source, target, resolutions, skill, amount, Skill::Hostility);
|
resolutions = hatred(&mut source, &mut target, resolutions, skill, amount, Skill::Hostility);
|
||||||
|
}
|
||||||
|
|
||||||
|
// beware that scatter doesn't cause any damage
|
||||||
|
// because then applying it will proc this
|
||||||
|
if target.affected(Effect::Scatter) {
|
||||||
|
resolutions = scatter_hit(&source, &target, resolutions, game, event)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Event::Immunity { skill: _, immunity } => match immunity.contains(&Effect::Parry) {
|
Event::Immunity { skill: _, immunity } => match immunity.contains(&Effect::Parry) {
|
||||||
true => resolutions = riposte(target, source, resolutions, Skill::Riposte),
|
true => {
|
||||||
|
resolutions = riposte(&mut target, &mut source, resolutions, Skill::Riposte);
|
||||||
|
}
|
||||||
false => (),
|
false => (),
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// i don't think we need to check the source being ko
|
game.update_cryp(&mut source);
|
||||||
if target.is_ko() {
|
game.update_cryp(&mut target);
|
||||||
resolutions.push(Resolution::new(source, target).event(Event::Ko { skill }));
|
};
|
||||||
target.effects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolutions;
|
return resolutions;
|
||||||
}
|
}
|
||||||
@ -381,6 +419,8 @@ impl Effect {
|
|||||||
Effect::Haste => vec![Stat::Speed],
|
Effect::Haste => vec![Stat::Speed],
|
||||||
Effect::Slow => vec![Stat::Speed],
|
Effect::Slow => vec![Stat::Speed],
|
||||||
|
|
||||||
|
Effect::Scatter => vec![Stat::BlueDamageTaken, Stat::GreenDamageTaken, Stat::RedDamageTaken],
|
||||||
|
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,6 +439,8 @@ impl Effect {
|
|||||||
Effect::Impurity => value.pct(150),
|
Effect::Impurity => value.pct(150),
|
||||||
Effect::Wither => value.pct(50),
|
Effect::Wither => value.pct(50),
|
||||||
|
|
||||||
|
Effect::Scatter => value >> 1,
|
||||||
|
|
||||||
Effect::Hatred => value + match meta {
|
Effect::Hatred => value + match meta {
|
||||||
Some(EffectMeta::AddedDamage(d)) => d,
|
Some(EffectMeta::AddedDamage(d)) => d,
|
||||||
_ => panic!("hatred meta not damage"),
|
_ => panic!("hatred meta not damage"),
|
||||||
@ -452,7 +494,7 @@ impl Effect {
|
|||||||
|
|
||||||
Effect::Hostility => Category::Buff,
|
Effect::Hostility => Category::Buff,
|
||||||
|
|
||||||
// magic
|
// magic
|
||||||
Effect::Impurity => Category::Buff,
|
Effect::Impurity => Category::Buff,
|
||||||
Effect::Scatter => Category::Buff,
|
Effect::Scatter => Category::Buff,
|
||||||
Effect::Invert => Category::Buff,
|
Effect::Invert => Category::Buff,
|
||||||
@ -585,7 +627,7 @@ impl Skill {
|
|||||||
match self {
|
match self {
|
||||||
// Attack Base
|
// Attack Base
|
||||||
Skill::Attack => 80, // Base
|
Skill::Attack => 80, // Base
|
||||||
|
|
||||||
Skill::Blast => 110, // BB
|
Skill::Blast => 110, // BB
|
||||||
Skill::Chaos => 40, // BR
|
Skill::Chaos => 40, // BR
|
||||||
Skill::Heal => 130, //GG
|
Skill::Heal => 130, //GG
|
||||||
@ -600,7 +642,7 @@ impl Skill {
|
|||||||
Skill::Purify => 45, //Green dmg (heal)
|
Skill::Purify => 45, //Green dmg (heal)
|
||||||
Skill::Recharge => 85, //restore red and blue life (heal)
|
Skill::Recharge => 85, //restore red and blue life (heal)
|
||||||
Skill::Reflect => 45, //restore blue life (heal)
|
Skill::Reflect => 45, //restore blue life (heal)
|
||||||
|
|
||||||
Skill::Parry => 110,
|
Skill::Parry => 110,
|
||||||
Skill::Riposte => 70,
|
Skill::Riposte => 70,
|
||||||
|
|
||||||
@ -618,7 +660,7 @@ impl Skill {
|
|||||||
Skill::HasteStrike => 30,
|
Skill::HasteStrike => 30,
|
||||||
Skill::Taunt => 80,
|
Skill::Taunt => 80,
|
||||||
Skill::TriageTick => 75,
|
Skill::TriageTick => 75,
|
||||||
|
Skill::Scatter => 140,
|
||||||
|
|
||||||
_ => 100,
|
_ => 100,
|
||||||
}
|
}
|
||||||
@ -783,7 +825,7 @@ impl Skill {
|
|||||||
Skill::Impurity => Category::Green,
|
Skill::Impurity => Category::Green,
|
||||||
Skill::Invert => Category::Green,
|
Skill::Invert => Category::Green,
|
||||||
Skill::Sleep => Category::Green,
|
Skill::Sleep => Category::Green,
|
||||||
|
|
||||||
Skill::ImpureBlast => Category::Blue,
|
Skill::ImpureBlast => Category::Blue,
|
||||||
Skill::Scatter => Category::Blue,
|
Skill::Scatter => Category::Blue,
|
||||||
Skill::Blast => Category::Blue,
|
Skill::Blast => Category::Blue,
|
||||||
@ -1035,7 +1077,7 @@ fn riposte(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill
|
|||||||
fn snare(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn snare(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
let snare = CrypEffect::new(Effect::Snare, skill.duration());
|
let snare = CrypEffect::new(Effect::Snare, skill.duration());
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, snare)));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, snare)));
|
||||||
|
|
||||||
let s_multi = target.skills
|
let s_multi = target.skills
|
||||||
.iter()
|
.iter()
|
||||||
.fold(100, |acc, cs| match cs.skill.category() {
|
.fold(100, |acc, cs| match cs.skill.category() {
|
||||||
@ -1043,7 +1085,6 @@ fn snare(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill:
|
|||||||
_ => acc,
|
_ => acc,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let amount = source.red_damage().pct(skill.multiplier()).pct(s_multi);
|
let amount = source.red_damage().pct(skill.multiplier()).pct(s_multi);
|
||||||
target.deal_red_damage(skill, amount)
|
target.deal_red_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -1142,7 +1183,7 @@ fn decay(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill:
|
|||||||
let wither = CrypEffect::new(Effect::Wither, skill.duration());
|
let wither = CrypEffect::new(Effect::Wither, skill.duration());
|
||||||
let decay = CrypEffect::new(Effect::Decay, skill.duration())
|
let decay = CrypEffect::new(Effect::Decay, skill.duration())
|
||||||
.set_tick(Cast::new_tick(source, target, Skill::DecayTick));
|
.set_tick(Cast::new_tick(source, target, Skill::DecayTick));
|
||||||
|
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, decay)));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, decay)));
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, wither)));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, wither)));
|
||||||
return decay_tick(source, target, results, Skill::DecayTick);
|
return decay_tick(source, target, results, Skill::DecayTick);
|
||||||
@ -1229,7 +1270,7 @@ fn invert(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill:
|
|||||||
fn reflect(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn reflect(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
let effect = CrypEffect::new(Effect::Reflect, skill.duration());
|
let effect = CrypEffect::new(Effect::Reflect, skill.duration());
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, effect)));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, effect)));
|
||||||
|
|
||||||
let blue_amount = source.blue_damage().pct(skill.multiplier());
|
let blue_amount = source.blue_damage().pct(skill.multiplier());
|
||||||
results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount)));
|
results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount)));
|
||||||
|
|
||||||
@ -1273,15 +1314,47 @@ fn siphon_tick(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn scatter(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn scatter(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
let scatter = CrypEffect::new(Effect::Scatter, skill.duration());
|
let effect = CrypEffect::new(Effect::Scatter, skill.duration())
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, scatter)));
|
.set_meta(EffectMeta::ScatterTarget(target.id));
|
||||||
|
|
||||||
|
let blue_amount = source.blue_damage().pct(skill.multiplier());
|
||||||
|
results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount)));
|
||||||
|
|
||||||
|
results.push(Resolution::new(source, target).event(source.add_effect(skill, effect)));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scatter_hit(source: &Cryp, target: &Cryp, mut results: Resolutions, game: &mut Game, event: Event) -> Resolutions {
|
||||||
|
match event {
|
||||||
|
Event::Damage { amount, skill, mitigation: _, colour } => {
|
||||||
|
let scatter = target.effects.iter().find(|e| e.effect == Effect::Scatter).unwrap();
|
||||||
|
|
||||||
|
if let Some(EffectMeta::ScatterTarget(scatter_target_id)) = scatter.meta {
|
||||||
|
let mut scatter_target = game.cryp_by_id(scatter_target_id).unwrap();
|
||||||
|
|
||||||
|
let res = match colour {
|
||||||
|
Category::RedDamage => scatter_target.deal_red_damage(skill, amount),
|
||||||
|
Category::BlueDamage => scatter_target.deal_blue_damage(skill, amount),
|
||||||
|
Category::GreenDamage => scatter_target.deal_green_damage(skill, amount),
|
||||||
|
_ => panic!("{:?} unknown damage type", colour),
|
||||||
|
};
|
||||||
|
|
||||||
|
results.push(Resolution::new(target, scatter_target).event(Event::Skill { skill: Skill::Scatter }));
|
||||||
|
res.into_iter().for_each(|e| results.push(Resolution::new(&source, &scatter_target).event(e)));
|
||||||
|
} else {
|
||||||
|
panic!("not a scatter target {:?}", scatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
_ => panic!("{:?} scatter hit not damage event", event),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn silence(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn silence(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
let silence = CrypEffect::new(Effect::Silence, skill.duration());
|
let silence = CrypEffect::new(Effect::Silence, skill.duration());
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, silence)));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, silence)));
|
||||||
|
|
||||||
let s_multi = target.skills
|
let s_multi = target.skills
|
||||||
.iter()
|
.iter()
|
||||||
.fold(100, |acc, cs| match cs.skill.category() {
|
.fold(100, |acc, cs| match cs.skill.category() {
|
||||||
@ -1531,47 +1604,6 @@ mod tests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn corrupt_test() {
|
|
||||||
let mut x = Cryp::new()
|
|
||||||
.named(&"muji".to_string());
|
|
||||||
|
|
||||||
let mut y = Cryp::new()
|
|
||||||
.named(&"camel".to_string());
|
|
||||||
|
|
||||||
corrupt(&mut y.clone(), &mut y, vec![], Skill::Corrupt);
|
|
||||||
assert!(y.affected(Effect::Corrupt));
|
|
||||||
|
|
||||||
resolve(Skill::Attack, &mut x, &mut y, vec![]);
|
|
||||||
|
|
||||||
assert!(x.affected(Effect::Corruption));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hatred_test() {
|
|
||||||
let mut x = Cryp::new()
|
|
||||||
.named(&"muji".to_string());
|
|
||||||
|
|
||||||
let mut y = Cryp::new()
|
|
||||||
.named(&"camel".to_string());
|
|
||||||
|
|
||||||
hostility(&mut y.clone(), &mut y, vec![], Skill::Hostility);
|
|
||||||
assert!(y.affected(Effect::Hostility));
|
|
||||||
|
|
||||||
resolve(Skill::TestAttack, &mut x, &mut y, vec![]);
|
|
||||||
|
|
||||||
assert!(y.affected(Effect::Hatred));
|
|
||||||
|
|
||||||
let mut results = resolve(Skill::TestAttack, &mut y, &mut x, vec![]);
|
|
||||||
|
|
||||||
let Resolution { source: _, target: _, event } = results.remove(0);
|
|
||||||
match event {
|
|
||||||
Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 512),
|
|
||||||
_ => panic!("not damage hatred"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn triage_test() {
|
fn triage_test() {
|
||||||
let mut x = Cryp::new()
|
let mut x = Cryp::new()
|
||||||
@ -1657,93 +1689,3 @@ mod tests {
|
|||||||
assert!(!x.effects.iter().any(|e| e.effect == Effect::Decay));
|
assert!(!x.effects.iter().any(|e| e.effect == Effect::Decay));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// pub enum Skill {
|
|
||||||
// Attack,
|
|
||||||
|
|
||||||
// // -----------------
|
|
||||||
// // Nature
|
|
||||||
// // -----------------
|
|
||||||
// Block, // reduce damage
|
|
||||||
// Parry, // avoid all damage
|
|
||||||
// Snare,
|
|
||||||
|
|
||||||
// Paralyse,
|
|
||||||
|
|
||||||
// Strangle, // physical dot and disable
|
|
||||||
// Strike,
|
|
||||||
// Stun,
|
|
||||||
// // Evade, // actively evade
|
|
||||||
|
|
||||||
|
|
||||||
// // -----------------
|
|
||||||
// // Technology
|
|
||||||
// // -----------------
|
|
||||||
// Replicate,
|
|
||||||
// Swarm,
|
|
||||||
// Orbit,
|
|
||||||
// Repair,
|
|
||||||
// Scan, // track?
|
|
||||||
|
|
||||||
// // -----------------
|
|
||||||
// // Nonviolence
|
|
||||||
// // -----------------
|
|
||||||
// Heal,
|
|
||||||
// Triage, // hot
|
|
||||||
// TriageTick,
|
|
||||||
// Throw, // no damage stun, adds vulnerable
|
|
||||||
// Charm,
|
|
||||||
// Calm,
|
|
||||||
// Rez,
|
|
||||||
|
|
||||||
// // Sleep,
|
|
||||||
// // Nightmare,
|
|
||||||
|
|
||||||
// // -------------------
|
|
||||||
// // Destruction
|
|
||||||
// // -------------------
|
|
||||||
// Blast,
|
|
||||||
// Amplify,
|
|
||||||
// Decay, // dot
|
|
||||||
// DecayTick, // dot
|
|
||||||
// Siphon,
|
|
||||||
// SiphonTick,
|
|
||||||
// Curse,
|
|
||||||
// Corrupt, // aoe dot
|
|
||||||
// Ruin, // aoe
|
|
||||||
|
|
||||||
// // -----------------
|
|
||||||
// // Purity
|
|
||||||
// // -----------------
|
|
||||||
// Empower,
|
|
||||||
// Slay,
|
|
||||||
// Shield,
|
|
||||||
// Silence,
|
|
||||||
// Inquiry,
|
|
||||||
// Purify,
|
|
||||||
// Purge,
|
|
||||||
// // Precision,
|
|
||||||
|
|
||||||
// // -----------------
|
|
||||||
// // Chaos
|
|
||||||
// // -----------------
|
|
||||||
// Banish,
|
|
||||||
// Hex,
|
|
||||||
// Fear,
|
|
||||||
// Taunt,
|
|
||||||
// Pause, // speed slow
|
|
||||||
// Haste,
|
|
||||||
// Slow,
|
|
||||||
|
|
||||||
// // used by tests, no cd, no damage
|
|
||||||
// TestTouch,
|
|
||||||
// TestStun,
|
|
||||||
// TestBlock,
|
|
||||||
// TestParry,
|
|
||||||
// TestSiphon,
|
|
||||||
// }
|
|
||||||
|
|||||||
@ -350,16 +350,16 @@ pub struct Combo {
|
|||||||
|
|
||||||
fn get_combos() -> Vec<Combo> {
|
fn get_combos() -> Vec<Combo> {
|
||||||
let mut combinations = vec![
|
let mut combinations = vec![
|
||||||
Combo { units: vec![Var::Buff, Var::Red, Var::Red], var: Var::Taunt },
|
Combo { units: vec![Var::Buff, Var::Red, Var::Red], var: Var::Taunt },
|
||||||
Combo { units: vec![Var::Buff, Var::Green, Var::Green], var: Var::Triage },
|
Combo { units: vec![Var::Buff, Var::Green, Var::Green], var: Var::Triage },
|
||||||
Combo { units: vec![Var::Buff, Var::Blue, Var::Blue], var: Var::Scatter }, //To be impl
|
Combo { units: vec![Var::Buff, Var::Blue, Var::Blue], var: Var::Scatter }, //To be impl
|
||||||
Combo { units: vec![Var::Buff, Var::Red, Var::Green], var: Var::Haste },
|
Combo { units: vec![Var::Buff, Var::Red, Var::Green], var: Var::Haste },
|
||||||
Combo { units: vec![Var::Buff, Var::Green, Var::Blue], var: Var::Impurity },
|
Combo { units: vec![Var::Buff, Var::Green, Var::Blue], var: Var::Impurity },
|
||||||
Combo { units: vec![Var::Buff, Var::Red, Var::Blue], var: Var::Amplify }, // Some flavour
|
Combo { units: vec![Var::Buff, Var::Red, Var::Blue], var: Var::Amplify }, // Some flavour
|
||||||
|
|
||||||
Combo { units: vec![Var::Debuff, Var::Red, Var::Red], var: Var::Snare },
|
Combo { units: vec![Var::Debuff, Var::Red, Var::Red], var: Var::Snare },
|
||||||
Combo { units: vec![Var::Debuff, Var::Green, Var::Green], var: Var::Purge }, // Needs flavour
|
Combo { units: vec![Var::Debuff, Var::Green, Var::Green], var: Var::Purge }, // Needs flavour
|
||||||
Combo { units: vec![Var::Debuff, Var::Blue, Var::Blue], var: Var::Silence },
|
Combo { units: vec![Var::Debuff, Var::Blue, Var::Blue], var: Var::Silence },
|
||||||
Combo { units: vec![Var::Debuff, Var::Red, Var::Green], var: Var::Curse }, // To be reworked
|
Combo { units: vec![Var::Debuff, Var::Red, Var::Green], var: Var::Curse }, // To be reworked
|
||||||
Combo { units: vec![Var::Debuff, Var::Green, Var::Blue], var: Var::Decay },
|
Combo { units: vec![Var::Debuff, Var::Green, Var::Blue], var: Var::Decay },
|
||||||
Combo { units: vec![Var::Debuff, Var::Red, Var::Blue], var: Var::Invert },
|
Combo { units: vec![Var::Debuff, Var::Red, Var::Blue], var: Var::Invert },
|
||||||
@ -675,8 +675,8 @@ mod tests {
|
|||||||
assert_eq!(count.red, 2);
|
assert_eq!(count.red, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn vbox_info_test() {
|
// fn vbox_info_test() {
|
||||||
println!("{:#?}", vbox_info());
|
// println!("{:#?}", vbox_info());
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user