diff --git a/CHANGELOG.md b/CHANGELOG.md index 46d96690..a817f86d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,39 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed ### Changed -## [In Progress] +## [0.1.4 2019-09-17] + +### Changed +Removed self targetting, all skills can be used on any target + +`Reflect` No cooldown, 1T duration +`Purify` No cooldown +`Recharge` No cooldown + +`Link` reworked -> + Stuns caster for 3/2/1T + If target has higher green life than caster: + Deal blue damage to target equal to difference between green life + Heal with green damage to source equal to difference between green life + +`Counter` effect no longer applies immunities + Counter no cooldown + Counter applies for 1T + Counter skill now applies block at 40% / 60% / 80% reduction for 1T + Counter no longer recharges red life + +`Electrify` + No Cooldown + Duration -> 1T + Electrocute duration now 2/3/4T + +`Sustain` + Now has 1T cooldown at all levels + Has 1T duration at all levels + Now recharges red life to target (120 / 150 / 230)% + + +## [0.1.3 2019-??-??] ### Added @@ -20,20 +52,6 @@ Added `Buff` as a skill `Sustain` now grants immunity to disables. -*BALANCE* -- purify - - 1 effect from all constructs at level 2 - - removes all effects from all constructs at l3 - -- invert - - fx for buffs when applied to enemies - - invert + haste -> doubles all cooldowns - -var / skill info rpc - thresholds / bonuses - sell cost - etc - ## [0.1.2] - 2019-05-07 ### Added diff --git a/WORKLOG.md b/WORKLOG.md index 298e6f99..3b95543c 100644 --- a/WORKLOG.md +++ b/WORKLOG.md @@ -31,6 +31,7 @@ * fuck magic * empower on ko +var / skill info rpc -> sell cost / cooldown * rework vecs into sets * remove names so games/instances are copy diff --git a/server/src/effect.rs b/server/src/effect.rs index 5b3d6bba..1e959e50 100644 --- a/server/src/effect.rs +++ b/server/src/effect.rs @@ -64,11 +64,6 @@ pub enum Effect { impl Effect { pub fn immune(&self, skill: Skill) -> bool { match self { - Effect::Counter => match skill { - Skill::Attack => true, - Skill::Stun => true, - _ => skill.colours().contains(&Colour::Red) - }, Effect::Banish => true, Effect::Sustain => [ Skill::Stun, diff --git a/server/src/game.rs b/server/src/game.rs index ed2ab7e6..222ab0f6 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -1172,14 +1172,14 @@ mod tests { } game.add_skill(x_player.id, x_construct.id, x_construct.id, Skill::Counter).unwrap(); - game.add_skill(y_player.id, y_construct.id, x_construct.id, Skill::Stun).unwrap(); + game.add_skill(y_player.id, y_construct.id, x_construct.id, Skill::Attack).unwrap(); game.player_ready(x_player.id).unwrap(); game.player_ready(y_player.id).unwrap(); game = game.resolve_phase_start(); - // should not be stunned because of counter + // don't get stunned but not really stunning ¯\_(ツ)_/¯ assert!(game.player_by_id(x_player.id).unwrap().constructs[0].is_stunned() == false); // riposte assert_eq!(game.player_by_id(y_player.id).unwrap().constructs[0].green_life(), ( @@ -1209,8 +1209,8 @@ mod tests { game.add_skill(x_player.id, x_construct.id, x_construct.id, Skill::Electrify).unwrap(); game.player_ready(x_player.id).unwrap(); game.player_ready(y_player.id).unwrap(); - game = game.resolve_phase_start(); - assert!(game.construct_by_id(x_construct.id).unwrap().affected(Effect::Electric)); + // game = game.resolve_phase_start(); + // assert!(game.construct_by_id(x_construct.id).unwrap().affected(Effect::Electric)); // attack and receive debuff game.add_skill(y_player.id, y_construct.id, x_construct.id, Skill::Attack).unwrap(); diff --git a/server/src/skill.rs b/server/src/skill.rs index d0972ca9..2f122399 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -315,21 +315,17 @@ fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) -> _ => panic!("no absorb skill"), }; } - }, - Event::Immunity { skill: _, immunity } => match immunity.contains(&Effect::Counter) { - true => { + if target.affected(Effect::Counter) { let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter() .find(|e| e.effect == Effect::Counter).unwrap().clone(); match meta { Some(EffectMeta::Skill(s)) => { - resolutions = riposte(&mut target, &mut source, resolutions, s); + resolutions = counter_attack(&mut target, &mut source, resolutions, s); }, _ => panic!("no counter skill"), }; - - }, - false => (), + } }, _ => (), }; @@ -747,9 +743,6 @@ impl Skill { Skill::ElectrocuteTickPlus => 100, Skill::ElectrocuteTickPlusPlus => 130, - Skill::Counter=> 110, - Skill::CounterPlus => 145, - Skill::CounterPlusPlus => 200, Skill::CounterAttack=> 70, Skill::CounterAttackPlus => 95, Skill::CounterAttackPlusPlus => 120, @@ -758,14 +751,18 @@ impl Skill { Skill::PurifyPlus => 70, Skill::PurifyPlusPlus => 105, - Skill::Reflect=> 45, //restore blue life (heal) + Skill::Reflect=> 45, //Recharge blue life (heal) Skill::ReflectPlus => 70, Skill::ReflectPlusPlus => 100, - Skill::Recharge=> 85, //restore red and blue life (heal) + Skill::Recharge=> 85, //Recharge red and blue life (heal) Skill::RechargePlus => 130, Skill::RechargePlusPlus => 200, + Skill::Sustain => 120, // Recharge red life (heal) + Skill::SustainPlus => 150, + Skill::SustainPlusPlus => 230, + // Stun Base Skill::Sleep=> 240, //Green dmg (heal) Skill::SleepPlus => 300, @@ -891,11 +888,17 @@ impl Skill { Skill::InvertPlusPlus => vec![ConstructEffect {effect: Effect::Invert, duration: 4, meta: None, tick: None}], Skill::Counter => vec![ConstructEffect {effect: Effect::Counter, duration: 1, - meta: Some(EffectMeta::Skill(Skill::CounterAttack)), tick: None}], + meta: Some(EffectMeta::Skill(Skill::CounterAttack)), tick: None}, + ConstructEffect {effect: Effect::Block, duration: 1, + meta: Some(EffectMeta::Multiplier(60)), tick: None}], Skill::CounterPlus => vec![ConstructEffect {effect: Effect::Counter, duration: 1, - meta: Some(EffectMeta::Skill(Skill::CounterAttackPlus)), tick: None}], + meta: Some(EffectMeta::Skill(Skill::CounterAttackPlus)), tick: None}, + ConstructEffect {effect: Effect::Block, duration: 1, + meta: Some(EffectMeta::Multiplier(40)), tick: None}], Skill::CounterPlusPlus => vec![ConstructEffect {effect: Effect::Counter, duration: 1, - meta: Some(EffectMeta::Skill(Skill::CounterAttackPlusPlus)), tick: None}], + meta: Some(EffectMeta::Skill(Skill::CounterAttackPlusPlus)), tick: None}, + ConstructEffect {effect: Effect::Block, duration: 1, + meta: Some(EffectMeta::Multiplier(20)), tick: None}], Skill::Reflect => vec![ConstructEffect {effect: Effect::Reflect, duration: 1, meta: None, tick: None }], Skill::ReflectPlus => vec![ConstructEffect {effect: Effect::Reflect, duration: 1, meta: None, tick: None }], @@ -1076,7 +1079,7 @@ impl Skill { Skill::Sustain | Skill::SustainPlus | - Skill::SustainPlusPlus => None, + Skill::SustainPlusPlus => Some(1), Skill::Intercept=> Some(2), Skill::InterceptPlus => Some(2), @@ -1341,8 +1344,14 @@ fn sleep(source: &mut Construct, target: &mut Construct, mut results: Resolution } fn sustain(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { - skill.effect().into_iter() - .for_each(|e| (results.push(Resolution::new(source, target).event(target.add_effect(skill, e))))); + let red_amount = source.red_power().pct(skill.multiplier()); + results.push(Resolution::new(source, target) + .event(target.recharge(skill, red_amount, 0))); + + results.push(Resolution::new(source, target) + .event(target.add_effect(skill, skill.effect()[0])) + .stages(EventStages::PostOnly)); + return results; } @@ -1378,19 +1387,17 @@ fn buff(source: &mut Construct, target: &mut Construct, mut results: Resolutions } fn counter(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { - let red_amount = source.red_power().pct(skill.multiplier()); results.push(Resolution::new(source, target) - .event(target.recharge(skill, red_amount, 0)) - .stages(EventStages::StartEnd)); + .event(target.add_effect(skill, skill.effect()[0]))); results.push(Resolution::new(source, target) - .event(target.add_effect(skill, skill.effect()[0])) + .event(target.add_effect(skill, skill.effect()[1])) .stages(EventStages::PostOnly)); return results; } -fn riposte(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { +fn counter_attack(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { let amount = source.red_power().pct(skill.multiplier()); target.deal_red_damage(skill, amount) .into_iter() @@ -1821,7 +1828,7 @@ mod tests { sustain(&mut y.clone(), &mut y, vec![], Skill::Sustain); assert!(y.affected(Effect::Sustain)); - let mut results = blast(&mut x, &mut y, vec![], Skill::Blast); + let mut results = ruin(&mut x, &mut y, vec![], Skill::Ruin); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0); match event { Event::Immunity { skill: _, immunity } => assert!(immunity.contains(&Effect::Sustain)), @@ -2056,8 +2063,8 @@ mod tests { .learn(Skill::HealPlus); purge(&mut x, &mut y, vec![], Skill::Purge); - // current turn + 2 turns at lvl 1 - assert!(y.effects.iter().any(|e| e.effect == Effect::Purge && e.duration == 3)); + // 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()); } }