diff --git a/CHANGELOG.md b/CHANGELOG.md
index 807de0fb..9a6107c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,23 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [1.6.6] - 2019-10-27
+# Added
+- Offering of draws
+ - Neither player receives a point if they agree to a draw
+ - Bots automatically agree to draws
+
+## [1.6.5] - 2019-10-25
+# Fixed
+- Stripe being blocked no longer causes unrecoverable error
+- Automatic ready up is now throttled after abandons
+- Player width styling
+
+# Changed
+- Improved wiggle animation
+- Intercept is now considered defensive by bots
+- Password restrictions relaxed
+
## [1.6.4] - 2019-10-24
### Changed
- Animations processing on client side reduced.
diff --git a/VERSION b/VERSION
index 49ebdd60..83d1a5eb 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.6.5
\ No newline at end of file
+1.6.6
\ No newline at end of file
diff --git a/acp/package.json b/acp/package.json
index 2591fabe..a1935bb7 100644
--- a/acp/package.json
+++ b/acp/package.json
@@ -1,6 +1,6 @@
{
"name": "mnml-client",
- "version": "1.6.5",
+ "version": "1.6.6",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/client/assets/styles/colours.less b/client/assets/styles/colours.less
index 79088b7c..13da2d0e 100644
--- a/client/assets/styles/colours.less
+++ b/client/assets/styles/colours.less
@@ -150,4 +150,22 @@ button {
&.green {
border-color: @green;
}
-}
\ No newline at end of file
+}
+
+@keyframes rgb {
+ 0% {
+ color: @red;
+ }
+ 25% {
+ color: @white;
+ }
+ 50% {
+ color: @blue;
+ }
+ 75% {
+ color: @white;
+ }
+ 100% {
+ color: @green;
+ }
+}
diff --git a/client/assets/styles/controls.less b/client/assets/styles/controls.less
index 2ff3ee04..54bcb375 100644
--- a/client/assets/styles/controls.less
+++ b/client/assets/styles/controls.less
@@ -144,7 +144,15 @@ aside {
&:active, &.confirming {
background: @red;
color: black;
- border: 2px solid black;
+ border: 2px solid @red;
+ }
+}
+
+.draw:not([disabled]) {
+ &:active, &.confirming {
+ background: @gray-hover;
+ color: black;
+ border: 2px solid @gray-hover;
}
}
diff --git a/client/assets/styles/game.less b/client/assets/styles/game.less
index f85ca3cf..65ad6b25 100644
--- a/client/assets/styles/game.less
+++ b/client/assets/styles/game.less
@@ -437,11 +437,12 @@
#targeting, .resolving-skill {
width: calc(100% - 1em);
}
+
+ .player {
+ width: calc(100% - 1em);
+ bottom: 3em;
+ height: calc(50% - 3em);
+ }
}
- .player {
- width: calc(100% - 1em);
- bottom: 3em;
- height: calc(50% - 3em);
- }
}
diff --git a/client/assets/styles/menu.less b/client/assets/styles/menu.less
index 0fbb7f90..672e928e 100644
--- a/client/assets/styles/menu.less
+++ b/client/assets/styles/menu.less
@@ -90,6 +90,11 @@
.login {
display: flex;
flex-flow: column;
+
+ .terms {
+ display: inline;
+ margin: 0 1em;
+ }
}
}
diff --git a/client/assets/styles/player.less b/client/assets/styles/player.less
index 616ba46f..cadd02fe 100644
--- a/client/assets/styles/player.less
+++ b/client/assets/styles/player.less
@@ -51,6 +51,11 @@
color: @yellow;
font-weight: bold;
}
+
+ .name.subscriber {
+ // animation: rgb 4s cubic-bezier(0.5, 0, 0.5, 1) 0s infinite alternate;
+ // font-weight: bold;
+ }
}
.chat {
diff --git a/client/assets/styles/styles.less b/client/assets/styles/styles.less
index e8188302..86ea5d38 100644
--- a/client/assets/styles/styles.less
+++ b/client/assets/styles/styles.less
@@ -143,7 +143,7 @@ button, input {
a {
color: whitesmoke;
- text-decoration: none;
+ // text-decoration: none;
&:hover {
color: whitesmoke;
diff --git a/client/package.json b/client/package.json
index 6c6d56fe..b6b1c359 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,12 +1,12 @@
{
"name": "mnml-client",
- "version": "1.6.5",
+ "version": "1.6.6",
"description": "",
"main": "index.js",
"scripts": {
"start": "parcel watch index.html --out-dir /var/lib/mnml/public/current",
"anims": "parcel watch animations.html --no-hmr --out-dir /var/lib/mnml/public/current",
- "build": "parcel build index.html",
+ "build": "parcel build index.html --no-source-maps",
"scss": "node-sass --watch assets/scss -o assets/styles",
"lint": "eslint --fix --ext .jsx src/",
"test": "echo \"Error: no test specified\" && exit 1"
diff --git a/client/src/app.jsx b/client/src/app.jsx
index cfc877b7..0d668980 100644
--- a/client/src/app.jsx
+++ b/client/src/app.jsx
@@ -15,10 +15,6 @@ const registerEvents = require('./events');
const Mnml = require('./components/mnml');
-if (process.env.NODE_ENV !== 'development') {
- LogRocket.init('yh0dy3/mnml');
-}
-
function stripeKey() {
if (window.location.host === 'mnml.gg') return 'pk_live_fQGrL1uWww2ot8W1G7vTySAv004ygmnMXq';
return 'pk_test_Cb49tTqTXpzk7nEmlGzRrNJg00AU0aNZDj';
@@ -40,9 +36,12 @@ events.setWs(ws);
const App = () => (
-
-
-
+ {window.Stripe
+ ?
+
+
+ :
+ }
);
diff --git a/client/src/components/account.box.jsx b/client/src/components/account.box.jsx
index c6383c55..0ff61b8f 100644
--- a/client/src/components/account.box.jsx
+++ b/client/src/components/account.box.jsx
@@ -101,11 +101,13 @@ function AccountBox(args) {
// );
// }
+ const nameClass = `name ${account.subscribed ? 'subscriber' : ''}`;
+
return (
-
{account.name}
+
{account.name}
);
diff --git a/client/src/components/anims/wiggle.jsx b/client/src/components/anims/wiggle.jsx
index a9615181..5886a47d 100644
--- a/client/src/components/anims/wiggle.jsx
+++ b/client/src/components/anims/wiggle.jsx
@@ -1,22 +1,24 @@
const anime = require('animejs').default;
function wiggle(id, idle) {
+ if (!idle) return true;
const duration = 300;
const target = document.getElementById(id);
const x = window.innerWidth * 0.01 * (Math.round(Math.random()) ? Math.random() : -Math.random());
const y = window.innerHeight * 0.01 * (Math.round(Math.random()) ? Math.random() : -Math.random());
-
+
+ const originalX = parseFloat(idle.animations[0].currentValue);
+ const originalY = parseFloat(idle.animations[1].currentValue);
// console.log(x, y);
return anime({
targets: target,
- rotate: 0,
- translateX: [x, -x, 0],
- translateY: [y, -y, 0],
+ translateX: [originalX + x, originalX - x, originalX],
+ translateY: [originalY + y, originalY - y, originalY],
duration,
easing: 'easeInOutSine',
// direction: 'alternate',
begin: idle.pause,
- complete: idle.restart,
+ complete: idle.play,
});
}
diff --git a/client/src/components/game.ctrl.btns.jsx b/client/src/components/game.ctrl.btns.jsx
index 671e9d62..3918b5ca 100644
--- a/client/src/components/game.ctrl.btns.jsx
+++ b/client/src/components/game.ctrl.btns.jsx
@@ -75,7 +75,7 @@ function GameCtrlBtns(args) {
} = args;
if (!game) return false;
- const finished = game.phase === 'Finish';
+ const finished = game.phase === 'Finished';
function quitClick() {
getInstanceState();
diff --git a/client/src/components/game.ctrl.btns.top.jsx b/client/src/components/game.ctrl.btns.top.jsx
index 4ab0d543..8e09718c 100644
--- a/client/src/components/game.ctrl.btns.top.jsx
+++ b/client/src/components/game.ctrl.btns.top.jsx
@@ -8,16 +8,23 @@ const addState = connect(
const {
ws,
game,
+ account,
} = state;
function sendAbandon() {
return ws.sendInstanceAbandon(game.instance);
}
+ function sendDraw() {
+ return ws.sendGameOfferDraw(game.id);
+ }
+
return {
game,
+ account,
sendAbandon,
+ sendDraw,
};
},
function receiveDispatch(dispatch) {
@@ -34,13 +41,18 @@ const addState = connect(
function GameCtrlTopBtns(args) {
const {
game,
+ account,
leave,
sendAbandon,
+ sendDraw,
} = args;
const finished = game && game.phase === 'Finished';
- const { abandonState } = this.state;
+ const { abandonState, drawState } = this.state;
+
+ const player = game.players.find(p => p.id === account.id);
+ const drawOffered = player && player.draw_offered;
const abandonStateTrue = e => {
e.stopPropagation();
@@ -48,16 +60,29 @@ function GameCtrlTopBtns(args) {
setTimeout(() => this.setState({ abandonState: false }), 2000);
};
+ const drawStateTrue = e => {
+ e.stopPropagation();
+ this.setState({ drawState: true });
+ setTimeout(() => this.setState({ drawState: false }), 2000);
+ };
+
const abandonClasses = `abandon ${abandonState ? 'confirming' : ''}`;
const abandonText = abandonState ? 'Confirm' : 'Abandon';
const abandonAction = abandonState ? sendAbandon : abandonStateTrue;
const abandonBtn = {abandonText} ;
- const leaveBtn = Leave ;
+
+ const drawClasses = `draw ${drawState || drawOffered ? 'confirming' : ''}`;
+ const drawText = drawOffered
+ ? 'Offered'
+ : drawState ? 'Draw' : 'Offer';
+ const drawAction = drawState ? sendDraw : drawStateTrue;
+ const drawBtn = {drawText} ;
return (
- {finished ? leaveBtn : abandonBtn}
+ {abandonBtn}
+ {drawBtn}
);
}
diff --git a/client/src/components/game.footer.jsx b/client/src/components/game.footer.jsx
index 101318a4..4a1589b0 100644
--- a/client/src/components/game.footer.jsx
+++ b/client/src/components/game.footer.jsx
@@ -82,7 +82,7 @@ function GameFooter(props) {
const now = Date.now();
const end = Date.parse(game.phase_end);
const timerPct = ((now - zero) / (end - zero) * 100);
- const displayPct = game.phase === 'Finish' || !game.phase_end
+ const displayPct = game.phase === 'Finished' || !game.phase_end
? 0
: Math.min(timerPct, 100);
@@ -108,7 +108,7 @@ function GameFooter(props) {
return (
{timer}
- {game.phase === 'Finish' && quitBtn }
+ {game.phase === 'Finished' && quitBtn }
{game.phase === 'Skill' && readyBtn }
);
diff --git a/client/src/components/play.footer.jsx b/client/src/components/play.footer.jsx
index f8a8479a..1f059064 100644
--- a/client/src/components/play.footer.jsx
+++ b/client/src/components/play.footer.jsx
@@ -3,8 +3,6 @@ const { connect } = require('preact-redux');
const { errorToast, infoToast } = require('../utils');
-const AccountBox = require('./account.box');
-
const addState = connect(
function receiveState(state) {
const {
diff --git a/client/src/components/play.jsx b/client/src/components/play.jsx
index 25906879..40f5b657 100644
--- a/client/src/components/play.jsx
+++ b/client/src/components/play.jsx
@@ -203,6 +203,7 @@ function Play(args) {
diff --git a/client/src/components/player.box.jsx b/client/src/components/player.box.jsx
index 29ee6532..6cace8a4 100644
--- a/client/src/components/player.box.jsx
+++ b/client/src/components/player.box.jsx
@@ -68,24 +68,33 @@ function Scoreboard(args) {
};
const winner = player.score === 'Win';
+ const chatText = chat
+ ? chat
+ : player.draw_offered
+ ? 'draw'
+ : '\u00A0';
if (!isPlayer) {
+ const nameClass = `name ${player.img ? 'subscriber' : ''}`;
return (
{scoreText()}
-
{player.name}
+
{player.name}
-
{chat || '\u00A0'}
+
{chatText}
);
}
+ const boxClass = `player-box bottom ${winner ? 'winner': player.ready ? 'ready' : ''}`;
+ const nameClass = `name ${player.img ? 'subscriber' : ''}`;
+
return (
-
-
{chat || '\u00A0'}
+
+
{chatText}
{scoreText()}
-
{player.name}
+
{player.name}
);
diff --git a/client/src/components/shop.jsx b/client/src/components/shop.jsx
index 08a79fad..7e23bc60 100644
--- a/client/src/components/shop.jsx
+++ b/client/src/components/shop.jsx
@@ -48,9 +48,12 @@ function Shop(args) {
ยค {account.balance}
-
-
-
+ {window.Stripe
+ ?
+
+
+ :
Please unblock Stripe to use the store
+ }
);
diff --git a/client/src/components/welcome.jsx b/client/src/components/welcome.jsx
index 790fe3ae..558e5719 100644
--- a/client/src/components/welcome.jsx
+++ b/client/src/components/welcome.jsx
@@ -53,7 +53,7 @@ function Welcome() {
Welcome to mnml.
-
Turn-based 1v1 strategy game in an abstract setting.
+
MNML is a turn-based 1v1 strategy game in an abstract setting.
Build a unique team of 3 constructs from a range of skills and specialisations.
Outplay your opponent in multiple rounds by adapting to an always shifting meta.
@@ -62,6 +62,7 @@ function Welcome() {
Free to play, no pay to win. Register to start playing.
+
Tutorial Playthrough on YouTube
{pageEl()}
diff --git a/client/src/components/welcome.register.jsx b/client/src/components/welcome.register.jsx
index 99f8baed..68b6fedb 100644
--- a/client/src/components/welcome.register.jsx
+++ b/client/src/components/welcome.register.jsx
@@ -58,7 +58,7 @@ function Register(args) {
value={this.state.name}
onInput={linkState(this, 'name')}
/>
- Password - min 12 chars
+ Password - min 4 chars
- Confirm agreement to terms of service
+ Confirm agreement to terms of service.
window.open('/tos.html')}>VIEW
https
server {
server_name mnml.gg;
@@ -91,8 +73,3 @@ server {
server_name minimal.gg;
return 301 https://mnml.gg$request_uri;
}
-
-server {
- server_name minimalstudios.com.au;
- return 301 https://minimalstudios.com.au$request_uri;
-}
diff --git a/ops/package.json b/ops/package.json
index 40211410..ae05c7f0 100755
--- a/ops/package.json
+++ b/ops/package.json
@@ -1,6 +1,6 @@
{
"name": "mnml-ops",
- "version": "1.6.5",
+ "version": "1.6.6",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/server/Cargo.toml b/server/Cargo.toml
index 4df35fa1..c80430f6 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mnml"
-version = "1.6.5"
+version = "1.6.6"
authors = ["ntr "]
[dependencies]
diff --git a/server/src/account.rs b/server/src/account.rs
index 56921e2c..22224568 100644
--- a/server/src/account.rs
+++ b/server/src/account.rs
@@ -20,7 +20,7 @@ use img;
use failure::Error;
use failure::{err_msg, format_err};
-static PASSWORD_MIN_LEN: usize = 11;
+static PASSWORD_MIN_LEN: usize = 3;
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Account {
@@ -189,7 +189,7 @@ pub fn new_img(tx: &mut Transaction, id: Uuid) -> Result {
}
pub fn set_password(tx: &mut Transaction, id: Uuid, current: &String, password: &String) -> Result {
- if password.len() < PASSWORD_MIN_LEN {
+ if password.len() < PASSWORD_MIN_LEN || password.len() > 100 {
return Err(MnmlHttpError::PasswordUnacceptable);
}
@@ -318,7 +318,7 @@ pub fn set_subscribed(tx: &mut Transaction, id: Uuid, subscribed: bool) -> Resul
}
pub fn create(name: &String, password: &String, tx: &mut Transaction) -> Result {
- if password.len() < PASSWORD_MIN_LEN {
+ if password.len() < PASSWORD_MIN_LEN || password.len() > 100 {
return Err(MnmlHttpError::PasswordUnacceptable);
}
@@ -328,7 +328,7 @@ pub fn create(name: &String, password: &String, tx: &mut Transaction) -> Result<
let id = Uuid::new_v4();
let img = Uuid::new_v4();
- let rounds = 8;
+ let rounds = 12;
let password = hash(&password, rounds)?;
let mut rng = thread_rng();
diff --git a/server/src/game.rs b/server/src/game.rs
index 0421ab65..12a175b4 100644
--- a/server/src/game.rs
+++ b/server/src/game.rs
@@ -27,7 +27,7 @@ pub enum Phase {
Start,
Skill,
Resolve,
- Finish,
+ Finished,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
@@ -325,6 +325,30 @@ impl Game {
return Ok(self);
}
+ fn offer_draw(mut self, player_id: Uuid) -> Result {
+ if self.phase != Phase::Skill {
+ return Err(err_msg("game not in skill phase"));
+ }
+
+ {
+ let player = self.player_by_id(player_id)?;
+ player.draw_offered = true;
+ }
+
+ // bots automatically accept draws
+ for player in self.players.iter_mut() {
+ if player.bot {
+ player.draw_offered = true;
+ }
+ }
+
+ if self.players.iter().all(|p| p.draw_offered) {
+ return Ok(self.finish());
+ }
+
+ return Ok(self);
+ }
+
fn clear_skill(&mut self, player_id: Uuid) -> Result<&mut Game, Error> {
self.player_by_id(player_id)?;
if self.phase != Phase::Skill {
@@ -564,15 +588,18 @@ impl Game {
// }
pub fn finished(&self) -> bool {
- self.players.iter().any(|t| t.constructs.iter().all(|c| c.is_ko()))
+ self.phase == Phase::Finished || self.players.iter().any(|t| t.constructs.iter().all(|c| c.is_ko()))
}
pub fn winner(&self) -> Option<&Player> {
- self.players.iter().find(|t| t.constructs.iter().any(|c| !c.is_ko()))
+ match self.players.iter().any(|t| t.constructs.iter().all(|c| c.is_ko())) {
+ true => self.players.iter().find(|t| t.constructs.iter().any(|c| !c.is_ko())),
+ false => None,
+ }
}
fn finish(mut self) -> Game {
- self.phase = Phase::Finish;
+ self.phase = Phase::Finished;
// self.log.push(format!("Game finished."));
// {
@@ -594,7 +621,7 @@ impl Game {
}
pub fn upkeep(mut self) -> Game {
- if self.phase == Phase::Finish {
+ if self.phase == Phase::Finished {
return self;
}
@@ -903,6 +930,15 @@ pub fn game_skill(tx: &mut Transaction, account: &Account, game_id: Uuid, constr
Ok(game)
}
+pub fn game_offer_draw(tx: &mut Transaction, account: &Account, game_id: Uuid) -> Result {
+ let game = game_get(tx, game_id)?
+ .offer_draw(account.id)?;
+
+ game_update(tx, &game)?;
+
+ Ok(game)
+}
+
pub fn game_skill_clear(tx: &mut Transaction, account: &Account, game_id: Uuid) -> Result {
let mut game = game_get(tx, game_id)?;
@@ -1051,7 +1087,7 @@ mod tests {
game = game.resolve_phase_start();
- assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
+ assert!([Phase::Skill, Phase::Finished].contains(&game.phase));
return;
}
@@ -1117,7 +1153,7 @@ mod tests {
game = game.resolve_phase_start();
assert!(!game.player_by_id(y_player.id).unwrap().constructs[0].is_stunned());
- assert!(game.phase == Phase::Finish);
+ assert!(game.phase == Phase::Finished);
}
#[test]
@@ -1423,7 +1459,7 @@ mod tests {
assert!(game.skill_phase_finished());
game = game.resolve_phase_start();
- assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
+ assert!([Phase::Skill, Phase::Finished].contains(&game.phase));
// kill a construct
game.player_by_id(i_player.id).unwrap().construct_by_id(i_construct.id).unwrap().green_life.reduce(u64::max_value());
diff --git a/server/src/instance.rs b/server/src/instance.rs
index 8c92a821..2e65b9d6 100644
--- a/server/src/instance.rs
+++ b/server/src/instance.rs
@@ -317,7 +317,13 @@ impl Instance {
self.phase_start = Utc::now();
self.phase_end = self.time_control.vbox_phase_end();
+ let bits = match self.rounds.len() > 0 {
+ true => 12 + 6 * self.rounds.len(),
+ false => 0,
+ };
+
self.players.iter_mut().for_each(|p| {
+ p.vbox.balance_add(bits.into());
p.set_ready(false);
p.vbox.fill();
});
@@ -329,28 +335,18 @@ impl Instance {
}
fn finish_condition(&mut self) -> bool {
- // tennis
- for player in self.players.iter() {
- if player.score == Score::Win {
- self.winner = Some(player.id);
- return true;
- }
- }
- // Game defaults to lose otherwise
- if self.rounds.len() < 4 {
- return false;
- }
-
- // both players afk
- if self.players.iter().all(|p| p.score == Score::Zero) {
- return true;
- }
-
- return false;
+ self.players.iter().any(|p| p.score == Score::Win)
}
pub fn finish(&mut self) -> &mut Instance {
self.phase = InstancePhase::Finished;
+
+ for player in self.players.iter() {
+ if player.score == Score::Win {
+ self.winner = Some(player.id);
+ }
+ }
+
self
}
@@ -412,38 +408,14 @@ impl Instance {
}
// if you don't win, you lose
- // ties can happen if both players forfeit
- // in this case we just finish the game and
- // dock them 10k mmr
- let winner_id = match game.winner() {
- Some(w) => w.id,
- None => return Ok(self.finish()),
- };
-
- let bits = 12 + 6 * self.rounds.len();
-
- {
- let loser = self.players.iter()
- .find(|p| p.id != winner_id)
- .map(|p| p.score)
- .unwrap();
-
+ // ties can happen if both players agree to a draw
+ // or ticks fire and knock everybody out
+ if let Some(winner) = game.winner() {
let winner = self.players.iter_mut()
- .find(|p| p.id == winner_id)
+ .find(|p| p.id == winner.id)
.unwrap();
-
- winner.score = winner.score.add_win(&loser);
- winner.vbox.balance_add(bits.into());
- }
-
- {
- let loser = self.players.iter_mut()
- .find(|p| p.id != winner_id)
- .unwrap();
-
- loser.score = loser.score.add_loss();
- loser.vbox.balance_add(bits.into());
- }
+ winner.score = winner.score.add_win(&Score::Zero);
+ };
if self.all_games_finished() {
self.next_round();
@@ -799,7 +771,7 @@ pub fn instance_state(tx: &mut Transaction, instance_id: Uuid) -> Result
Ok(RpcMessage::GameState(game_ready(&mut tx, account, id)?)),
+ RpcRequest::GameOfferDraw { game_id } =>
+ Ok(RpcMessage::GameState(game_offer_draw(&mut tx, account, game_id)?)),
+
RpcRequest::InstancePractice {} =>
Ok(RpcMessage::InstanceState(instance_practice(&mut tx, account)?)),
@@ -450,6 +454,7 @@ pub fn start(pool: PgPool, events_tx: CbSender, stripe: StripeClient) {
}
// we done
Err(_e) => {
+ // info!("{:?}", e);
break;
},
};
diff --git a/server/src/skill.rs b/server/src/skill.rs
index 75a6094d..2e98af9b 100644
--- a/server/src/skill.rs
+++ b/server/src/skill.rs
@@ -1264,6 +1264,9 @@ impl Skill {
Skill::Invert|
Skill::InvertPlus |
Skill::InvertPlusPlus |
+ Skill::Intercept|
+ Skill::InterceptPlus |
+ Skill::InterceptPlusPlus |
Skill::Counter|
Skill::CounterPlus |
Skill::CounterPlusPlus |
@@ -2083,7 +2086,7 @@ mod tests {
let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event {
- Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256.pct(Skill::SiphonTick.multiplier())
+ Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256.pct(Skill::SiphonTick.multiplier())
+ 220.pct(Skill::SiphonTick.multiplier())),
_ => panic!("not damage siphon"),
};