diff --git a/VERSION b/VERSION index b0f61c56..0c9cb695 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.11.1 \ No newline at end of file +1.11.2 \ No newline at end of file diff --git a/acp/package.json b/acp/package.json index 199b7393..e3c2b7f2 100644 --- a/acp/package.json +++ b/acp/package.json @@ -1,6 +1,6 @@ { "name": "mnml-client", - "version": "1.11.1", + "version": "1.11.2", "description": "", "main": "index.js", "scripts": { diff --git a/client/index.html b/client/index.html index f9a2f86c..d9d8e7ef 100644 --- a/client/index.html +++ b/client/index.html @@ -7,7 +7,7 @@ - + MNML - abstract strategy diff --git a/client/package.json b/client/package.json index cfa9c258..94c36086 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "mnml-client", - "version": "1.11.1", + "version": "1.11.2", "description": "", "main": "index.js", "scripts": { diff --git a/client/src/components/game.construct.effect.box.jsx b/client/src/components/game.construct.effect.box.jsx index 4f571533..602f2d8f 100644 --- a/client/src/components/game.construct.effect.box.jsx +++ b/client/src/components/game.construct.effect.box.jsx @@ -27,6 +27,7 @@ class GameConstructEffects extends preact.Component { && (type === 'Effect' || type === 'Removal')) return true; } if (newProps.construct !== this.props.construct) return true; + if (newProps.gameSkillInfo !== this.props.gameSkillInfo) return true; return false; } diff --git a/core/Cargo.toml b/core/Cargo.toml index 8f638279..f128fda1 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mnml_core" -version = "1.11.1" +version = "1.11.2" authors = ["ntr ", "mashy "] [dependencies] diff --git a/core/src/construct.rs b/core/src/construct.rs index 5eb26e17..3a11d06d 100644 --- a/core/src/construct.rs +++ b/core/src/construct.rs @@ -499,7 +499,7 @@ impl Construct { return None; } - info!("reduced effect {:?}", effect); + // info!("reduced effect {:?}", effect); return Some(effect); }).collect::>(); diff --git a/core/src/effect.rs b/core/src/effect.rs index c1d98d39..14391d5b 100644 --- a/core/src/effect.rs +++ b/core/src/effect.rs @@ -32,6 +32,7 @@ pub enum Effect { // electrocute the dmg debuff Electric, Electrocute, + Electrocuted, // absorbtion is the buff // absorb is the increased damage @@ -75,27 +76,31 @@ impl Effect { match self { Effect::Banish => true, - // these provide immunity for the ticks - // the base skills will still resolve - // but they have early return checks - // to ensure the effect is reapplied but damage is not - Effect::Siphoned => [ - Skill::SiphonTick, - ].contains(&skill), - - Effect::Decayed => [ - Skill::DecayTick, - ].contains(&skill), - - Effect::Triaged => [ - Skill::TriageTick, - ].contains(&skill), - Effect::Countered => [ Skill::CounterAttack, Skill::CounterAttackPlus, Skill::CounterAttackPlusPlus, ].contains(&skill), + + // these provide immunity for the ticks + // the base skills will still resolve + // but they have early return checks + // to ensure the effect is reapplied but damage is not + Effect::Decayed => [ + Skill::DecayTick, + ].contains(&skill), + + Effect::Electrocuted => [ + Skill::ElectrocuteTick, + ].contains(&skill), + + Effect::Siphoned => [ + Skill::SiphonTick, + ].contains(&skill), + + Effect::Triaged => [ + Skill::TriageTick, + ].contains(&skill), _ => false, } @@ -106,10 +111,11 @@ impl Effect { // and not included in counts pub fn hidden(&self) -> bool { match self { - Effect::Siphoned => true, - Effect::Decayed => true, - Effect::Triaged => true, Effect::Countered => true, + Effect::Decayed => true, + Effect::Electrocuted => true, + Effect::Siphoned => true, + Effect::Triaged => true, _ => false, } } diff --git a/core/src/game.rs b/core/src/game.rs index fcea46ab..fbb8f187 100644 --- a/core/src/game.rs +++ b/core/src/game.rs @@ -518,7 +518,9 @@ impl Game { .any(|c| !self.construct(c.target).is_ko() && !self.construct(c.target).immune(c.skill).is_some()); if castable { - self.action(cast, Action::Cast); + if cast.skill.cast_animation() { + self.action(cast, Action::Cast); + } if cast.skill.aoe() { self.action(cast, Action::HitAoe); } @@ -630,11 +632,11 @@ impl Game { Value::ColourSkills { construct, colour } => self.construct(construct).stat(Stat::Skills(colour)), - Value::DamageReceived { construct, colour } => + Value::DamageReceived { construct } => self.events.iter().fold(0, |dmg, e| match e { - Event::Damage { construct: event_construct, amount, mitigation:_, colour: event_colour, display: _ } => - match construct == *event_construct && colour == *event_colour { - true => dmg + amount, + Event::Damage { construct: event_construct, amount, mitigation, colour: _, display: _ } => + match construct == *event_construct { + true => amount + mitigation, false => dmg, } _ => dmg, @@ -854,7 +856,7 @@ pub enum Value { ColourSkills { construct: Uuid, colour: Colour }, Effects { construct: Uuid }, Removals { construct: Uuid }, - DamageReceived { construct: Uuid, colour: Colour }, + DamageReceived { construct: Uuid }, TickDamage { construct: Uuid, effect: Effect }, // Affected { construct: Uuid, effect: Effect }, // not an int :( } @@ -1293,10 +1295,6 @@ mod tests { } -// #[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); @@ -1476,48 +1474,6 @@ mod tests { // }; // } - // #[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() @@ -2190,7 +2146,7 @@ mod tests { }).count() == 2); - let _siphon_dmg = resolutions.iter().find_map(|r| match r.skill { + let siphon_dmg = resolutions.iter().find_map(|r| match r.skill { Skill::Siphon => { match r.event { Event::Damage { construct: _, colour: _, amount, mitigation: _, display: _ } => Some(amount), @@ -2200,24 +2156,12 @@ mod tests { _ => None }).expect("no siphon dmg"); - // let hybrid_dmg = resolutions.iter().find_map(|r| match r.skill { - // Skill::HybridBlast => { - // match r.event { - // Event::Damage { construct: _, colour: _, amount, mitigation: _, display: _ } => Some(amount), - // _ => None, - // } - // }, - // _ => None - // }).expect("no hybrid dmg"); - - // assert!(resolutions.iter().any(|r| match r.event { - // Event::Healing { construct, colour, amount, overhealing, display: _ } => { - // construct == source && (amount + overhealing) == siphon_dmg && colour == Colour::Green - // // this works - // // construct == source && (amount + overhealing) == (siphon_dmg + hybrid_dmg) && colour == Colour::Green - // }, - // _ => false, - // })); + assert!(resolutions.iter().any(|r| match r.event { + Event::Healing { construct, colour, amount, overhealing, display: _ } => { + construct == source && (amount + overhealing) == siphon_dmg && colour == Colour::Green + }, + _ => false, + })); } #[test] @@ -2258,6 +2202,31 @@ mod tests { construct == source && amount > 0 && colour == Colour::Blue, _ => false, })); + + game.resolve(Cast::new(source, player_id, target, Skill::Electrify)); + game.resolve(Cast::new(source, player_id, target, Skill::Blast)); + + let last = game.resolutions.len() - 1; + let resolutions = &game.resolutions[last]; + + let electrocute_dmg_events = resolutions.iter().filter(|r| match r.event { + Event::Damage { construct: _, colour: _, amount: _, mitigation: _, display: _ } => match r.skill { + Skill::Electrocute => true, + _ => false + }, + _ => false, + }).count(); + + let effect_events = resolutions.iter().filter(|r| match r.event { + Event::Effect { construct, effect, duration: _, display: _ } => + construct == source && effect == Effect::Electrocute, + _ => false, + }).count(); + + assert!(effect_events == 2); + assert!(electrocute_dmg_events == 1); // second electrocute application deals no damage + + } #[test] @@ -2333,13 +2302,13 @@ mod tests { let resolutions = &game.resolutions[last]; assert!(resolutions.iter().any(|r| match r.event { - Event::Damage { construct, colour, amount, mitigation: _, display: _ } => { + Event::Damage { construct, colour, amount, mitigation, display: _ } => { assert!(construct == target && amount > 0 && colour == Colour::Blue && r.skill == Skill::Blast); resolutions.iter().any(|r| match r.event { Event::Meta { construct, effect, meta } => construct == target && effect == Effect::Absorption && { match meta { - EffectMeta::AddedDamage(added_dmg) => added_dmg == amount, + EffectMeta::AddedDamage(added_dmg) => added_dmg == amount + mitigation, _ => false, } }, diff --git a/core/src/skill.rs b/core/src/skill.rs index 91aba876..653719f2 100644 --- a/core/src/skill.rs +++ b/core/src/skill.rs @@ -559,8 +559,6 @@ impl Skill { pub fn cast_animation(&self) -> bool { match self { - Skill::HybridBlast | - Skill::HasteStrike | Skill::CounterAttack| Skill::CounterAttackPlus | Skill::CounterAttackPlusPlus | // counter @@ -1004,7 +1002,7 @@ fn siphon(cast: Cast, game: &mut Game, values: Siphon) { Action::Heal { construct: cast.source, colour: Colour::Green, - amount: game.value(Value::DamageReceived { construct: cast.target, colour: Colour::Blue }).pct(100), + amount: game.value(Value::DamageReceived { construct: cast.target }).pct(100), }, ); @@ -1034,7 +1032,7 @@ fn siphon_tick(cast: Cast, game: &mut Game) { Action::Heal { construct: cast.source, colour: Colour::Green, - amount: game.value(Value::DamageReceived { construct: cast.target, colour: Colour::Blue }).pct(100), + amount: game.value(Value::DamageReceived { construct: cast.target }).pct(100), }, ); } @@ -1075,7 +1073,7 @@ fn slay(cast: Cast, game: &mut Game, values: Slay) { Action::Heal { construct: cast.source, colour: Colour::Green, - amount: game.value(Value::DamageReceived { construct: cast.target, colour: Colour::Red }).pct(values.self_heal_multi()), + amount: game.value(Value::DamageReceived { construct: cast.target }).pct(values.self_heal_multi()), }, ); } @@ -1320,7 +1318,7 @@ fn absorption(cast: Cast, game: &mut Game, values: Absorption) { Action::SetEffectMeta { construct: cast.target, effect: Effect::Absorption, - amount: game.value(Value::DamageReceived { construct: cast.source, colour: Colour::Blue }).pct(100), + amount: game.value(Value::DamageReceived { construct: cast.source }).pct(100), }, ); } @@ -1691,13 +1689,22 @@ fn electrocute(cast: Cast, game: &mut Game, values: Electrocute) { Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::ElectrocuteTick, speed: cast.speed, amount }) }, }, ); - game.action(cast, - Action::Damage { - construct: cast.target, - colour: Colour::Blue, - amount, - }, - ); + + if !game.affected(cast.target, Effect::Electrocuted) { + game.action(cast, + Action::Damage { + construct: cast.target, + colour: Colour::Blue, + amount, + }, + ); + game.action(cast, + Action::Effect { + construct: cast.target, + effect: ConstructEffect { effect: Effect::Electrocuted, duration: 1, meta: None }, // immunity to additional ticks + }, + ); + } game.action(cast, Action::Remove { @@ -1715,6 +1722,13 @@ fn electrocute_tick(cast: Cast, game: &mut Game) { amount: game.value(Value::TickDamage { construct: cast.target, effect: Effect::Electrocute }), }, ); + + game.action(cast, + Action::Effect { + construct: cast.target, + effect: ConstructEffect { effect: Effect::Electrocuted, duration: 1, meta: None }, // immunity to additional ticks + }, + ); } #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] diff --git a/ops/package.json b/ops/package.json index 7e57f7ed..9a1ed953 100644 --- a/ops/package.json +++ b/ops/package.json @@ -1,6 +1,6 @@ { "name": "mnml-ops", - "version": "1.11.1", + "version": "1.11.2", "description": "", "main": "index.js", "scripts": { diff --git a/server/Cargo.toml b/server/Cargo.toml index aaf88df0..16ced6b7 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mnml" -version = "1.11.1" +version = "1.11.2" authors = ["ntr "] [dependencies] diff --git a/studios/package.json b/studios/package.json index f7167fc8..d7abb0fd 100644 --- a/studios/package.json +++ b/studios/package.json @@ -1,6 +1,6 @@ { "name": "mnml-studios", - "version": "1.11.1", + "version": "1.11.2", "description": "", "main": "index.js", "scripts": {