2307 lines
89 KiB
Rust
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);
|
|
// };
|