Merge tag '1.3.0' into develop

1.3.0
This commit is contained in:
ntr 2019-09-06 17:45:22 +10:00
commit 76a8db35e0
15 changed files with 136 additions and 187 deletions

View File

@ -1 +1 @@
1.2.0 1.3.0

View File

@ -1,6 +1,6 @@
{ {
"name": "mnml-client", "name": "mnml-client",
"version": "1.2.0", "version": "1.3.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@ -208,6 +208,7 @@ button[disabled] {
} }
.options { .options {
display: flex;
width: 50%; width: 50%;
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "mnml-client", "name": "mnml-client",
"version": "1.2.0", "version": "1.3.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@ -9,7 +9,6 @@ const shapes = require('./shapes');
function InfoComponent(args) { function InfoComponent(args) {
const { const {
itemInfo, itemInfo,
combiner,
player, player,
info, info,
} = args; } = args;
@ -25,6 +24,8 @@ function InfoComponent(args) {
<p>double clicking items in the <b>VBOX</b> will purchase and move them to your <b>INVENTORY</b>.</p> <p>double clicking items in the <b>VBOX</b> will purchase and move them to your <b>INVENTORY</b>.</p>
<p> <p>
hover over an item to see its effects and combinations.<br /> hover over an item to see its effects and combinations.<br />
combine a <b>SKILL</b> or <b>SPEC</b> with 2 <b>COLOURS</b> to create an item.<br />
combine 3 of the same item to upgrade it.<br />
click an item and then click a construct to equip that item to it.<br /> click an item and then click a construct to equip that item to it.<br />
</p> </p>
<p>click the <b>READY</b> button on the right to progress to the <b>GAME PHASE</b>.</p> <p>click the <b>READY</b> button on the right to progress to the <b>GAME PHASE</b>.</p>
@ -40,17 +41,11 @@ function InfoComponent(args) {
const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/;
const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]());
const itemSource = itemInfo.combos.filter(c => c.item === info);
const itemSourceInfo = itemSource.length
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
: false;
const itemRegEx = /(Red|Blue|Green)/;
const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
return ( return (
<div class="info-skill"> <div class="info-skill">
<h2>{fullInfo.item}</h2> <h2>{fullInfo.item}</h2>
<h3>{itemSourceDescription}</h3> <h3>SKILL</h3>
<div> {infoDescription} </div> <div>{infoDescription}</div>
</div> </div>
); );
} }
@ -144,6 +139,7 @@ function InfoComponent(args) {
return ( return (
<div class="info-spec"> <div class="info-spec">
<h2>{info}</h2> <h2>{info}</h2>
<h3>SPEC</h3>
<div>{infoDescription}</div> <div>{infoDescription}</div>
<div class="thresholds"> <div class="thresholds">
{thresholds} {thresholds}
@ -162,30 +158,11 @@ function InfoComponent(args) {
function Combos() { function Combos() {
if (!player) return false; if (!player) return false;
// show recipe for what's in combiner
if (combiner.some(u => u !== null)) {
const filteredCombos = itemInfo.combos
.filter(combo => combiner.every(u => u === null
|| combo.components.includes(player.vbox.bound[u])));
if (filteredCombos.length > 6) return false;
return (
<table>
<tbody>
{filteredCombos.map((c, i) =>
<tr key={i} >
<td class="highlight" >{convertItem(c.item)}</td>
{c.components.map((u, j) => <td key={j}>{convertItem(u)}</td>)}
</tr>
)}
</tbody>
</table>
);
}
if (!info) return false; if (!info) return false;
const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info)); const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info));
if (vboxCombos.length > 6) return false; if (vboxCombos.length > 6) return false;
return ( return (
<table class="combos"> <table class="combos">
<tbody> <tbody>

View File

@ -14,7 +14,6 @@ const addState = connect(
player, player,
combiner, combiner,
reclaiming, reclaiming,
vboxHighlight,
vboxSelected, vboxSelected,
itemInfo, itemInfo,
itemUnequip, itemUnequip,
@ -49,7 +48,6 @@ const addState = connect(
sendVboxCombine, sendVboxCombine,
sendVboxDiscard, sendVboxDiscard,
sendVboxReclaim, sendVboxReclaim,
vboxHighlight,
vboxSelected, vboxSelected,
itemInfo, itemInfo,
itemUnequip, itemUnequip,
@ -70,10 +68,6 @@ const addState = connect(
return dispatch(actions.setInfo(item)); return dispatch(actions.setInfo(item));
} }
function setVboxHighlight(v) {
return dispatch(actions.setVboxHighlight(v));
}
function setVboxSelected(v) { function setVboxSelected(v) {
return dispatch(actions.setVboxSelected(v)); return dispatch(actions.setVboxSelected(v));
} }
@ -86,7 +80,6 @@ const addState = connect(
setCombiner, setCombiner,
setReclaiming, setReclaiming,
setInfo, setInfo,
setVboxHighlight,
setVboxSelected, setVboxSelected,
setItemEquip, setItemEquip,
}; };
@ -105,7 +98,6 @@ function Vbox(args) {
sendVboxCombine, sendVboxCombine,
sendVboxDiscard, sendVboxDiscard,
sendVboxReclaim, sendVboxReclaim,
// vboxHighlight,
setCombiner, setCombiner,
setInfo, setInfo,
@ -118,19 +110,12 @@ function Vbox(args) {
sendItemUnequip, sendItemUnequip,
setReclaiming, setReclaiming,
setVboxHighlight,
} = args; } = args;
if (!player) return false; if (!player) return false;
const { vbox } = player; const { vbox } = player;
const vboxSelecting = vboxSelected.length; const vboxSelecting = vboxSelected.length;
// function setHighlight(type) {
// if (type === 'skill') return setVboxHighlight(itemInfo.items.filter(v => v.skill).map(v => v.item));
// if (type === 'spec') return setVboxHighlight(itemInfo.items.filter(v => v.spec).map(v => v.item));
// return false;
// }
function combinerChange(newCombiner) { function combinerChange(newCombiner) {
setCombiner(newCombiner); setCombiner(newCombiner);
@ -140,20 +125,7 @@ function Vbox(args) {
setItemEquip(null); setItemEquip(null);
} }
if (newCombiner.every(c => c === null)) return setVboxHighlight([]); return true;
const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv);
const filteredCombos = itemInfo.combos
.filter(combo => combinerValues.every(u => combo.components.includes(u)));
const comboValues = itemInfo.items.filter(v => {
if (!filteredCombos.some(c => c.components.includes(v.item))) return false;
if (!['Red', 'Green', 'Blue'].includes(v.item) && combinerValues.includes(v.item)) return false;
return true;
});
return setVboxHighlight(comboValues.map(v => v.item));
} }
// //

View File

@ -50,7 +50,6 @@ module.exports = {
teamPage: createReducer(0, 'SET_TEAM_PAGE'), teamPage: createReducer(0, 'SET_TEAM_PAGE'),
teamSelect: createReducer([null, null, null], 'SET_TEAM_SELECT'), teamSelect: createReducer([null, null, null], 'SET_TEAM_SELECT'),
vboxHighlight: createReducer([], 'SET_VBOX_HIGHLIGHT'),
vboxSelected: createReducer([], 'SET_VBOX_SELECTED'), vboxSelected: createReducer([], 'SET_VBOX_SELECTED'),
ws: createReducer(null, 'SET_WS'), ws: createReducer(null, 'SET_WS'),

View File

@ -200,7 +200,7 @@ function createSocket(events) {
let pongTimeout; let pongTimeout;
function onPong() { function onPong() {
events.setPing(Date.now() - ping); events.setPing(Date.now() - ping);
pongTimeout = setTimeout(sendPing, 1000); // pongTimeout = setTimeout(sendPing, 1000);
} }
// ------------- // -------------

View File

@ -1,6 +1,6 @@
{ {
"name": "mnml-ops", "name": "mnml-ops",
"version": "1.2.0", "version": "1.3.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mnml" name = "mnml"
version = "1.2.0" version = "1.3.0"
authors = ["ntr <ntr@smokestack.io>"] authors = ["ntr <ntr@smokestack.io>"]
[dependencies] [dependencies]

View File

@ -10,7 +10,7 @@ use postgres::transaction::Transaction;
use http::MnmlHttpError; use http::MnmlHttpError;
use names::{name as generate_name}; use names::{name as generate_name};
use construct::{Construct, construct_recover, construct_spawn}; use construct::{Construct, ConstructSkeleton, construct_spawn};
use instance::{Instance, instance_delete}; use instance::{Instance, instance_delete};
use mtx::{Mtx, FREE_MTX}; use mtx::{Mtx, FREE_MTX};
use pg::Db; use pg::Db;
@ -350,23 +350,20 @@ pub fn constructs(tx: &mut Transaction, account: &Account) -> Result<Vec<Constru
let result = tx let result = tx
.query(query, &[&account.id])?; .query(query, &[&account.id])?;
let constructs: Result<Vec<Construct>, _> = result.iter() let mut constructs = result.iter()
.map(|row| { .filter_map(|row| {
let construct_bytes: Vec<u8> = row.get(0); let construct_bytes: Vec<u8> = row.get(0);
match from_slice::<Construct>(&construct_bytes) { match from_slice::<ConstructSkeleton>(&construct_bytes) {
Ok(c) => Ok(c), Ok(s) => Some(s),
Err(_e) => construct_recover(construct_bytes, tx), Err(e) => {
warn!("{:?}", e);
None
},
} }
}) })
.collect(); .map(|sk| Construct::from_skeleton(&sk))
.collect::<Vec<Construct>>();
// catch any errors
if constructs.is_err() {
warn!("{:?}", constructs);
return Err(err_msg("could not deserialise a construct"));
}
let mut constructs = constructs.unwrap();
constructs.sort_by_key(|c| c.id); constructs.sort_by_key(|c| c.id);
return Ok(constructs); return Ok(constructs);
} }
@ -382,23 +379,19 @@ pub fn team(tx: &mut Transaction, account: &Account) -> Result<Vec<Construct>, E
let result = tx let result = tx
.query(query, &[&account.id])?; .query(query, &[&account.id])?;
let constructs: Result<Vec<Construct>, _> = result.iter() let mut constructs = result.iter()
.map(|row| { .filter_map(|row| {
let construct_bytes: Vec<u8> = row.get(0); let construct_bytes: Vec<u8> = row.get(0);
match from_slice::<Construct>(&construct_bytes) { match from_slice::<ConstructSkeleton>(&construct_bytes) {
Ok(c) => Ok(c), Ok(s) => Some(s),
Err(_e) => construct_recover(construct_bytes, tx), Err(e) => {
warn!("{:?}", e);
None
},
} }
}) })
.collect(); .map(|sk| Construct::from_skeleton(&sk))
.collect::<Vec<Construct>>();
// catch any errors
if constructs.is_err() {
warn!("{:?}", constructs);
return Err(err_msg("could not deserialise a construct"));
}
let mut constructs = constructs.unwrap();
if constructs.len() != 3 { if constructs.len() != 3 {
return Err(format_err!("team not size 3 account={:?}", account)); return Err(format_err!("team not size 3 account={:?}", account));

View File

@ -187,9 +187,10 @@ impl ConstructStat {
} }
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]
pub struct ConstructRecover { pub struct ConstructSkeleton {
pub id: Uuid, pub id: Uuid,
pub account: Uuid, pub account: Uuid,
pub img: Uuid,
pub name: String, pub name: String,
} }
@ -236,6 +237,27 @@ impl Construct {
}; };
} }
pub fn from_skeleton(skeleton: &ConstructSkeleton) -> Construct {
return Construct {
id: skeleton.id,
account: skeleton.id,
img: skeleton.img,
name: skeleton.name.clone(),
.. Construct::new()
};
}
pub fn to_skeleton(&self) -> ConstructSkeleton {
ConstructSkeleton {
id: self.id,
account: self.id,
img: self.img,
name: self.name.clone(),
}
}
pub fn named(mut self, name: &String) -> Construct { pub fn named(mut self, name: &String) -> Construct {
self.name = name.clone(); self.name = name.clone();
self self
@ -827,10 +849,9 @@ pub fn construct_get(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result
let result = result.iter().next().ok_or(format_err!("construct {:} not found", id))?; let result = result.iter().next().ok_or(format_err!("construct {:} not found", id))?;
let construct_bytes: Vec<u8> = result.get(0); let construct_bytes: Vec<u8> = result.get(0);
let construct = from_slice::<Construct>(&construct_bytes) let skeleton = from_slice::<ConstructSkeleton>(&construct_bytes)?;
.or_else(|_| construct_recover(construct_bytes, tx))?;
return Ok(construct); return Ok(Construct::from_skeleton(&skeleton));
} }
pub fn construct_select(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result<Construct, Error> { pub fn construct_select(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result<Construct, Error> {
@ -847,10 +868,9 @@ pub fn construct_select(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Res
let result = result.iter().next().ok_or(format_err!("construct {:} not found", id))?; let result = result.iter().next().ok_or(format_err!("construct {:} not found", id))?;
let construct_bytes: Vec<u8> = result.get(0); let construct_bytes: Vec<u8> = result.get(0);
let construct = from_slice::<Construct>(&construct_bytes) let skeleton = from_slice::<ConstructSkeleton>(&construct_bytes)?;
.or_else(|_| construct_recover(construct_bytes, tx))?;
return Ok(construct); return Ok(Construct::from_skeleton(&skeleton));
} }
pub fn construct_spawn(tx: &mut Transaction, account: Uuid, name: String, team: bool) -> Result<Construct, Error> { pub fn construct_spawn(tx: &mut Transaction, account: Uuid, name: String, team: bool) -> Result<Construct, Error> {
@ -878,7 +898,7 @@ pub fn construct_spawn(tx: &mut Transaction, account: Uuid, name: String, team:
} }
pub fn construct_write(tx: &mut Transaction, construct: Construct) -> Result<Construct, Error> { pub fn construct_write(tx: &mut Transaction, construct: Construct) -> Result<Construct, Error> {
let construct_bytes = to_vec(&construct)?; let construct_bytes = to_vec(&construct.to_skeleton())?;
let query = " let query = "
UPDATE constructs UPDATE constructs
@ -897,20 +917,6 @@ pub fn construct_write(tx: &mut Transaction, construct: Construct) -> Result<Con
return Ok(construct); return Ok(construct);
} }
pub fn construct_recover(construct_bytes: Vec<u8>, tx: &mut Transaction) -> Result<Construct, Error> {
let c = from_slice::<ConstructRecover>(&construct_bytes)?;
let mut construct = Construct::new()
.named(&c.name)
.set_account(c.account);
construct.id = c.id;
info!("recovered construct {:?}", c.name);
return construct_write(tx, construct);
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use construct::*; use construct::*;

View File

@ -132,12 +132,12 @@ impl Events {
}, },
Event::Subscribe(id, obj) => { Event::Subscribe(id, obj) => {
info!("subscribe id={:?} object={:?}", id, obj); trace!("subscribe id={:?} object={:?}", id, obj);
match self.clients.get_mut(&id) { match self.clients.get_mut(&id) {
Some(client) => { Some(client) => {
client.subs.insert(obj); client.subs.insert(obj);
info!("client={:?} subscriptions={:?}", id, client.subs.len()); trace!("client={:?} subscriptions={:?}", id, client.subs.len());
Ok(()) Ok(())
}, },
None => return Err(format_err!("unknown client {:?}", id)) None => return Err(format_err!("unknown client {:?}", id))
@ -145,12 +145,12 @@ impl Events {
}, },
Event::Unsubscribe(id, obj) => { Event::Unsubscribe(id, obj) => {
info!("unsubscribe id={:?} object={:?}", id, obj); trace!("unsubscribe id={:?} object={:?}", id, obj);
match self.clients.get_mut(&id) { match self.clients.get_mut(&id) {
Some(mut client) => { Some(mut client) => {
client.subs.remove(&obj); client.subs.remove(&obj);
info!("unsubscribe subscriptions removed={:?}", client.subs.len()); trace!("unsubscribe subscriptions removed={:?}", client.subs.len());
Ok(()) Ok(())
}, },
None => return Err(format_err!("unknown client {:?}", id)) None => return Err(format_err!("unknown client {:?}", id))
@ -158,7 +158,7 @@ impl Events {
}, },
Event::Push(id, msg) => { Event::Push(id, msg) => {
info!("push id={:?}", id); trace!("push id={:?}", id);
let mut subs = 0; let mut subs = 0;
let mut dead = vec![]; let mut dead = vec![];
@ -177,11 +177,11 @@ impl Events {
} }
if !dead.is_empty() { if !dead.is_empty() {
info!("dead connections={:?}", dead.len()); trace!("dead connections={:?}", dead.len());
dead.iter().for_each(|id| self.remove_client(*id)); dead.iter().for_each(|id| self.remove_client(*id));
} }
info!("push subscribers={:?}", subs); trace!("push subscribers={:?}", subs);
Ok(()) Ok(())
}, },

View File

@ -88,181 +88,181 @@ pub enum Item {
AmplifyPlus, AmplifyPlus,
#[serde(rename = "Amplify++")] #[serde(rename = "Amplify++")]
AmplifyPlusPlus, AmplifyPlusPlus,
Absorb, Absorb,
#[serde(rename = "Absorb+")] #[serde(rename = "Absorb+")]
AbsorbPlus, AbsorbPlus,
#[serde(rename = "Absorb++")] #[serde(rename = "Absorb++")]
AbsorbPlusPlus, AbsorbPlusPlus,
Banish, Banish,
#[serde(rename = "Banish+")] #[serde(rename = "Banish+")]
BanishPlus, BanishPlus,
#[serde(rename = "Banish++")] #[serde(rename = "Banish++")]
BanishPlusPlus, BanishPlusPlus,
Bash, Bash,
#[serde(rename = "Bash+")] #[serde(rename = "Bash+")]
BashPlus, BashPlus,
#[serde(rename = "Bash++")] #[serde(rename = "Bash++")]
BashPlusPlus, BashPlusPlus,
Blast, Blast,
#[serde(rename = "Blast+")] #[serde(rename = "Blast+")]
BlastPlus, BlastPlus,
#[serde(rename = "Blast++")] #[serde(rename = "Blast++")]
BlastPlusPlus, BlastPlusPlus,
Chaos, Chaos,
#[serde(rename = "Chaos+")] #[serde(rename = "Chaos+")]
ChaosPlus, ChaosPlus,
#[serde(rename = "Chaos++")] #[serde(rename = "Chaos++")]
ChaosPlusPlus, ChaosPlusPlus,
Sustain, Sustain,
#[serde(rename = "Sustain+")] #[serde(rename = "Sustain+")]
SustainPlus, SustainPlus,
#[serde(rename = "Sustain++")] #[serde(rename = "Sustain++")]
SustainPlusPlus, SustainPlusPlus,
Electrify, Electrify,
#[serde(rename = "Electrify+")] #[serde(rename = "Electrify+")]
ElectrifyPlus, ElectrifyPlus,
#[serde(rename = "Electrify++")] #[serde(rename = "Electrify++")]
ElectrifyPlusPlus, ElectrifyPlusPlus,
Curse, Curse,
#[serde(rename = "Curse+")] #[serde(rename = "Curse+")]
CursePlus, CursePlus,
#[serde(rename = "Curse++")] #[serde(rename = "Curse++")]
CursePlusPlus, CursePlusPlus,
Decay, Decay,
#[serde(rename = "Decay+")] #[serde(rename = "Decay+")]
DecayPlus, DecayPlus,
#[serde(rename = "Decay++")] #[serde(rename = "Decay++")]
DecayPlusPlus, DecayPlusPlus,
Hex, Hex,
#[serde(rename = "Hex+")] #[serde(rename = "Hex+")]
HexPlus, HexPlus,
#[serde(rename = "Hex++")] #[serde(rename = "Hex++")]
HexPlusPlus, HexPlusPlus,
Haste, Haste,
#[serde(rename = "Haste+")] #[serde(rename = "Haste+")]
HastePlus, HastePlus,
#[serde(rename = "Haste++")] #[serde(rename = "Haste++")]
HastePlusPlus, HastePlusPlus,
Heal, Heal,
#[serde(rename = "Heal+")] #[serde(rename = "Heal+")]
HealPlus, HealPlus,
#[serde(rename = "Heal++")] #[serde(rename = "Heal++")]
HealPlusPlus, HealPlusPlus,
Hybrid, Hybrid,
#[serde(rename = "Hybrid+")] #[serde(rename = "Hybrid+")]
HybridPlus, HybridPlus,
#[serde(rename = "Hybrid++")] #[serde(rename = "Hybrid++")]
HybridPlusPlus, HybridPlusPlus,
Invert, Invert,
#[serde(rename = "Invert+")] #[serde(rename = "Invert+")]
InvertPlus, InvertPlus,
#[serde(rename = "Invert++")] #[serde(rename = "Invert++")]
InvertPlusPlus, InvertPlusPlus,
Counter, Counter,
#[serde(rename = "Counter+")] #[serde(rename = "Counter+")]
CounterPlus, CounterPlus,
#[serde(rename = "Counter++")] #[serde(rename = "Counter++")]
CounterPlusPlus, CounterPlusPlus,
Purge, Purge,
#[serde(rename = "Purge+")] #[serde(rename = "Purge+")]
PurgePlus, PurgePlus,
#[serde(rename = "Purge++")] #[serde(rename = "Purge++")]
PurgePlusPlus, PurgePlusPlus,
Purify, Purify,
#[serde(rename = "Purify+")] #[serde(rename = "Purify+")]
PurifyPlus, PurifyPlus,
#[serde(rename = "Purify++")] #[serde(rename = "Purify++")]
PurifyPlusPlus, PurifyPlusPlus,
Reflect, Reflect,
#[serde(rename = "Reflect+")] #[serde(rename = "Reflect+")]
ReflectPlus, ReflectPlus,
#[serde(rename = "Reflect++")] #[serde(rename = "Reflect++")]
ReflectPlusPlus, ReflectPlusPlus,
Recharge, Recharge,
#[serde(rename = "Recharge+")] #[serde(rename = "Recharge+")]
RechargePlus, RechargePlus,
#[serde(rename = "Recharge++")] #[serde(rename = "Recharge++")]
RechargePlusPlus, RechargePlusPlus,
Ruin, Ruin,
#[serde(rename = "Ruin+")] #[serde(rename = "Ruin+")]
RuinPlus, RuinPlus,
#[serde(rename = "Ruin++")] #[serde(rename = "Ruin++")]
RuinPlusPlus, RuinPlusPlus,
Link, Link,
#[serde(rename = "Link+")] #[serde(rename = "Link+")]
LinkPlus, LinkPlus,
#[serde(rename = "Link++")] #[serde(rename = "Link++")]
LinkPlusPlus, LinkPlusPlus,
Silence, Silence,
#[serde(rename = "Silence+")] #[serde(rename = "Silence+")]
SilencePlus, SilencePlus,
#[serde(rename = "Silence++")] #[serde(rename = "Silence++")]
SilencePlusPlus, SilencePlusPlus,
Slay, Slay,
#[serde(rename = "Slay+")] #[serde(rename = "Slay+")]
SlayPlus, SlayPlus,
#[serde(rename = "Slay++")] #[serde(rename = "Slay++")]
SlayPlusPlus, SlayPlusPlus,
Sleep, Sleep,
#[serde(rename = "Sleep+")] #[serde(rename = "Sleep+")]
SleepPlus, SleepPlus,
#[serde(rename = "Sleep++")] #[serde(rename = "Sleep++")]
SleepPlusPlus, SleepPlusPlus,
Restrict, Restrict,
#[serde(rename = "Restrict+")] #[serde(rename = "Restrict+")]
RestrictPlus, RestrictPlus,
#[serde(rename = "Restrict++")] #[serde(rename = "Restrict++")]
RestrictPlusPlus, RestrictPlusPlus,
Strike, Strike,
#[serde(rename = "Strike+")] #[serde(rename = "Strike+")]
StrikePlus, StrikePlus,
#[serde(rename = "Strike++")] #[serde(rename = "Strike++")]
StrikePlusPlus, StrikePlusPlus,
Siphon, Siphon,
#[serde(rename = "Siphon+")] #[serde(rename = "Siphon+")]
SiphonPlus, SiphonPlus,
#[serde(rename = "Siphon++")] #[serde(rename = "Siphon++")]
SiphonPlusPlus, SiphonPlusPlus,
Intercept, Intercept,
#[serde(rename = "Intercept+")] #[serde(rename = "Intercept+")]
InterceptPlus, InterceptPlus,
#[serde(rename = "Intercept++")] #[serde(rename = "Intercept++")]
InterceptPlusPlus, InterceptPlusPlus,
Break, Break,
#[serde(rename = "Break+")] #[serde(rename = "Break+")]
BreakPlus, BreakPlus,
#[serde(rename = "Break++")] #[serde(rename = "Break++")]
BreakPlusPlus, BreakPlusPlus,
Triage, Triage,
#[serde(rename = "Triage+")] #[serde(rename = "Triage+")]
TriagePlus, TriagePlus,
@ -748,7 +748,7 @@ impl Item {
Item::Counter| Item::Counter|
Item::CounterPlus | Item::CounterPlus |
Item::CounterPlusPlus => format!("Self targetting skill. Recharges RedLife for {:?}% RedPower and blocks red skills for {:?}T. Item::CounterPlusPlus => format!("Self targetting skill. Recharges RedLife for {:?}% RedPower and blocks red skills for {:?}T.
If a red skill is parried the construct will riposte the source dealing {:?}% RedPower as red damage.", If a red skill is parried the construct will riposte the source dealing {:?}% RedPower as red damage.",
self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().multiplier(),
self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().effect()[0].get_duration(),

View File

@ -503,181 +503,181 @@ pub enum Skill {
AmplifyPlus, AmplifyPlus,
#[serde(rename = "Amplify++")] #[serde(rename = "Amplify++")]
AmplifyPlusPlus, AmplifyPlusPlus,
Absorb, Absorb,
#[serde(rename = "Absorb+")] #[serde(rename = "Absorb+")]
AbsorbPlus, AbsorbPlus,
#[serde(rename = "Absorb++")] #[serde(rename = "Absorb++")]
AbsorbPlusPlus, AbsorbPlusPlus,
Banish, Banish,
#[serde(rename = "Banish+")] #[serde(rename = "Banish+")]
BanishPlus, BanishPlus,
#[serde(rename = "Banish++")] #[serde(rename = "Banish++")]
BanishPlusPlus, BanishPlusPlus,
Bash, Bash,
#[serde(rename = "Bash+")] #[serde(rename = "Bash+")]
BashPlus, BashPlus,
#[serde(rename = "Bash++")] #[serde(rename = "Bash++")]
BashPlusPlus, BashPlusPlus,
Blast, Blast,
#[serde(rename = "Blast+")] #[serde(rename = "Blast+")]
BlastPlus, BlastPlus,
#[serde(rename = "Blast++")] #[serde(rename = "Blast++")]
BlastPlusPlus, BlastPlusPlus,
Chaos, Chaos,
#[serde(rename = "Chaos+")] #[serde(rename = "Chaos+")]
ChaosPlus, ChaosPlus,
#[serde(rename = "Chaos++")] #[serde(rename = "Chaos++")]
ChaosPlusPlus, ChaosPlusPlus,
Sustain, Sustain,
#[serde(rename = "Sustain+")] #[serde(rename = "Sustain+")]
SustainPlus, SustainPlus,
#[serde(rename = "Sustain++")] #[serde(rename = "Sustain++")]
SustainPlusPlus, SustainPlusPlus,
Electrify, Electrify,
#[serde(rename = "Electrify+")] #[serde(rename = "Electrify+")]
ElectrifyPlus, ElectrifyPlus,
#[serde(rename = "Electrify++")] #[serde(rename = "Electrify++")]
ElectrifyPlusPlus, ElectrifyPlusPlus,
Curse, Curse,
#[serde(rename = "Curse+")] #[serde(rename = "Curse+")]
CursePlus, CursePlus,
#[serde(rename = "Curse++")] #[serde(rename = "Curse++")]
CursePlusPlus, CursePlusPlus,
Decay, Decay,
#[serde(rename = "Decay+")] #[serde(rename = "Decay+")]
DecayPlus, DecayPlus,
#[serde(rename = "Decay++")] #[serde(rename = "Decay++")]
DecayPlusPlus, DecayPlusPlus,
Hex, Hex,
#[serde(rename = "Hex+")] #[serde(rename = "Hex+")]
HexPlus, HexPlus,
#[serde(rename = "Hex++")] #[serde(rename = "Hex++")]
HexPlusPlus, HexPlusPlus,
Haste, Haste,
#[serde(rename = "Haste+")] #[serde(rename = "Haste+")]
HastePlus, HastePlus,
#[serde(rename = "Haste++")] #[serde(rename = "Haste++")]
HastePlusPlus, HastePlusPlus,
Heal, Heal,
#[serde(rename = "Heal+")] #[serde(rename = "Heal+")]
HealPlus, HealPlus,
#[serde(rename = "Heal++")] #[serde(rename = "Heal++")]
HealPlusPlus, HealPlusPlus,
Hybrid, Hybrid,
#[serde(rename = "Hybrid+")] #[serde(rename = "Hybrid+")]
HybridPlus, HybridPlus,
#[serde(rename = "Hybrid++")] #[serde(rename = "Hybrid++")]
HybridPlusPlus, HybridPlusPlus,
Invert, Invert,
#[serde(rename = "Invert+")] #[serde(rename = "Invert+")]
InvertPlus, InvertPlus,
#[serde(rename = "Invert++")] #[serde(rename = "Invert++")]
InvertPlusPlus, InvertPlusPlus,
Counter, Counter,
#[serde(rename = "Counter+")] #[serde(rename = "Counter+")]
CounterPlus, CounterPlus,
#[serde(rename = "Counter++")] #[serde(rename = "Counter++")]
CounterPlusPlus, CounterPlusPlus,
Purge, Purge,
#[serde(rename = "Purge+")] #[serde(rename = "Purge+")]
PurgePlus, PurgePlus,
#[serde(rename = "Purge++")] #[serde(rename = "Purge++")]
PurgePlusPlus, PurgePlusPlus,
Purify, Purify,
#[serde(rename = "Purify+")] #[serde(rename = "Purify+")]
PurifyPlus, PurifyPlus,
#[serde(rename = "Purify++")] #[serde(rename = "Purify++")]
PurifyPlusPlus, PurifyPlusPlus,
Reflect, Reflect,
#[serde(rename = "Reflect+")] #[serde(rename = "Reflect+")]
ReflectPlus, ReflectPlus,
#[serde(rename = "Reflect++")] #[serde(rename = "Reflect++")]
ReflectPlusPlus, ReflectPlusPlus,
Recharge, Recharge,
#[serde(rename = "Recharge+")] #[serde(rename = "Recharge+")]
RechargePlus, RechargePlus,
#[serde(rename = "Recharge++")] #[serde(rename = "Recharge++")]
RechargePlusPlus, RechargePlusPlus,
Ruin, Ruin,
#[serde(rename = "Ruin+")] #[serde(rename = "Ruin+")]
RuinPlus, RuinPlus,
#[serde(rename = "Ruin++")] #[serde(rename = "Ruin++")]
RuinPlusPlus, RuinPlusPlus,
Link, Link,
#[serde(rename = "Link+")] #[serde(rename = "Link+")]
LinkPlus, LinkPlus,
#[serde(rename = "Link++")] #[serde(rename = "Link++")]
LinkPlusPlus, LinkPlusPlus,
Silence, Silence,
#[serde(rename = "Silence+")] #[serde(rename = "Silence+")]
SilencePlus, SilencePlus,
#[serde(rename = "Silence++")] #[serde(rename = "Silence++")]
SilencePlusPlus, SilencePlusPlus,
Slay, Slay,
#[serde(rename = "Slay+")] #[serde(rename = "Slay+")]
SlayPlus, SlayPlus,
#[serde(rename = "Slay++")] #[serde(rename = "Slay++")]
SlayPlusPlus, SlayPlusPlus,
Sleep, Sleep,
#[serde(rename = "Sleep+")] #[serde(rename = "Sleep+")]
SleepPlus, SleepPlus,
#[serde(rename = "Sleep++")] #[serde(rename = "Sleep++")]
SleepPlusPlus, SleepPlusPlus,
Restrict, Restrict,
#[serde(rename = "Restrict+")] #[serde(rename = "Restrict+")]
RestrictPlus, RestrictPlus,
#[serde(rename = "Restrict++")] #[serde(rename = "Restrict++")]
RestrictPlusPlus, RestrictPlusPlus,
Strike, Strike,
#[serde(rename = "Strike+")] #[serde(rename = "Strike+")]
StrikePlus, StrikePlus,
#[serde(rename = "Strike++")] #[serde(rename = "Strike++")]
StrikePlusPlus, StrikePlusPlus,
Siphon, Siphon,
#[serde(rename = "Siphon+")] #[serde(rename = "Siphon+")]
SiphonPlus, SiphonPlus,
#[serde(rename = "Siphon++")] #[serde(rename = "Siphon++")]
SiphonPlusPlus, SiphonPlusPlus,
Intercept, Intercept,
#[serde(rename = "Intercept+")] #[serde(rename = "Intercept+")]
InterceptPlus, InterceptPlus,
#[serde(rename = "Intercept++")] #[serde(rename = "Intercept++")]
InterceptPlusPlus, InterceptPlusPlus,
Break, Break,
#[serde(rename = "Break+")] #[serde(rename = "Break+")]
BreakPlus, BreakPlus,
#[serde(rename = "Break++")] #[serde(rename = "Break++")]
BreakPlusPlus, BreakPlusPlus,
Triage, Triage,
#[serde(rename = "Triage+")] #[serde(rename = "Triage+")]
TriagePlus, TriagePlus,
@ -695,7 +695,7 @@ pub enum Skill {
CounterAttackPlus, CounterAttackPlus,
#[serde(rename = "CounterAttack++")] #[serde(rename = "CounterAttack++")]
CounterAttackPlusPlus, CounterAttackPlusPlus,
Electrocute, Electrocute,
#[serde(rename = "Electrocute+")] #[serde(rename = "Electrocute+")]
ElectrocutePlus, ElectrocutePlus,
@ -1758,13 +1758,14 @@ fn purge(source: &mut Construct, target: &mut Construct, mut results: Resolution
.event(Event::Removal { effect: ce.effect, construct_effects: target.effects.clone() })); .event(Event::Removal { effect: ce.effect, construct_effects: target.effects.clone() }));
} }
let mut turns = 0; let mut turns = 1;
for cs in target.skills.iter_mut() { for cs in target.skills.iter_mut() {
if Effect::Purge.disables_skill(cs.skill) { if Effect::Purge.disables_skill(cs.skill) {
turns += 1; turns += 1;
} }
} }
if turns > 0 {
if turns > 1 {
let mut effect = skill.effect()[0]; let mut effect = skill.effect()[0];
effect.duration = effect.duration * turns; effect.duration = effect.duration * turns;
results.push(Resolution::new(source, target).event(target.add_effect(skill, effect)).stages(EventStages::PostOnly)); results.push(Resolution::new(source, target).event(target.add_effect(skill, effect)).stages(EventStages::PostOnly));