mnml/core/src/skill.rs
2019-12-11 14:23:38 +10:00

2307 lines
89 KiB
Rust

use rand::{thread_rng, Rng};
use uuid::Uuid;
use util::{IntPct};
use item::{Item};
use game::{Game, Colour, Value, Action};
use construct::{Construct, ConstructEffect, EffectMeta, Stat};
use effect::{Effect, Cooldown};
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub struct Cast {
pub id: Uuid,
pub player: Uuid,
pub source: Uuid,
pub target: Uuid,
pub skill: Skill,
pub speed: usize,
}
fn start() {}
impl Cast {
pub fn new(source: Uuid, player: Uuid, target: Uuid, skill: Skill) -> Cast {
return Cast {
id: Uuid::new_v4(),
source,
player,
target,
skill,
speed: 0,
};
}
pub fn target(self) -> Uuid {
self.target
}
pub fn new_tick(source: &mut Construct, target: &mut Construct, skill: Skill) -> Cast {
Cast {
id: Uuid::new_v4(),
source: source.id,
player: source.account,
target: target.id,
skill,
speed: source.skill_speed(skill),
}
}
pub fn used_cooldown(&self) -> bool {
return self.skill.base_cd().is_some();
}
pub fn actions(&self) -> Vec<Action> {
let mut rng = thread_rng();
let mut actions = vec![];
if !self.skill.aoe() {
if self.skill.cast_animation() {
actions.push(Action::Cast);
}
actions.push(Action::Hit);
}
let mut rest = match self.skill {
Skill::Attack => vec![
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
},
],
Skill::Block => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Block, duration: 1, meta: Some(EffectMeta::Multiplier(35)) },
},
],
Skill::Buff => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Buff, duration: 3, meta: Some(EffectMeta::Multiplier(130)) },
},
],
Skill::Debuff => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Slow, duration: 3, meta: Some(EffectMeta::Multiplier(50)) },
},
],
Skill::Stun => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 2, meta: None },
},
],
Skill::Amplify => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Amplify, duration: 2, meta: Some(EffectMeta::Multiplier(150)) },
},
],
Skill::AmplifyPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Amplify, duration: 3, meta: Some(EffectMeta::Multiplier(175)) },
},
],
Skill::AmplifyPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Amplify, duration: 4, meta: Some(EffectMeta::Multiplier(200)) },
},
],
Skill::Absorb => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::Absorption)) },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
colour: Colour::Blue,
},
],
Skill::AbsorbPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::AbsorptionPlus)) },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
colour: Colour::Blue,
},
],
Skill::AbsorbPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::AbsorptionPlusPlus)) },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
colour: Colour::Blue,
},
],
Skill::Absorption => vec![
Action::Remove {
construct: self.source,
effect: Effect::Absorb,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Absorption, duration: 3, meta: None },
},
],
Skill::AbsorptionPlus => vec![
Action::Remove {
construct: self.source,
effect: Effect::Absorb,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Absorption, duration: 4, meta: None },
},
],
Skill::AbsorptionPlusPlus => vec![
Action::Remove {
construct: self.source,
effect: Effect::Absorb,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Absorption, duration: 5, meta: None },
},
],
// fn absorb(source: &mut Construct, target: &mut Construct, skill: Skill) {
// game.event(Event::new(source, target).event(target.effect_remove(skill, skill.effect()[0])));
// let blue_amount = source.blue_power().pct(skill.multiplier());
// target.recharge(skill, 0, blue_amount)
// .into_iter()
// .for_each(|e| game.event(Event::new(source, target).event(e).stages(EventStages::PostOnly)));
// }
// fn absorption(source: &mut Construct, target: &mut Construct, reflect_skill: Skill, amount: usize, skill: Skill) {
// let absorb = skill.effect()[0].set_meta(EffectMeta::AddedDamage(amount));
// game.event(Event::new(source, target)
// .event(target.effect_remove(reflect_skill, absorb))
// .stages(EventStages::PostOnly));
// let absorb_index = target.effects.iter().position(|e| e.effect == Effect::Absorb).expect("No absorb");
// let ce = target.effects.remove(absorb_index);
// game.event(Event::new(source, target)
// .event(Event::Remove { skill, effect: Some(ce.effect), construct_effects: target.effects.clone() })
// .stages(EventStages::PostOnly));
// }
Skill::Banish |
Skill::BanishPlus |
Skill::BanishPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![Value::Stat { construct: self.target, stat: Stat::RedLife, mult: self.skill.multiplier() }],
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.target, stat: Stat::BlueLife, mult: self.skill.multiplier() }],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Banish, duration: 2, meta: None }
}
],
Skill::Bash |
Skill::BashPlus |
Skill::BashPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![
Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() },
Value::Cooldowns { construct: self.source, mult: 45 },
],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 2, meta: None }
},
Action::IncreaseCooldowns {
construct: self.target,
turns: 1,
},
],
Skill::Blast |
Skill::BlastPlus |
Skill::BlastPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::Break => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 1, meta: None },
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Vulnerable, duration: 3, meta: Some(EffectMeta::Multiplier(150)), },
},
],
Skill::BreakPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 1, meta: None },
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Vulnerable, duration: 4, meta: Some(EffectMeta::Multiplier(175)), },
},
],
Skill::BreakPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 2, meta: None },
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Vulnerable, duration: 4, meta: Some(EffectMeta::Multiplier(200)), },
},
],
Skill::Curse => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Curse, duration: 2, meta: Some(EffectMeta::Multiplier(150)) },
},
],
Skill::CursePlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Curse, duration: 2, meta: Some(EffectMeta::Multiplier(175)) },
},
],
Skill::CursePlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Curse, duration: 3, meta: Some(EffectMeta::Multiplier(200)) },
},
],
Skill::Chaos |
Skill::ChaosPlus |
Skill::ChaosPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![
Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() },
Value::Stat { construct: self.source, stat: Stat::RedPower, mult: rng.gen_range(0, 30) },
],
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![
Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() },
Value::Stat { construct: self.source, stat: Stat::BluePower, mult: rng.gen_range(0, 30) },
],
},
],
Skill::Counter => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Counter, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::CounterAttack)) },
},
],
Skill::CounterPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Counter, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::CounterAttackPlus)) },
},
],
Skill::CounterPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Counter, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::CounterAttackPlusPlus)) },
},
],
Skill::CounterAttack |
Skill::CounterAttackPlus |
Skill::CounterAttackPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
},
],
Skill::Decay => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Wither, duration: 3, meta: Some(EffectMeta::Multiplier(50)) },
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Decay, duration: 2, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::DecayTick }) },
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::DecayPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Wither, duration: 3, meta: Some(EffectMeta::Multiplier(35)) },
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Decay, duration: 4, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::DecayTickPlus }) },
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::DecayPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Wither, duration: 4, meta: Some(EffectMeta::Multiplier(20)) },
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Decay, duration: 4, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::DecayTickPlusPlus }) },
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::DecayTick |
Skill::DecayTickPlus |
Skill::DecayTickPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Decayed, duration: 1, meta: None }, // immunity to additional ticks
},
],
Skill::Electrify=> vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Electric, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::Electrocute)) },
},
],
Skill::ElectrifyPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Electric, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::ElectrocutePlus)) },
},
],
Skill::ElectrifyPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Electric, duration: 1, meta: Some(EffectMeta::CastOnHit(Skill::ElectrocutePlusPlus)) },
},
],
Skill::Electrocute => vec![
Action::Remove {
construct: self.source,
effect: Effect::Electric,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Electric, duration: 2, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::ElectrocuteTick }) },
},
],
Skill::ElectrocutePlus => vec![
Action::Remove {
construct: self.source,
effect: Effect::Electric,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Electric, duration: 3, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::ElectrocuteTickPlus }) },
},
],
Skill::ElectrocutePlusPlus => vec![
Action::Remove {
construct: self.source,
effect: Effect::Electric,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Electric, duration: 4, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::ElectrocuteTickPlusPlus }) },
},
],
Skill::ElectrocuteTick |
Skill::ElectrocuteTickPlus |
Skill::ElectrocuteTickPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::Heal |
Skill::HealPlus |
Skill::HealPlusPlus => vec![
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
},
],
Skill::Haste => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Haste, duration: 3, meta: Some(EffectMeta::Multiplier(150)) },
},
],
Skill::HastePlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Haste, duration: 3, meta: Some(EffectMeta::Multiplier(175)) },
},
],
Skill::HastePlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Haste, duration: 3, meta: Some(EffectMeta::Multiplier(225)) },
},
],
Skill::Hybrid => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Hybrid, duration: 3, meta: Some(EffectMeta::Multiplier(150)) },
},
],
Skill::HybridPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Hybrid, duration: 4, meta: Some(EffectMeta::Multiplier(175)) },
},
],
Skill::HybridPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Hybrid, duration: 5, meta: Some(EffectMeta::Multiplier(200)) },
},
],
Skill::Intercept |
Skill::InterceptPlus |
Skill::InterceptPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Intercept, duration: 1, meta: None },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
colour: Colour::Red,
},
],
Skill::Invert => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Invert, duration: 2, meta: None },
},
],
Skill::InvertPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Invert, duration: 3, meta: None },
},
],
Skill::InvertPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Invert, duration: 4, meta: None },
},
],
Skill::Link |
Skill::LinkPlus |
Skill::LinkPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 1, meta: None },
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![
Value::Effects { construct: self.target, mult: self.skill.multiplier() },
],
},
],
Skill::Purge => vec![
Action::RemoveAll {
construct: self.target,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Purge, duration: 2, meta: None }
},
],
Skill::PurgePlus => vec![
Action::RemoveAll {
construct: self.target,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Purge, duration: 3, meta: None }
},
],
Skill::PurgePlusPlus => vec![
Action::RemoveAll {
construct: self.target,
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Purge, duration: 4, meta: None }
},
],
Skill::Purify => vec![
Action::RemoveAll {
construct: self.target,
},
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![
Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() },
Value::Removals { construct: self.target, mult: self.skill.multiplier() },
],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Pure, duration: 2, meta: Some(EffectMeta::Multiplier(150)) }
},
],
Skill::PurifyPlus => vec![
Action::RemoveAll {
construct: self.target,
},
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![
Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() },
Value::Removals { construct: self.target, mult: self.skill.multiplier() },
],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Pure, duration: 2, meta: Some(EffectMeta::Multiplier(175)) }
},
],
Skill::PurifyPlusPlus => vec![
Action::RemoveAll {
construct: self.target,
},
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![
Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() },
Value::Removals { construct: self.target, mult: self.skill.multiplier() },
],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Pure, duration: 2, meta: Some(EffectMeta::Multiplier(200)) }
},
],
Skill::Recharge |
Skill::RechargePlus |
Skill::RechargePlusPlus => vec![
Action::Heal {
construct: self.target,
colour: Colour::Red,
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
},
Action::Heal {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::Reflect |
Skill::ReflectPlus |
Skill::ReflectPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Reflect, duration: 1, meta: None },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
colour: Colour::Blue,
},
],
Skill::Restrict |
Skill::RestrictPlus |
Skill::RestrictPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Restrict, duration: 2, meta: None }
},
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![Value::ColourSkills { construct: self.source, colour: Colour::Red, mult: self.skill.multiplier() }],
},
],
Skill::Ruin |
Skill::RuinPlus |
Skill::RuinPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.target, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 1, meta: None }
}
],
Skill::Siphon => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Siphon, duration: 2, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::SiphonTick }) },
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::SiphonPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Siphon, duration: 3, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::SiphonTickPlus }) },
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::SiphonPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Siphon, duration: 4, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::SiphonTickPlusPlus }) },
},
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
],
Skill::SiphonTick |
Skill::SiphonTickPlus |
Skill::SiphonTickPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Blue,
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
},
Action::Heal {
construct: self.source,
colour: Colour::Green,
values: vec![Value::DamageReceived { construct: self.target, colour: Colour::Blue, mult: 100 }],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Siphoned, duration: 1, meta: None }, // immunity to additional ticks
},
],
Skill::Slay |
Skill::SlayPlus |
Skill::SlayPlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
},
Action::Heal {
construct: self.source,
colour: Colour::Green,
values: vec![Value::DamageReceived { construct: self.target, colour: Colour::Red, mult: 50 }],
},
],
Skill::Sleep => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 2, meta: None },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
colour: Colour::Blue,
},
],
Skill::SleepPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 2, meta: None },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
colour: Colour::Blue,
},
],
Skill::SleepPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Stun, duration: 2, meta: None },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
colour: Colour::Blue,
},
],
Skill::Silence |
Skill::SilencePlus |
Skill::SilencePlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Silence, duration: 2, meta: None },
},
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![
Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() },
Value::ColourSkills { construct: self.target, colour: Colour::Blue, mult: self.skill.multiplier() },
],
},
],
Skill::Strike |
Skill::StrikePlus |
Skill::StrikePlusPlus => vec![
Action::Damage {
construct: self.target,
colour: Colour::Red,
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
},
],
Skill::Sustain |
Skill::SustainPlus |
Skill::SustainPlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Sustain, duration: 1, meta: None },
},
Action::Heal {
construct: self.target,
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
colour: Colour::Red,
},
],
Skill::Triage => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Triage, duration: 2, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::TriageTick }) },
},
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
},
],
Skill::TriagePlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Triage, duration: 3, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::TriageTickPlus }) },
},
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
},
],
Skill::TriagePlusPlus => vec![
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Triage, duration: 4, meta:
Some(EffectMeta::CastTick { source: self.source, target: self.target, skill: Skill::TriageTickPlusPlus }) },
},
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
},
],
Skill::TriageTick |
Skill::TriageTickPlus |
Skill::TriageTickPlusPlus => vec![
Action::Heal {
construct: self.target,
colour: Colour::Green,
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
},
Action::Effect {
construct: self.target,
effect: ConstructEffect { effect: Effect::Triaged, duration: 1, meta: None },
},
],
// _ => unimplemented!(),
_ => vec![], // for client testing
};
actions.append(&mut rest);
return actions;
}
}
// pub fn dev_resolve(a_id: Uuid, b_id: Uuid, skill: Skill) {
// let mut resolutions =vec![];
// let mut a = Construct::new();
// a.id = a_id;
// let mut b = Construct::new();
// b.id = b_id;
// if skill.aoe() { // Send an aoe skill event for anims
// game.event(Event::new(&a, &b).event(Event::AoeSkill { skill }).stages(EventStages::StartEnd));
// }
// return cast_actions(skill, &mut a, &mut b, resolutions);
// }
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum Skill {
Attack,
Debuff,
Buff,
Block, // reduce damage
Stun,
// Boost -- sounds nice
// Evade, // actively evade
// Nightmare,
// Sleep,
Amplify,
#[serde(rename = "Amplify+")]
AmplifyPlus,
#[serde(rename = "Amplify++")]
AmplifyPlusPlus,
Absorb,
#[serde(rename = "Absorb+")]
AbsorbPlus,
#[serde(rename = "Absorb++")]
AbsorbPlusPlus,
Banish,
#[serde(rename = "Banish+")]
BanishPlus,
#[serde(rename = "Banish++")]
BanishPlusPlus,
Bash,
#[serde(rename = "Bash+")]
BashPlus,
#[serde(rename = "Bash++")]
BashPlusPlus,
Blast,
#[serde(rename = "Blast+")]
BlastPlus,
#[serde(rename = "Blast++")]
BlastPlusPlus,
Chaos,
#[serde(rename = "Chaos+")]
ChaosPlus,
#[serde(rename = "Chaos++")]
ChaosPlusPlus,
Sustain,
#[serde(rename = "Sustain+")]
SustainPlus,
#[serde(rename = "Sustain++")]
SustainPlusPlus,
Electrify,
#[serde(rename = "Electrify+")]
ElectrifyPlus,
#[serde(rename = "Electrify++")]
ElectrifyPlusPlus,
Curse,
#[serde(rename = "Curse+")]
CursePlus,
#[serde(rename = "Curse++")]
CursePlusPlus,
Decay,
#[serde(rename = "Decay+")]
DecayPlus,
#[serde(rename = "Decay++")]
DecayPlusPlus,
Haste,
#[serde(rename = "Haste+")]
HastePlus,
#[serde(rename = "Haste++")]
HastePlusPlus,
Heal,
#[serde(rename = "Heal+")]
HealPlus,
#[serde(rename = "Heal++")]
HealPlusPlus,
Hybrid,
#[serde(rename = "Hybrid+")]
HybridPlus,
#[serde(rename = "Hybrid++")]
HybridPlusPlus,
Invert,
#[serde(rename = "Invert+")]
InvertPlus,
#[serde(rename = "Invert++")]
InvertPlusPlus,
Counter,
#[serde(rename = "Counter+")]
CounterPlus,
#[serde(rename = "Counter++")]
CounterPlusPlus,
Purge,
#[serde(rename = "Purge+")]
PurgePlus,
#[serde(rename = "Purge++")]
PurgePlusPlus,
Purify,
#[serde(rename = "Purify+")]
PurifyPlus,
#[serde(rename = "Purify++")]
PurifyPlusPlus,
Reflect,
#[serde(rename = "Reflect+")]
ReflectPlus,
#[serde(rename = "Reflect++")]
ReflectPlusPlus,
Recharge,
#[serde(rename = "Recharge+")]
RechargePlus,
#[serde(rename = "Recharge++")]
RechargePlusPlus,
Ruin,
#[serde(rename = "Ruin+")]
RuinPlus,
#[serde(rename = "Ruin++")]
RuinPlusPlus,
Link,
#[serde(rename = "Link+")]
LinkPlus,
#[serde(rename = "Link++")]
LinkPlusPlus,
Silence,
#[serde(rename = "Silence+")]
SilencePlus,
#[serde(rename = "Silence++")]
SilencePlusPlus,
Slay,
#[serde(rename = "Slay+")]
SlayPlus,
#[serde(rename = "Slay++")]
SlayPlusPlus,
Sleep,
#[serde(rename = "Sleep+")]
SleepPlus,
#[serde(rename = "Sleep++")]
SleepPlusPlus,
Restrict,
#[serde(rename = "Restrict+")]
RestrictPlus,
#[serde(rename = "Restrict++")]
RestrictPlusPlus,
Strike,
#[serde(rename = "Strike+")]
StrikePlus,
#[serde(rename = "Strike++")]
StrikePlusPlus,
Siphon,
#[serde(rename = "Siphon+")]
SiphonPlus,
#[serde(rename = "Siphon++")]
SiphonPlusPlus,
Intercept,
#[serde(rename = "Intercept+")]
InterceptPlus,
#[serde(rename = "Intercept++")]
InterceptPlusPlus,
Break,
#[serde(rename = "Break+")]
BreakPlus,
#[serde(rename = "Break++")]
BreakPlusPlus,
Triage,
#[serde(rename = "Triage+")]
TriagePlus,
#[serde(rename = "Triage++")]
TriagePlusPlus,
Absorption,
#[serde(rename = "Absorption+")]
AbsorptionPlus,
#[serde(rename = "Absorption++")]
AbsorptionPlusPlus,
CounterAttack,
#[serde(rename = "CounterAttack+")]
CounterAttackPlus,
#[serde(rename = "CounterAttack++")]
CounterAttackPlusPlus,
Electrocute,
#[serde(rename = "Electrocute+")]
ElectrocutePlus,
#[serde(rename = "Electrocute++")]
ElectrocutePlusPlus,
ElectrocuteTick,
#[serde(rename = "ElectrocuteTick+")]
ElectrocuteTickPlus,
#[serde(rename = "ElectrocuteTick++")]
ElectrocuteTickPlusPlus,
DecayTick, // dot
#[serde(rename = "DecayTick+")]
DecayTickPlus,
#[serde(rename = "DecayTick++")]
DecayTickPlusPlus,
HasteStrike,
HybridBlast,
SiphonTick,
#[serde(rename = "SiphonTick+")]
SiphonTickPlus,
#[serde(rename = "SiphonTick++")]
SiphonTickPlusPlus,
TriageTick,
#[serde(rename = "TriageTick+")]
TriageTickPlus,
#[serde(rename = "TriageTick++")]
TriageTickPlusPlus,
}
impl Skill {
pub fn multiplier(&self) -> usize {
match self {
// Attack Base
Skill::Attack => 80, // Base
Skill::Blast => 105, // BB
Skill::BlastPlus => 125, // BB
Skill::BlastPlusPlus => 145, // BB
Skill::Chaos => 40, // BR
Skill::ChaosPlus => 50, // BR
Skill::ChaosPlusPlus => 65, // BR
Skill::Heal => 115, //GG
Skill::HealPlus => 135, //GG
Skill::HealPlusPlus => 160, //GG
Skill::SiphonTick => 25, // GB
Skill::SiphonTickPlus => 27,
Skill::SiphonTickPlusPlus => 30,
Skill::Slay => 40, // RG
Skill::SlayPlus => 50,
Skill::SlayPlusPlus => 65,
Skill::Strike => 90, //RR
Skill::StrikePlus => 110,
Skill::StrikePlusPlus => 140,
// Block Base
Skill::ElectrocuteTick => 80,
Skill::ElectrocuteTickPlus => 90,
Skill::ElectrocuteTickPlusPlus => 100,
Skill::CounterAttack => 115,
Skill::CounterAttackPlus => 130,
Skill::CounterAttackPlusPlus => 160,
Skill::Purify => 45, //Green dmg (heal)
Skill::PurifyPlus => 60,
Skill::PurifyPlusPlus => 85,
Skill::Reflect => 45, //Recharge blue life (heal)
Skill::ReflectPlus => 70,
Skill::ReflectPlusPlus => 100,
Skill::Recharge => 70, //Recharge red and blue life (heal)
Skill::RechargePlus => 90,
Skill::RechargePlusPlus => 110,
Skill::Sustain => 110, // Recharge red life (heal)
Skill::SustainPlus => 130,
Skill::SustainPlusPlus => 150,
// Stun Base
Skill::Sleep => 160, //Green dmg (heal)
Skill::SleepPlus => 200,
Skill::SleepPlusPlus => 240,
Skill::Banish => 50, //Green dmg (heal)
Skill::BanishPlus => 65,
Skill::BanishPlusPlus => 80,
Skill::Bash => 45,
Skill::BashPlus => 55,
Skill::BashPlusPlus => 70,
Skill::Link => 25,
Skill::LinkPlus => 35,
Skill::LinkPlusPlus => 45,
Skill::Ruin => 40,
Skill::RuinPlus => 55,
Skill::RuinPlusPlus => 70,
// Debuff Base
Skill::DecayTick => 33,
Skill::DecayTickPlus => 37,
Skill::DecayTickPlusPlus => 45,
Skill::Silence => 55, // Deals more per blue skill on target
Skill::SilencePlus => 65,
Skill::SilencePlusPlus => 80,
Skill::Restrict => 40, // Deals more per red skill on target
Skill::RestrictPlus => 55,
Skill::RestrictPlusPlus => 70,
// Buff base
Skill::HybridBlast => 50,
Skill::HasteStrike => 60,
Skill::Absorb=> 95,
Skill::AbsorbPlus => 110,
Skill::AbsorbPlusPlus => 120,
Skill::Intercept => 85,
Skill::InterceptPlus => 100,
Skill::InterceptPlusPlus => 125,
Skill::TriageTick => 75,
Skill::TriageTickPlus => 90,
Skill::TriageTickPlusPlus => 110,
_ => 100,
}
}
pub fn effect(&self) -> Vec<ConstructEffect> {
match self {
// Modifiers
Skill::Amplify => vec![ConstructEffect { effect: Effect::Amplify, duration: 2,
meta: Some(EffectMeta::Multiplier(150)) }],
Skill::AmplifyPlus => vec![ConstructEffect { effect: Effect::Amplify, duration: 3,
meta: Some(EffectMeta::Multiplier(175)) }],
Skill::AmplifyPlusPlus => vec![ConstructEffect { effect: Effect::Amplify, duration: 4,
meta: Some(EffectMeta::Multiplier(200)) }],
Skill::Banish => vec![ConstructEffect { effect: Effect::Banish, duration: 2, meta: None }],
Skill::BanishPlus => vec![ConstructEffect { effect: Effect::Banish, duration: 2, meta: None }],
Skill::BanishPlusPlus => vec![ConstructEffect { effect: Effect::Banish, duration: 2, meta: None }],
Skill::Block => vec![ConstructEffect { effect: Effect::Block, duration: 1,
meta: Some(EffectMeta::Multiplier(35)) }],
Skill::Buff => vec![ConstructEffect { effect: Effect::Buff, duration: 3,
meta: Some(EffectMeta::Multiplier(130)) }],
Skill::Electrify => vec![ConstructEffect { effect: Effect::Electric, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::Electrocute)) }],
Skill::ElectrifyPlus => vec![ConstructEffect { effect: Effect::Electric, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::ElectrocutePlus)) }],
Skill::ElectrifyPlusPlus => vec![ConstructEffect { effect: Effect::Electric, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::ElectrocutePlusPlus)) }],
Skill::Electrocute => vec![ConstructEffect { effect: Effect::Electrocute, duration: 2,
meta: Some(EffectMeta::CastOnHit(Skill::ElectrocuteTick)) }],
Skill::ElectrocutePlus => vec![ConstructEffect { effect: Effect::Electrocute, duration: 3,
meta: Some(EffectMeta::CastOnHit(Skill::ElectrocuteTickPlus)) }],
Skill::ElectrocutePlusPlus => vec![ConstructEffect { effect: Effect::Electrocute, duration: 4,
meta: Some(EffectMeta::CastOnHit(Skill::ElectrocuteTickPlusPlus)) }],
Skill::Sustain => vec![ConstructEffect { effect: Effect::Sustain, duration: 1, meta: None }],
Skill::SustainPlus => vec![ConstructEffect { effect: Effect::Sustain, duration: 1, meta: None }],
Skill::SustainPlusPlus => vec![ConstructEffect { effect: Effect::Sustain, duration: 1, meta: None }],
Skill::Curse => vec![ConstructEffect { effect: Effect::Curse, duration: 2,
meta: Some(EffectMeta::Multiplier(150)) }],
Skill::CursePlus => vec![ConstructEffect { effect: Effect::Curse, duration: 2,
meta: Some(EffectMeta::Multiplier(175)) }],
Skill::CursePlusPlus => vec![ConstructEffect { effect: Effect::Curse, duration: 3,
meta: Some(EffectMeta::Multiplier(200)) }],
Skill::Debuff => vec![ConstructEffect { effect: Effect::Slow, duration: 3,
meta: Some(EffectMeta::Multiplier(50)) }],
Skill::Decay => vec![ConstructEffect { effect: Effect::Wither, duration: 3,
meta: Some(EffectMeta::Multiplier(50)) },
ConstructEffect { effect: Effect::Decay, duration: 3,
meta: Some(EffectMeta::CastOnHit(Skill::DecayTick)) }],
Skill::DecayPlus => vec![ConstructEffect { effect: Effect::Wither, duration: 3,
meta: Some(EffectMeta::Multiplier(35)) },
ConstructEffect { effect: Effect::Decay, duration: 3,
meta: Some(EffectMeta::CastOnHit(Skill::DecayTickPlus)) }],
Skill::DecayPlusPlus => vec![ConstructEffect { effect: Effect::Wither, duration: 4,
meta: Some(EffectMeta::Multiplier(20)) },
ConstructEffect { effect: Effect::Decay, duration: 4,
meta: Some(EffectMeta::CastOnHit(Skill::DecayTickPlusPlus)) }],
Skill::Haste => vec![ConstructEffect { effect: Effect::Haste, duration: 3,
meta: Some(EffectMeta::Multiplier(150)) }],
Skill::HastePlus => vec![ConstructEffect { effect: Effect::Haste, duration: 4,
meta: Some(EffectMeta::Multiplier(175)) }],
Skill::HastePlusPlus => vec![ConstructEffect { effect: Effect::Haste, duration: 5,
meta: Some(EffectMeta::Multiplier(225)) }],
Skill::Absorb => vec![ConstructEffect { effect: Effect::Absorb, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::Absorption)) }],
Skill::AbsorbPlus => vec![ConstructEffect { effect: Effect::Absorb, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::AbsorptionPlus)) }],
Skill::AbsorbPlusPlus => vec![ConstructEffect { effect: Effect::Absorb, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::AbsorptionPlusPlus)) }],
Skill::Absorption => vec![ConstructEffect { effect: Effect::Absorption, duration: 3, meta: None }],
Skill::AbsorptionPlus => vec![ConstructEffect { effect: Effect::Absorption, duration: 4, meta: None }],
Skill::AbsorptionPlusPlus => vec![ConstructEffect { effect: Effect::Absorption, duration: 5, meta: None }],
Skill::Hybrid => vec![ConstructEffect { effect: Effect::Hybrid, duration: 3,
meta: Some(EffectMeta::Multiplier(150)) }],
Skill::HybridPlus => vec![ConstructEffect { effect: Effect::Hybrid, duration: 4,
meta: Some(EffectMeta::Multiplier(175)) }],
Skill::HybridPlusPlus => vec![ConstructEffect { effect: Effect::Hybrid, duration: 5,
meta: Some(EffectMeta::Multiplier(200)) }],
Skill::Invert => vec![ConstructEffect { effect: Effect::Invert, duration: 2, meta: None }],
Skill::InvertPlus => vec![ConstructEffect { effect: Effect::Invert, duration: 3, meta: None }],
Skill::InvertPlusPlus => vec![ConstructEffect { effect: Effect::Invert, duration: 4, meta: None }],
Skill::Counter => vec![ConstructEffect { effect: Effect::Counter, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::CounterAttack)) }],
Skill::CounterPlus => vec![ConstructEffect { effect: Effect::Counter, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::CounterAttackPlus)) }],
Skill::CounterPlusPlus => vec![ConstructEffect { effect: Effect::Counter, duration: 1,
meta: Some(EffectMeta::CastOnHit(Skill::CounterAttackPlusPlus)) }],
Skill::Reflect => vec![ConstructEffect { effect: Effect::Reflect, duration: 1, meta: None }],
Skill::ReflectPlus => vec![ConstructEffect { effect: Effect::Reflect, duration: 1, meta: None }],
Skill::ReflectPlusPlus => vec![ConstructEffect { effect: Effect::Reflect, duration: 1, meta: None }],
Skill::Break => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None },
ConstructEffect { effect: Effect::Vulnerable, duration: 3,
meta: Some(EffectMeta::Multiplier(150)) }],
Skill::BreakPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None },
ConstructEffect { effect: Effect::Vulnerable, duration: 4,
meta: Some(EffectMeta::Multiplier(175)) }],
Skill::BreakPlusPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 2, meta: None },
ConstructEffect { effect: Effect::Vulnerable, duration: 4,
meta: Some(EffectMeta::Multiplier(200)) }],
Skill::Ruin => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None }],
Skill::RuinPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None }],
Skill::RuinPlusPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None }],
Skill::Purge => vec![ConstructEffect { effect: Effect::Purge, duration: 2, meta: None }],
Skill::PurgePlus => vec![ConstructEffect { effect: Effect::Purge, duration: 3, meta: None }],
Skill::PurgePlusPlus => vec![ConstructEffect { effect: Effect::Purge, duration: 4, meta: None }],
Skill::Link => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None }],
Skill::LinkPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None }],
Skill::LinkPlusPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 1, meta: None }],
Skill::Silence => vec![ConstructEffect { effect: Effect::Silence, duration: 2, meta: None }],
Skill::SilencePlus => vec![ConstructEffect { effect: Effect::Silence, duration: 2, meta: None }],
Skill::SilencePlusPlus => vec![ConstructEffect { effect: Effect::Silence, duration: 2, meta: None }],
Skill::Siphon => vec![ConstructEffect { effect: Effect::Siphon, duration: 2,
meta: Some(EffectMeta::CastOnHit(Skill::SiphonTick)) }],
Skill::SiphonPlus => vec![ConstructEffect { effect: Effect::Siphon, duration: 3,
meta: Some(EffectMeta::CastOnHit(Skill::SiphonTickPlus)) }],
Skill::SiphonPlusPlus => vec![ConstructEffect { effect: Effect::Siphon, duration: 4,
meta: Some(EffectMeta::CastOnHit(Skill::SiphonTickPlusPlus)) }],
Skill::Sleep => vec![ConstructEffect { effect: Effect::Stun, duration: 2, meta: None }],
Skill::SleepPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 3, meta: None }],
Skill::SleepPlusPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 4, meta: None }],
Skill::Restrict => vec![ConstructEffect { effect: Effect::Restrict, duration: 2, meta: None }],
Skill::RestrictPlus => vec![ConstructEffect { effect: Effect::Restrict, duration: 2, meta: None }],
Skill::RestrictPlusPlus => vec![ConstructEffect { effect: Effect::Restrict, duration: 2, meta: None }],
Skill::Bash => vec![ConstructEffect { effect: Effect::Stun, duration: 2,
meta: Some(EffectMeta::CastOnHit(Skill::Bash)) }],
Skill::BashPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 2,
meta: Some(EffectMeta::CastOnHit(Skill::BashPlus)) }],
Skill::BashPlusPlus => vec![ConstructEffect { effect: Effect::Stun, duration: 2,
meta: Some(EffectMeta::CastOnHit(Skill::BashPlusPlus)) }],
Skill::Stun => vec![ConstructEffect { effect: Effect::Stun, duration: 2, meta: None }],
Skill::Intercept => vec![ConstructEffect { effect: Effect::Intercept, duration: 1, meta: None }],
Skill::InterceptPlus => vec![ConstructEffect { effect: Effect::Intercept, duration: 1, meta: None }],
Skill::InterceptPlusPlus => vec![ConstructEffect { effect: Effect::Intercept, duration: 1, meta: None }],
Skill::Triage => vec![ConstructEffect { effect: Effect::Triage, duration: 2,
meta: Some(EffectMeta::CastOnHit(Skill::TriageTick)) }],
Skill::TriagePlus => vec![ConstructEffect { effect: Effect::Triage, duration: 3,
meta: Some(EffectMeta::CastOnHit(Skill::TriageTickPlus)) }],
Skill::TriagePlusPlus => vec![ConstructEffect { effect: Effect::Triage, duration: 4,
meta: Some(EffectMeta::CastOnHit(Skill::TriageTickPlusPlus)) }],
Skill::Purify => vec![ConstructEffect { effect: Effect::Pure, duration: 2,
meta: Some(EffectMeta::Multiplier(150)) }],
Skill::PurifyPlus => vec![ConstructEffect { effect: Effect::Pure, duration: 2,
meta: Some(EffectMeta::Multiplier(175)) }],
Skill::PurifyPlusPlus => vec![ConstructEffect { effect: Effect::Pure, duration: 2,
meta: Some(EffectMeta::Multiplier(200)) }],
_ => {
panic!("{:?} no skill effect", self);
},
}
}
pub fn base_cd(&self) -> Cooldown {
match self {
Skill::Attack => None,
Skill::Block => None, // reduce damage
Skill::Buff => None,
Skill::Debuff => Some(1),
Skill::Stun => Some(2),
Skill::Strike=> None,
Skill::StrikePlus => None,
Skill::StrikePlusPlus => None,
Skill::Counter|
Skill::CounterPlus |
Skill::CounterPlusPlus => None, // avoid all damage
Skill::Restrict |
Skill::RestrictPlus |
Skill::RestrictPlusPlus => Some(2),
Skill::Bash |
Skill::BashPlus |
Skill::BashPlusPlus => Some(2),
Skill::Heal=> None,
Skill::HealPlus => None,
Skill::HealPlusPlus => None,
Skill::Triage=> None, // hot
Skill::TriagePlus => None, // hot
Skill::TriagePlusPlus => None, // hot
Skill::Break | // no damage stun, adds vulnerable
Skill::BreakPlus |
Skill::BreakPlusPlus => Some(1),
Skill::Blast |
Skill::BlastPlus |
Skill::BlastPlusPlus => None,
Skill::Chaos |
Skill::ChaosPlus |
Skill::ChaosPlusPlus => None,
Skill::Amplify |
Skill::AmplifyPlus |
Skill::AmplifyPlusPlus => Some(1),
Skill::Hybrid |
Skill::HybridPlus |
Skill::HybridPlusPlus => Some(1),
Skill::Invert |
Skill::InvertPlus |
Skill::InvertPlusPlus => Some(2),
Skill::Decay => None, // dot
Skill::DecayPlus => None,
Skill::DecayPlusPlus => None,
Skill::Siphon|
Skill::SiphonPlus |
Skill::SiphonPlusPlus => None,
Skill::Curse |
Skill::CursePlus |
Skill::CursePlusPlus => Some(1),
Skill::Link |
Skill::LinkPlus |
Skill::LinkPlusPlus => Some(1),
Skill::Silence |
Skill::SilencePlus |
Skill::SilencePlusPlus => Some(2),
Skill::Purify |
Skill::PurifyPlus |
Skill::PurifyPlusPlus => None,
Skill::Purge |
Skill::PurgePlus |
Skill::PurgePlusPlus => Some(1),
Skill::Banish |
Skill::BanishPlus |
Skill::BanishPlusPlus => Some(1),
Skill::Haste |
Skill::HastePlus |
Skill::HastePlusPlus => Some(1),
Skill::Reflect |
Skill::ReflectPlus |
Skill::ReflectPlusPlus => None,
Skill::Recharge |
Skill::RechargePlus |
Skill::RechargePlusPlus => None,
Skill::Ruin |
Skill::RuinPlus |
Skill::RuinPlusPlus => Some(2),
Skill::Slay=> None,
Skill::SlayPlus => None,
Skill::SlayPlusPlus => None,
Skill::Sleep |
Skill::SleepPlus |
Skill::SleepPlusPlus => Some(2),
Skill::Sustain |
Skill::SustainPlus |
Skill::SustainPlusPlus => Some(1),
Skill::Intercept => Some(1),
Skill::InterceptPlus => Some(1),
Skill::InterceptPlusPlus => Some(1),
Skill::Electrify |
Skill::ElectrifyPlus |
Skill::ElectrifyPlusPlus => None,
Skill::Absorb |
Skill::AbsorbPlus |
Skill::AbsorbPlusPlus => Some(1),
//-----------
// Never cast directly
//---------
// Trigger
Skill::HybridBlast |
Skill::HasteStrike |
Skill::CounterAttack|
Skill::CounterAttackPlus |
Skill::CounterAttackPlusPlus | // counter
Skill::Electrocute|
Skill::ElectrocutePlus |
Skill::ElectrocutePlusPlus |
Skill::Absorption|
Skill::AbsorptionPlus |
Skill::AbsorptionPlusPlus |
// Ticks
Skill::ElectrocuteTick|
Skill::ElectrocuteTickPlus |
Skill::ElectrocuteTickPlusPlus |
Skill::DecayTick|
Skill::DecayTickPlus |
Skill::DecayTickPlusPlus |
Skill::SiphonTick|
Skill::SiphonTickPlus |
Skill::SiphonTickPlusPlus |
Skill::TriageTick|
Skill::TriageTickPlus |
Skill::TriageTickPlusPlus => None,
}
}
pub fn cast_animation(&self) -> bool {
match self {
Skill::HybridBlast |
Skill::HasteStrike |
Skill::CounterAttack|
Skill::CounterAttackPlus |
Skill::CounterAttackPlusPlus | // counter
Skill::Electrocute|
Skill::ElectrocutePlus |
Skill::ElectrocutePlusPlus |
Skill::Absorption|
Skill::AbsorptionPlus |
Skill::AbsorptionPlusPlus |
Skill::ElectrocuteTick|
Skill::ElectrocuteTickPlus |
Skill::ElectrocuteTickPlusPlus |
Skill::DecayTick|
Skill::DecayTickPlus |
Skill::DecayTickPlusPlus |
Skill::SiphonTick|
Skill::SiphonTickPlus |
Skill::SiphonTickPlusPlus |
Skill::TriageTick|
Skill::TriageTickPlus |
Skill::TriageTickPlusPlus => false,
_ => true,
}
}
pub fn ko_castable(&self) -> bool {
match self {
Skill::ElectrocuteTick |
Skill::ElectrocuteTickPlus |
Skill::ElectrocuteTickPlusPlus |
Skill::DecayTick |
Skill::DecayTickPlus |
Skill::DecayTickPlusPlus |
Skill::SiphonTick |
Skill::SiphonTickPlus |
Skill::SiphonTickPlusPlus |
Skill::TriageTick |
Skill::TriageTickPlus |
Skill::TriageTickPlusPlus => true,
_ => false,
}
}
pub fn is_tick(&self) -> bool {
match self {
Skill::ElectrocuteTick |
Skill::ElectrocuteTickPlus |
Skill::ElectrocuteTickPlusPlus |
Skill::DecayTick |
Skill::DecayTickPlus |
Skill::DecayTickPlusPlus |
Skill::SiphonTick |
Skill::SiphonTickPlus |
Skill::SiphonTickPlusPlus |
Skill::TriageTick |
Skill::TriageTickPlus |
Skill::TriageTickPlusPlus => true,
_ => false,
}
}
pub fn speed(&self) -> usize {
match self {
Skill::SiphonTick |
Skill::SiphonTickPlus |
Skill::SiphonTickPlusPlus => Skill::Siphon.speed(),
Skill::DecayTick |
Skill::DecayTickPlus |
Skill::DecayTickPlusPlus => Skill::Decay.speed(),
Skill::TriageTick |
Skill::TriageTickPlus |
Skill::TriageTickPlusPlus => Skill::Triage.speed(),
Skill::ElectrocuteTick |
Skill::ElectrocuteTickPlus |
Skill::ElectrocuteTickPlusPlus => Skill::Electrify.speed(),
_ => Item::from(*self).speed(),
}
}
pub fn aoe(&self) -> bool {
match self {
Skill::Ruin |
Skill::RuinPlus |
Skill::RuinPlusPlus => true,
_ => false,
}
}
pub fn defensive(&self) -> bool {
match self {
Skill::Amplify|
Skill::AmplifyPlus |
Skill::AmplifyPlusPlus |
Skill::Block |
Skill::Sustain |
Skill::SustainPlus |
Skill::SustainPlusPlus |
Skill::Electrify |
Skill::ElectrifyPlus |
Skill::ElectrifyPlusPlus |
Skill::Haste |
Skill::HastePlus |
Skill::HastePlusPlus |
Skill::Heal |
Skill::HealPlus |
Skill::HealPlusPlus |
Skill::Absorb |
Skill::AbsorbPlus |
Skill::AbsorbPlusPlus |
Skill::Invert |
Skill::InvertPlus |
Skill::InvertPlusPlus |
Skill::Intercept |
Skill::InterceptPlus |
Skill::InterceptPlusPlus |
Skill::Counter |
Skill::CounterPlus |
Skill::CounterPlusPlus |
Skill::Purify |
Skill::PurifyPlus |
Skill::PurifyPlusPlus |
Skill::Recharge |
Skill::RechargePlus |
Skill::RechargePlusPlus |
Skill::Reflect |
Skill::ReflectPlus |
Skill::ReflectPlusPlus |
Skill::Triage |
Skill::TriagePlus |
Skill::TriagePlusPlus => true,
_ => false,
}
}
fn components(&self) -> Vec<Item> {
let mut components = Item::from(*self).components();
components.sort_unstable();
return components;
}
pub fn colours(&self) -> Vec<Colour> {
let mut components = self.components();
let colour_items = [Item::Red, Item::Green, Item::Blue];
components.dedup();
return components.iter()
.filter(|i| colour_items.contains(i))
.map(|i| i.into_colour())
.collect::<Vec<Colour>>();
}
fn base(&self) -> Skill {
let bases = [Item::Attack, Item::Stun, Item::Buff, Item::Debuff, Item::Block];
match self.components()
.iter()
.find(|i| bases.contains(i)) {
Some(i) => i.into_skill().unwrap(),
None => panic!("{:?} has no base item", self),
}
}
}
// #[cfg(test)]
mod tests {
use skill::*;
#[test]
fn attack_actions_test() {
let cast = Cast::new(Uuid::new_v4(), Uuid::new_v4(), Uuid::new_v4(), Skill::Attack);
let actions = cast.actions();
match actions[0] {
Action::Cast => (),
_ => panic!("{:?}", actions),
};
match actions[1] {
Action::Hit => (),
_ => panic!("{:?}", actions),
};
match actions[2] {
Action::Damage { construct: _, values: _, colour } => {
assert_eq!(colour, Colour::Red);
},
_ => panic!("{:?}", actions),
};
}
// #[test]
// fn heal_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string())
// .learn(Skill::Heal);
// let mut y = Construct::new()
// .named(&"camel".to_string())
// .learn(Skill::Heal);
// x.deal_red_damage(Skill::Attack, 5);
// heal(&mut y, &mut x, vec![], Skill::Heal);
// }
// #[test]
// fn decay_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"camel".to_string());
// decay(&mut x, &mut y, vec![], Skill::Decay);
// assert!(y.effects.iter().any(|e| e.effect == Effect::Decay));
// y.reduce_effect_durations();
// let _decay = y.effects.iter().find(|e| e.effect == Effect::Decay);
// // assert!(y.green_life() == y.green_life().saturating_sub(decay.unwrap().tick.unwrap().amount));
// }
// #[test]
// fn block_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"camel".to_string());
// // ensure it doesn't have 0 pd
// x.red_power.force(100);
// y.green_life.force(500);
// block(&mut y.clone(), &mut y, vec![], Skill::Block);
// assert!(y.effects.iter().any(|e| e.effect == Effect::Block));
// attack(&mut x, &mut y, vec![], Skill::Attack);
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Damage { amount, mitigation: _, colour: _, skill: _ } =>
// assert!(amount < x.red_power().pct(Skill::Attack.multiplier())),
// _ => panic!("not damage"),
// };
// }
// #[test]
// fn sustain_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"camel".to_string());
// x.red_power.force(10000000000000); // multiplication of int max will cause overflow
// y.green_life.force(1024); // make tests more flexible if we change stats
// sustain(&mut y.clone(), &mut y, vec![], Skill::Sustain);
// assert!(y.affected(Effect::Sustain));
// ruin(&mut x, &mut y, vec![], Skill::Ruin);
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Immunity { skill: _, immunity } => assert!(immunity.contains(&Effect::Sustain)),
// _ => panic!("not immune cluthc"),
// };
// attack(&mut x, &mut y, vec![], Skill::Attack);
// assert!(y.green_life() == 1);
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert_eq!(amount, 1023),
// _ => panic!("not damage"),
// };
// }
// #[test]
// fn invert_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"camel".to_string());
// // give red shield but reduce to 0
// y.red_life.force(64);
// y.red_life.reduce(64);
// x.red_power.force(512);
// invert(&mut y.clone(), &mut y, vec![], Skill::Invert);
// assert!(y.affected(Effect::Invert));
// // heal should deal green damage
// heal(&mut x, &mut y, vec![], Skill::Heal);
// assert!(y.green_life() < 1024);
// // attack should heal and recharge red shield
// attack(&mut x, &mut y, vec![], Skill::Attack);
// // match resolutions.remove(0).event {
// // Event::Inversion { skill } => assert_eq!(skill, Skill::Attack),
// // _ => panic!("not inversion"),
// //};
// match resolutions.remove(0).event {
// Event::Heal { skill: _, overhealing: _, amount } => assert!(amount > 0),
// _ => panic!("not healing from inversion"),
// };
// match resolutions.remove(0).event {
// Event::Recharge { skill: _, red, blue: _ } => assert!(red > 0),
// _ => panic!("not recharge from inversion"),
// };
// }
// #[test]
// fn reflect_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"camel".to_string());
// reflect(&mut y.clone(), &mut y, vec![], Skill::Reflect);
// assert!(y.affected(Effect::Reflect));
// let mut vec![];
// cast_actions(Skill::Blast, &mut x, &mut y, resolutions);
// assert!(x.green_life() < 1024);
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Reflection { skill } => assert_eq!(skill, Skill::Blast),
// _ => panic!("not reflection"),
// };
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert!(amount > 0),
// _ => panic!("not damage"),
// };
// }
// #[test]
// fn siphon_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"camel".to_string());
// x.blue_power.force(256);
// x.green_power.force(220);
// x.green_life.force(1024);
// y.blue_life.force(0);
// x.green_life.reduce(512);
// cast_actions(Skill::Siphon, &mut x, &mut y, vec![]);
// assert!(y.affected(Effect::Siphon));
// assert!(x.green_life() == (512 + 256.pct(Skill::SiphonTick.multiplier()) + 220.pct(Skill::SiphonTick.multiplier())));
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Effect { effect, skill: _, duration: _, construct_effects: _ } => assert_eq!(effect, Effect::Siphon),
// _ => panic!("not siphon"),
// };
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256.pct(Skill::SiphonTick.multiplier())
// + 220.pct(Skill::SiphonTick.multiplier())),
// _ => panic!("not damage siphon"),
// };
// let Event { source: _, target, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Heal { amount, skill: _, overhealing: _ } => {
// assert_eq!(amount, 256.pct(Skill::SiphonTick.multiplier()) + 220.pct(Skill::SiphonTick.multiplier()));
// assert_eq!(target.id, x.id);
// },
// _ => panic!("not healing"),
// };
// }
// #[test]
// fn triage_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"pretaliation".to_string());
// // ensure it doesn't have 0 sd
// x.blue_power.force(50);
// // remove all mitigation
// y.red_life.force(0);
// y.blue_life.force(0);
// y.deal_red_damage(Skill::Attack, 5);
// let prev_hp = y.green_life();
// triage(&mut x, &mut y, vec![], Skill::Triage);
// assert!(y.effects.iter().any(|e| e.effect == Effect::Triage));
// assert!(y.green_life() > prev_hp);
// }
// #[test]
// fn recharge_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"pretaliation".to_string());
// y.red_life.force(50);
// y.blue_life.force(50);
// y.deal_red_damage(Skill::Attack, 5);
// y.deal_blue_damage(Skill::Blast, 5);
// recharge(&mut x, &mut y, vec![], Skill::Recharge);
// resolutions.remove(0);
// let Event { source: _, target: _, event, stages: _ } = resolutions.remove(0);
// match event {
// Event::Recharge { red, blue, skill: _ } => {
// assert!(red == 5);
// assert!(blue == 5);
// }
// _ => panic!("result was not recharge"),
// }
// }
// #[test]
// fn silence_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// silence(&mut x.clone(), &mut x, vec![], Skill::Silence);
// assert!(x.effects.iter().any(|e| e.effect == Effect::Silence));
// assert!(x.disabled(Skill::Silence).is_some());
// }
// #[test]
// fn amplify_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// x.blue_power.force(50);
// amplify(&mut x.clone(), &mut x, vec![], Skill::Amplify);
// assert!(x.effects.iter().any(|e| e.effect == Effect::Amplify));
// assert_eq!(x.blue_power(), 75);
// }
// #[test]
// fn purify_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// decay(&mut x.clone(), &mut x, vec![], Skill::Decay);
// assert!(x.effects.iter().any(|e| e.effect == Effect::Decay));
// purify(&mut x.clone(), &mut x, vec![], Skill::Purify);
// assert!(!x.effects.iter().any(|e| e.effect == Effect::Decay));
// }
// #[test]
// fn bash_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"pretaliation".to_string())
// .learn(Skill::Stun);
// let stun_cd = y.skills.iter().find(|cs| cs.skill == Skill::Stun).unwrap().cd.unwrap();
// bash(&mut x, &mut y, vec![], Skill::Bash);
// assert!(!x.effects.iter().any(|e| e.effect == Effect::Stun));
// assert!(y.skills.iter().any(|cs| cs.skill == Skill::Stun && cs.cd.unwrap() == stun_cd + 1));
// }
// #[test]
// fn purge_test() {
// let mut x = Construct::new()
// .named(&"muji".to_string());
// let mut y = Construct::new()
// .named(&"pretaliation".to_string())
// .learn(Skill::Heal)
// .learn(Skill::HealPlus);
// purge(&mut x, &mut y, vec![], Skill::Purge);
// // 2 turns at lvl 1
// assert!(y.effects.iter().any(|e| e.effect == Effect::Purge && e.duration == 2));
// assert!(y.disabled(Skill::Heal).is_some());
// }
}
// Skill::Strike => game.event(
// Event::Damage {
// colour: Colour::Red,
// amount: SkillPower { construct: cast.source, skill: Skill::Strike }
// },
// Event::LifeSteal {
// amount: CastDamage { id: cast.id, colour: Colour::Red, target: cast.source },
// },
// ),
// Skill::Attack => game.event(Event::Damage {
// colour: Colour::Red,
// amount: Stat { construct: cast.source, stat: Stat::RedPower, pct: ATTACK_RED_POWER_PCT }
// }),
// Skill::Bash => game.event(Event::Damage {
// colour: Colour::Red,
// amounts: vec![
// Stat { construct: cast.source, stat: Stat::RedPower, pct: ATTACK_RED_POWER_PCT },
// Cooldowns { construct: cast.source },
// ],
// })
// // we clone the current state of the target and source
// // so we can modify them during the resolution
// // no more than 1 mutable ref allowed on game
// let mut source = game.construct_by_id(cast.source).unwrap().clone();
// let mut target = game.construct_by_id(target_id).unwrap().clone();
// // bail out on ticks that have been removed
// if skill.is_tick() && target.effects.iter().find(|ce| match ce.tick {
// Some(t) => t.id == cast.id,
// None => false,
// }).is_none() {
// return;
// }
// if let Some(_disable) = source.disabled(skill) {
// game.event(Event::new(source, target).event(Event::Disable { disable, skill }).stages(EventStages::PostOnly));
// return;
// }
// if target.is_ko() {
// game.event(Event::new(source, target).event(Event::TargetKo { skill }).stages(EventStages::PostOnly));
// return;
// }
// if target.affected(Effect::Reflect) && skill.colours().contains(&Colour::Blue) && !skill.is_tick() {
// // guard against overflow
// if source.affected(Effect::Reflect) {
// }
// game.event(Event::new(source, target).event(Event::Reflection { skill }));
// return cast_actions(skill, &mut source.clone(), source, resolutions);
// }
// // haste_strike_check(game)
// if source.affected(Effect::Haste) {
// match skill {
// Skill::Slay |
// Skill::SlayPlus |
// Skill::SlayPlusPlus |
// Skill::Chaos |
// Skill::ChaosPlus |
// Skill::ChaosPlusPlus |
// Skill::Strike |
// Skill::StrikePlus |
// Skill::StrikePlusPlus => {
// let amount = source.speed().pct(Skill::HasteStrike.multiplier());
// target.deal_red_damage(Skill::HasteStrike, amount)
// .into_iter()
// .for_each(|e| game.event(Event::new(source, target).event(e)));
// },
// _ => (),
// }
// }
// if source.affected(Effect::Hybrid) {
// match skill {
// Skill::Blast|
// Skill::BlastPlus |
// Skill::BlastPlusPlus |
// Skill::Chaos |
// Skill::ChaosPlus |
// Skill::ChaosPlusPlus |
// Skill::Siphon |
// Skill::SiphonPlus |
// Skill::SiphonPlusPlus => {
// let amount = source.green_power().pct(Skill::HybridBlast.multiplier());
// target.deal_blue_damage(Skill::HybridBlast, amount)
// .into_iter()
// .for_each(|e| game.event(Event::new(source, target).event(e)));
// },
// _ => (),
// }
// }
// match self.category() == EffectCategory::Red {
// true => {
// if let Some(evasion) = target.evade(*self) {
// game.event(evasion);
// return Event;
// }
// },
// false => (),
// }
// for Event { source: event_source, target: event_target, event, stages: _ } in resolutions.clone() {
// let mut source = game.construct_by_id(event_source.id).unwrap().clone();
// let mut target = game.construct_by_id(event_target.id).unwrap().clone();
// match event {
// Event::Damage { amount, skill, mitigation, colour: c } => {
// if target.affected(Effect::Electric) && !skill.is_tick() {
// let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
// .find(|e| e.effect == Effect::Electric).unwrap().clone();
// match meta {
// Some(EffectMeta::CastOnHit(s)) => {
// // Gurad against reflect overflow
// if !(source.affected(Effect::Reflect) && target.affected(Effect::Reflect)) {
// // Check reflect don't bother if electrocute is procing on death
// if source.affected(Effect::Reflect) && !target.is_ko() {
// game.event(Event::new(&target, &source)
// .event(Event::Reflection { skill: s }).stages(EventStages::EndPost));
// electrocute(&mut source, &mut target, resolutions, s);
// } else {
// electrocute(&mut target, &mut source, resolutions, s);
// }
// }
// },
// _ => panic!("no electrify skill"),
// };
// }
// if target.affected(Effect::Absorb) && !target.is_ko() {
// let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
// .find(|e| e.effect == Effect::Absorb).unwrap().clone();
// match meta {
// Some(EffectMeta::CastOnHit(s)) => {
// absorption(&mut source, &mut target, resolutions, skill, amount + mitigation, s);
// },
// _ => panic!("no absorb skill"),
// };
// }
// if c == Colour::Red {
// if target.affected(Effect::Counter) && !target.is_ko() {
// let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
// .find(|e| e.effect == Effect::Counter).unwrap().clone();
// match meta {
// Some(EffectMeta::CastOnHit(s)) => {
// counter_attack(&mut target, &mut source, resolutions, s);
// },
// _ => panic!("no counter skill"),
// };
// }
// }
// if target.is_ko() && event_target.green == 0 {
// // Make sure target ko is from this event
// target.effects.clear();
// game.event(Event::new(&source, &target).event(Event::Ko()).stages(EventStages::PostOnly));
// }
// },
// _ => (),
// };
// game.update_construct(&mut source);
// game.update_construct(&mut target);
// };