Merge branch 'release/1.11.2'
This commit is contained in:
commit
4b465361fb
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.11.1",
|
||||
"version": "1.11.2",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="application-name" content="mnml">
|
||||
<meta name="description" content="mnml pvp tbs">
|
||||
<meta name="description" content="1v1 pvp tbs">
|
||||
<meta name="author" content="ntr@smokestack.io">
|
||||
<title>MNML - abstract strategy</title>
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.11.1",
|
||||
"version": "1.11.2",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mnml_core"
|
||||
version = "1.11.1"
|
||||
version = "1.11.2"
|
||||
authors = ["ntr <ntr@smokestack.io>", "mashy <mashy@mnml.gg>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -499,7 +499,7 @@ impl Construct {
|
||||
return None;
|
||||
}
|
||||
|
||||
info!("reduced effect {:?}", effect);
|
||||
// info!("reduced effect {:?}", effect);
|
||||
return Some(effect);
|
||||
}).collect::<Vec<ConstructEffect>>();
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ pub enum Effect {
|
||||
// electrocute the dmg debuff
|
||||
Electric,
|
||||
Electrocute,
|
||||
Electrocuted,
|
||||
|
||||
// absorbtion is the buff
|
||||
// absorb is the increased damage
|
||||
@ -75,28 +76,32 @@ 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,
|
||||
}
|
||||
}
|
||||
|
||||
115
core/src/game.rs
115
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,
|
||||
}
|
||||
},
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-ops",
|
||||
"version": "1.11.1",
|
||||
"version": "1.11.2",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mnml"
|
||||
version = "1.11.1"
|
||||
version = "1.11.2"
|
||||
authors = ["ntr <ntr@smokestack.io>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-studios",
|
||||
"version": "1.11.1",
|
||||
"version": "1.11.2",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user