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": {