Merge branch 'vbox-rework' into develop
This commit is contained in:
commit
3088d104da
@ -185,7 +185,7 @@
|
|||||||
|
|
||||||
.game-construct.ko {
|
.game-construct.ko {
|
||||||
animation: none;
|
animation: none;
|
||||||
opacity: 0.35;
|
opacity: 0.20;
|
||||||
/* filter: grayscale(100%);
|
/* filter: grayscale(100%);
|
||||||
*/}
|
*/}
|
||||||
|
|
||||||
@ -199,6 +199,7 @@
|
|||||||
*/}
|
*/}
|
||||||
|
|
||||||
.game-construct.unfocus.ko {
|
.game-construct.unfocus.ko {
|
||||||
|
opacity: 0.20;
|
||||||
/* filter: blur(5px) grayscale(100%);
|
/* filter: blur(5px) grayscale(100%);
|
||||||
*/}
|
*/}
|
||||||
|
|
||||||
@ -453,4 +454,8 @@
|
|||||||
#mnml .game .skills button, #mnml .game .stats {
|
#mnml .game .skills button, #mnml .game .stats {
|
||||||
font-size: 75%;
|
font-size: 75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-construct .name {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -6,12 +6,10 @@
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 2fr minmax(min-content, 1fr);
|
grid-template-columns: 2fr minmax(min-content, 1fr);
|
||||||
grid-template-rows: min-content min-content min-content 1fr;
|
grid-template-rows: min-content 1fr;
|
||||||
|
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"top info"
|
|
||||||
"vbox info"
|
"vbox info"
|
||||||
"equip info"
|
|
||||||
"constructs info";
|
"constructs info";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,10 +79,6 @@
|
|||||||
"vbox . combiner";
|
"vbox . combiner";
|
||||||
}
|
}
|
||||||
|
|
||||||
.vbox-box {
|
|
||||||
grid-area: vbox;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-inventory {
|
.vbox-inventory {
|
||||||
grid-area: inventory;
|
grid-area: inventory;
|
||||||
}
|
}
|
||||||
@ -121,19 +115,6 @@
|
|||||||
flex: 0;
|
flex: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vbox-btn:active, .vbox-btn:hover, .vbox-btn:focus {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-btn.reclaiming, .vbox-btn.reclaim.reclaiming:hover {
|
|
||||||
background: #a52a2a;
|
|
||||||
color: black;
|
|
||||||
box-shadow: inset 0.5em 0 0 0 #a52a2a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-btn.reclaim:hover {
|
|
||||||
color: #a52a2a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-hdr {
|
.vbox-hdr {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -164,26 +145,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vbox button {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
background-color: #333;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-table td {
|
|
||||||
transition-property: color, background, border;
|
|
||||||
transition-duration: 0.5s;
|
|
||||||
transition-delay: 0;
|
|
||||||
transition-timing-function: linear;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-table td:active {
|
|
||||||
background: whitesmoke;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* CONSTRUCT LIST */
|
/* CONSTRUCT LIST */
|
||||||
|
|
||||||
.construct-list {
|
.construct-list {
|
||||||
|
|||||||
@ -146,7 +146,7 @@ button, input {
|
|||||||
color: whitesmoke;
|
color: whitesmoke;
|
||||||
height: auto;
|
height: auto;
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-color: #222;
|
border-color: #333;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
letter-spacing: 0.25em;
|
letter-spacing: 0.25em;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -234,8 +234,8 @@ table .highlight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button[disabled] {
|
button[disabled] {
|
||||||
color: #333;
|
color: #222;
|
||||||
border-color: #333;
|
border-color: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
104
client/assets/styles/vbox.less
Normal file
104
client/assets/styles/vbox.less
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
@green: #1FF01F;
|
||||||
|
@red: #a52a2a;
|
||||||
|
@blue: #3498db;
|
||||||
|
@white: #f5f5f5; // whitesmoke
|
||||||
|
@purple: #9355b5; // 6lack - that far cover
|
||||||
|
|
||||||
|
@darkgray: #222;
|
||||||
|
@gray: #333;
|
||||||
|
|
||||||
|
.vbox {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
|
||||||
|
.vbox-section {
|
||||||
|
// border: 2px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-hdr {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-colours {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(6, 1fr);
|
||||||
|
grid-gap: 1em 2em;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-items {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
grid-gap: 1em 2em;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-btn {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
background-color: @gray;
|
||||||
|
border-width: 0;
|
||||||
|
|
||||||
|
:active, :hover, :focus {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.reclaim {
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @red;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
&.reclaiming, &.reclaiming:hover, &.reclaiming:active {
|
||||||
|
background: @red;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
background: black;
|
||||||
|
border-width: 1px;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
height: 3em;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&.empty {
|
||||||
|
border-style: dashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.highlight {
|
||||||
|
color: black;
|
||||||
|
background: @white;
|
||||||
|
border: 1px solid @white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
stroke: none;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
&.red {
|
||||||
|
fill: @red;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.green {
|
||||||
|
fill: @green;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.blue {
|
||||||
|
fill: @blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
require('./assets/styles/styles.css');
|
require('./assets/styles/styles.css');
|
||||||
require('./assets/styles/styles.mobile.css');
|
require('./assets/styles/styles.mobile.css');
|
||||||
require('./assets/styles/instance.css');
|
require('./assets/styles/instance.css');
|
||||||
|
require('./assets/styles/vbox.less');
|
||||||
require('./assets/styles/instance.mobile.css');
|
require('./assets/styles/instance.mobile.css');
|
||||||
require('./assets/styles/game.css');
|
require('./assets/styles/game.css');
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "parcel watch index.html --out-dir /var/lib/mnml/public/current",
|
"start": "parcel watch index.html --out-dir /var/lib/mnml/public/current",
|
||||||
"anims": "parcel animations.html --host 0.0.0.0 --port 40080 --no-source-maps",
|
"anims": "parcel watch animations.html --out-dir /var/lib/mnml/public/current",
|
||||||
"build": "parcel build index.html",
|
"build": "parcel build index.html",
|
||||||
"scss": "node-sass --watch assets/scss -o assets/styles",
|
"scss": "node-sass --watch assets/scss -o assets/styles",
|
||||||
"lint": "eslint --fix --ext .jsx src/",
|
"lint": "eslint --fix --ext .jsx src/",
|
||||||
@ -40,7 +40,8 @@
|
|||||||
"eslint-config-airbnb-base": "^13.1.0",
|
"eslint-config-airbnb-base": "^13.1.0",
|
||||||
"eslint-plugin-import": "^2.14.0",
|
"eslint-plugin-import": "^2.14.0",
|
||||||
"eslint-plugin-react": "^7.11.1",
|
"eslint-plugin-react": "^7.11.1",
|
||||||
"jest": "^18.0.0"
|
"jest": "^18.0.0",
|
||||||
|
"less": "^3.9.0"
|
||||||
},
|
},
|
||||||
"alias": {
|
"alias": {
|
||||||
"react": "preact-compat",
|
"react": "preact-compat",
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
export const setAccount = value => ({ type: 'SET_ACCOUNT', value });
|
export const setAccount = value => ({ type: 'SET_ACCOUNT', value });
|
||||||
export const setActiveConstruct = value => ({ type: 'SET_ACTIVE_CONSTRUCT', value });
|
export const setActiveConstruct = value => ({ type: 'SET_ACTIVE_CONSTRUCT', value });
|
||||||
export const setAvatarAnimation = value => ({ type: 'SET_AVATAR_ANIMATION', value });
|
|
||||||
|
export const setAnimating = value => ({ type: 'SET_ANIMATING', value });
|
||||||
|
export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value });
|
||||||
|
export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value });
|
||||||
|
export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value });
|
||||||
|
|
||||||
export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value });
|
export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value });
|
||||||
export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null });
|
export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null });
|
||||||
export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) });
|
export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) });
|
||||||
@ -27,4 +32,7 @@ export const setSkip = value => ({ type: 'SET_SKIP', value });
|
|||||||
export const setShop = value => ({ type: 'SET_SHOP', value });
|
export const setShop = value => ({ type: 'SET_SHOP', value });
|
||||||
export const setTeam = value => ({ type: 'SET_SELECTED_CONSTRUCTS', value: Array.from(value) });
|
export const setTeam = value => ({ type: 'SET_SELECTED_CONSTRUCTS', value: Array.from(value) });
|
||||||
export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value });
|
export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value });
|
||||||
|
|
||||||
|
export const setVboxSelected = value => ({ type: 'SET_VBOX_SELECTED', value });
|
||||||
|
|
||||||
export const setWs = value => ({ type: 'SET_WS', value });
|
export const setWs = value => ({ type: 'SET_WS', value });
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const eachSeries = require('async/eachSeries');
|
|||||||
|
|
||||||
const actions = require('./actions');
|
const actions = require('./actions');
|
||||||
const { TIMES } = require('./constants');
|
const { TIMES } = require('./constants');
|
||||||
const { getCombatSequence } = require('./utils');
|
const animations = require('./animations.utils');
|
||||||
|
|
||||||
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/api/ws' : 'ws://localhost/api/ws';
|
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/api/ws' : 'ws://localhost/api/ws';
|
||||||
|
|
||||||
@ -20,47 +20,57 @@ function createSocket(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sendDevResolve(a, b, skill) {
|
function sendDevResolve(a, b, skill) {
|
||||||
send({ method: 'dev_game_resolve', params: { a, b, skill } });
|
send(['DevResolve', { a, b, skill }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDevResolutions(newRes) {
|
function onDevResolutions(newRes) {
|
||||||
const { game: currentGame } = store.getState();
|
const { game, account, animating } = store.getState();
|
||||||
let id = 0;
|
|
||||||
|
if (animating) return false;
|
||||||
|
store.dispatch(actions.setAnimating(true));
|
||||||
|
|
||||||
return eachSeries(newRes, (r, cb) => {
|
return eachSeries(newRes, (r, cb) => {
|
||||||
if (['Disable', 'TargetKo'].includes(r.event[0])) return cb();
|
if (['Disable', 'TargetKo'].includes(r.event[0])) return cb();
|
||||||
// Create sub events for combat animations
|
|
||||||
const sequence = getCombatSequence(r);
|
|
||||||
id += 1;
|
|
||||||
|
|
||||||
return eachSeries(sequence, (stages, sCb) => {
|
store.dispatch(actions.setResolution(r));
|
||||||
const stagedR = Object.create(r);
|
|
||||||
stagedR.sequence = sequence;
|
|
||||||
stagedR.stages = stages;
|
|
||||||
stagedR.id = id;
|
|
||||||
|
|
||||||
let timeout = 0;
|
// convert server enum into anims keywords
|
||||||
if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) {
|
// todo make serersideonly
|
||||||
timeout = TIMES.SOURCE_AND_TARGET_TOTAL_DURATION;
|
const sequence = animations.getSequence(r);
|
||||||
} else if (stages.includes('START_SKILL')) timeout = TIMES.SOURCE_DURATION_MS;
|
const timeout = animations.getTime(sequence);
|
||||||
else if (stages.includes('END_SKILL')) timeout = TIMES.TARGET_DURATION_MS;
|
const anims = animations.getObjects(r, sequence, game, account);
|
||||||
else if (stages.includes('POST_SKILL')) timeout = TIMES.POST_SKILL_DURATION_MS;
|
const text = animations.getText(r, sequence);
|
||||||
store.dispatch(actions.setResolution(stagedR));
|
|
||||||
|
if (sequence.includes('START_SKILL')) store.dispatch(actions.setAnimSource(anims.animSource));
|
||||||
|
if (sequence.includes('END_SKILL')) store.dispatch(actions.setAnimTarget(anims.animTarget));
|
||||||
|
if (sequence.includes('POST_SKILL')) {
|
||||||
|
// timeout to prevent text classes from being added too soon
|
||||||
|
setTimeout(
|
||||||
|
() => store.dispatch(actions.setAnimText(text)),
|
||||||
|
timeout - 1000,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setTimeout(() => {
|
||||||
|
store.dispatch(actions.setAnimSource(null));
|
||||||
|
store.dispatch(actions.setAnimTarget(null));
|
||||||
|
store.dispatch(actions.setAnimText(null));
|
||||||
|
return setTimeout(cb, 50);
|
||||||
|
}, timeout);
|
||||||
|
|
||||||
return setTimeout(sCb, timeout);
|
|
||||||
}, err => {
|
|
||||||
if (err) console.error(err);
|
|
||||||
store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false }));
|
|
||||||
// Finished this resolution
|
|
||||||
return cb();
|
|
||||||
});
|
|
||||||
}, err => {
|
}, err => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
store.dispatch(actions.setAvatarAnimation({ id: -1, source: false, target: false }));
|
// clear animation state
|
||||||
store.dispatch(actions.setResolution(null));
|
store.dispatch(actions.setAnimSource(null));
|
||||||
// stop skipping resolutions
|
store.dispatch(actions.setAnimTarget(null));
|
||||||
|
store.dispatch(actions.setAnimText(null));
|
||||||
|
store.dispatch(actions.setAnimating(false));
|
||||||
|
|
||||||
store.dispatch(actions.setSkip(false));
|
store.dispatch(actions.setSkip(false));
|
||||||
// update the game
|
store.dispatch(actions.setResolution(null));
|
||||||
store.dispatch(actions.setGame(currentGame));
|
|
||||||
|
// set the game state so resolutions don't fire twice
|
||||||
|
store.dispatch(actions.setGame(game));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -75,8 +85,13 @@ function createSocket(store) {
|
|||||||
// decode binary msg from server
|
// decode binary msg from server
|
||||||
const blob = new Uint8Array(event.data);
|
const blob = new Uint8Array(event.data);
|
||||||
const res = cbor.decode(blob);
|
const res = cbor.decode(blob);
|
||||||
|
// if (res.err) return errHandler(res.err);
|
||||||
|
|
||||||
const [msgType, params] = res;
|
const [msgType, params] = res;
|
||||||
if (!handlers[msgType]) return false;
|
if (msgType !== 'Pong') console.log(res);
|
||||||
|
|
||||||
|
// check for error and split into response type and data
|
||||||
|
if (!handlers[msgType]) return console.error(`${msgType} handler missing`);
|
||||||
return handlers[msgType](params);
|
return handlers[msgType](params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,10 +20,10 @@ const testAccount = {
|
|||||||
|
|
||||||
// Redux Store
|
// Redux Store
|
||||||
const store = createStore(
|
const store = createStore(
|
||||||
combineReducers(reducers)
|
combineReducers(reducers),
|
||||||
|
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
|
||||||
);
|
);
|
||||||
|
|
||||||
store.subscribe(() => console.log(store.getState()));
|
|
||||||
store.dispatch(actions.setAccount(testAccount));
|
store.dispatch(actions.setAccount(testAccount));
|
||||||
store.dispatch(actions.setGame(testGame));
|
store.dispatch(actions.setGame(testGame));
|
||||||
|
|
||||||
|
|||||||
185
client/src/animations.utils.jsx
Normal file
185
client/src/animations.utils.jsx
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
const { removeTier } = require('./utils');
|
||||||
|
const { TIMES } = require('./constants');
|
||||||
|
|
||||||
|
function none() {
|
||||||
|
return {
|
||||||
|
animSource: null,
|
||||||
|
animTarget: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getObjects(resolution, stages, game, account) {
|
||||||
|
if (!resolution) return none();
|
||||||
|
if (!resolution.target) return none();
|
||||||
|
|
||||||
|
const [, event] = resolution.event;
|
||||||
|
if (!event || !event.skill) return none();
|
||||||
|
|
||||||
|
const playerTeam = game.players.find(t => t.id === account.id);
|
||||||
|
const playerTeamIds = playerTeam.constructs.map(c => c.id);
|
||||||
|
const otherTeam = game.players.find(t => t.id !== account.id);
|
||||||
|
const otherTeamIds = otherTeam.constructs.map(c => c.id);
|
||||||
|
const sourceIsPlayer = playerTeamIds.includes(resolution.source.id);
|
||||||
|
const targetIsPlayer = playerTeamIds.includes(resolution.target.id);
|
||||||
|
|
||||||
|
const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer);
|
||||||
|
let y = 0;
|
||||||
|
if (!sameTeam) y = targetIsPlayer ? 1 : -1;
|
||||||
|
|
||||||
|
const i = sourceIsPlayer
|
||||||
|
? playerTeamIds.findIndex(c => c === resolution.source.id)
|
||||||
|
: otherTeamIds.findIndex(c => c === resolution.source.id);
|
||||||
|
|
||||||
|
const j = targetIsPlayer
|
||||||
|
? playerTeamIds.findIndex(c => c === resolution.target.id)
|
||||||
|
: otherTeamIds.findIndex(c => c === resolution.target.id);
|
||||||
|
const x = j - i;
|
||||||
|
const direction = { x, y };
|
||||||
|
// const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds;
|
||||||
|
|
||||||
|
const createSourceAnim = () => {
|
||||||
|
return {
|
||||||
|
animation: 'sourceCast',
|
||||||
|
constructId: resolution.source.id,
|
||||||
|
direction,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const skipSource = !stages.includes('START_SKILL')
|
||||||
|
|| resolution.source.id === resolution.target.id;
|
||||||
|
|
||||||
|
const animSource = skipSource
|
||||||
|
? null
|
||||||
|
: createSourceAnim();
|
||||||
|
|
||||||
|
const skill = removeTier(event.skill);
|
||||||
|
|
||||||
|
const animTarget = {
|
||||||
|
skill,
|
||||||
|
constructId: resolution.target.id,
|
||||||
|
player: playerTeamIds.includes(resolution.target.id),
|
||||||
|
direction,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
animSource,
|
||||||
|
animTarget,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSequence(resolution) {
|
||||||
|
if (!resolution.event) return [];
|
||||||
|
if (resolution.event[0] === 'Inversion') return [];
|
||||||
|
if (['Skill', 'AoeSkill'].includes(resolution.event[0])) return ['START_SKILL', 'END_SKILL'];
|
||||||
|
if (resolution.event[0] === 'Ko') return ['POST_SKILL'];
|
||||||
|
|
||||||
|
switch (resolution.stages) {
|
||||||
|
case 'AllStages': return ['START_SKILL', 'END_SKILL', 'POST_SKILL'];
|
||||||
|
case 'StartEnd': return ['START_SKILL', 'END_SKILL'];
|
||||||
|
case 'StartPost': return ['START_SKILL', 'POST_SKILL'];
|
||||||
|
case 'StartOnly': return ['START_SKILL'];
|
||||||
|
case 'EndPost': return ['END_SKILL', 'POST_SKILL'];
|
||||||
|
case 'EndOnly': return ['END_SKILL'];
|
||||||
|
case 'PostOnly': return ['POST_SKILL'];
|
||||||
|
case 'None': return [];
|
||||||
|
default: return ['START_SKILL', 'END_SKILL', 'POST_SKILL'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SOURCE_DURATION_MS = 1000;
|
||||||
|
const TARGET_DELAY_MS = 500;
|
||||||
|
const TARGET_DURATION_MS = 1500;
|
||||||
|
const POST_SKILL_DELAY_MS = 2000;
|
||||||
|
const POST_SKILL_DURATION_MS = 1000;
|
||||||
|
const SOURCE_AND_TARGET_TOTAL_DURATION = TARGET_DELAY_MS + TARGET_DURATION_MS + POST_SKILL_DURATION_MS;
|
||||||
|
|
||||||
|
function getTime(stages) {
|
||||||
|
if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) {
|
||||||
|
return TIMES.SOURCE_AND_TARGET_TOTAL_DURATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
let time = 0;
|
||||||
|
|
||||||
|
if (stages.includes('START_SKILL')) time += TIMES.SOURCE_DURATION_MS;
|
||||||
|
if (stages.includes('END_SKILL')) time += TIMES.TARGET_DURATION_MS;
|
||||||
|
if (stages.includes('POST_SKILL')) time += TIMES.POST_SKILL_DURATION_MS;
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getText(resolution, sequence) {
|
||||||
|
if (!resolution) return { text: null, constructId: null };
|
||||||
|
if (!sequence.includes('POST_SKILL')) return { text: null, constructId: null };
|
||||||
|
|
||||||
|
function generateText() {
|
||||||
|
const [type, event] = resolution.event;
|
||||||
|
if (type === 'Ko') {
|
||||||
|
return 'KO!';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Disable') {
|
||||||
|
const { disable } = event;
|
||||||
|
return `${disable}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Immunity') {
|
||||||
|
return 'IMMUNE';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Damage') {
|
||||||
|
const { mitigation, colour } = event;
|
||||||
|
let { amount } = event;
|
||||||
|
if (colour === 'Green') amount *= -1;
|
||||||
|
const mitigationText = mitigation
|
||||||
|
? `(${mitigation})`
|
||||||
|
: '';
|
||||||
|
return `${amount} ${mitigationText}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Healing') {
|
||||||
|
const { amount, overhealing } = event;
|
||||||
|
return `${amount} (${overhealing} OH)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Inversion') {
|
||||||
|
return 'INVERT';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Reflection') {
|
||||||
|
return 'REFLECT';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Effect') {
|
||||||
|
const { effect, duration } = event;
|
||||||
|
return `+ ${effect} ${duration}T`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Recharge') {
|
||||||
|
const { red, blue } = event;
|
||||||
|
return [`+${red}R ${blue}B`, ''];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'Removal') {
|
||||||
|
const { effect } = event;
|
||||||
|
return `-${effect}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
text: generateText(),
|
||||||
|
constructId: resolution.target.id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getObjects,
|
||||||
|
getTime,
|
||||||
|
getSequence,
|
||||||
|
getText,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// if (!(resolution.target.id === construct.id)
|
||||||
|
// && !(resolution.event[0] === 'AoeSkill' && targetTeam.includes(construct.id))) return false;
|
||||||
@ -15,7 +15,8 @@ const Mnml = require('./components/mnml');
|
|||||||
|
|
||||||
// Redux Store
|
// Redux Store
|
||||||
const store = createStore(
|
const store = createStore(
|
||||||
combineReducers(reducers)
|
combineReducers(reducers),
|
||||||
|
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
|
||||||
);
|
);
|
||||||
|
|
||||||
document.fonts.load('16pt "Jura"').then(() => {
|
document.fonts.load('16pt "Jura"').then(() => {
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
|
const { Component } = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
|
||||||
const Amplify = require('./anims/amplify');
|
const Amplify = require('./anims/amplify');
|
||||||
const Absorb = require('./anims/absorb');
|
const Absorb = require('./anims/absorb');
|
||||||
@ -36,69 +38,44 @@ const Stun = require('./anims/stun');
|
|||||||
const Triage = require('./anims/triage');
|
const Triage = require('./anims/triage');
|
||||||
const TriageTick = require('./anims/triage.tick');
|
const TriageTick = require('./anims/triage.tick');
|
||||||
|
|
||||||
// const Test = require('./anims/test');
|
const actions = require('../actions');
|
||||||
|
|
||||||
const { removeTier } = require('../utils');
|
const addState = connect(
|
||||||
|
function receiveState(state) {
|
||||||
|
const { animTarget } = state;
|
||||||
|
return { animTarget };
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
function animations(props) {
|
class ConstructAnimation extends Component {
|
||||||
const { game, account, resolution, player, construct, avatarAnimation, setAvatarAnimation } = props;
|
render(props) {
|
||||||
if (!resolution || resolution === 'clear') return false;
|
const {
|
||||||
const [, event] = resolution.event;
|
animTarget,
|
||||||
if (!event || !event.skill) return false;
|
construct,
|
||||||
if (!resolution.target) return false;
|
} = props;
|
||||||
|
|
||||||
// source animation
|
if (!animTarget) return false;
|
||||||
const playerTeam = game.players.find(t => t.id === account.id);
|
|
||||||
const playerTeamIds = playerTeam.constructs.map(c => c.id);
|
|
||||||
const otherTeam = game.players.find(t => t.id !== account.id);
|
|
||||||
const otherTeamIds = otherTeam.constructs.map(c => c.id);
|
|
||||||
|
|
||||||
const sourceIsPlayer = playerTeamIds.includes(resolution.source.id);
|
const {
|
||||||
const targetIsPlayer = playerTeamIds.includes(resolution.target.id);
|
skill,
|
||||||
|
player,
|
||||||
|
direction,
|
||||||
|
constructId,
|
||||||
|
} = animTarget;
|
||||||
|
|
||||||
const getDirection = () => {
|
if (construct.id !== constructId) return false;
|
||||||
const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer);
|
|
||||||
let y = 0;
|
|
||||||
if (!sameTeam) y = targetIsPlayer ? 1 : -1;
|
|
||||||
|
|
||||||
const i = sourceIsPlayer
|
// find target animation
|
||||||
? playerTeamIds.findIndex(c => c === resolution.source.id)
|
const chooseAnim = (skill) => {
|
||||||
: otherTeamIds.findIndex(c => c === resolution.source.id);
|
|
||||||
|
|
||||||
const j = targetIsPlayer
|
|
||||||
? playerTeamIds.findIndex(c => c === resolution.target.id)
|
|
||||||
: otherTeamIds.findIndex(c => c === resolution.target.id);
|
|
||||||
const x = j - i;
|
|
||||||
return { x, y };
|
|
||||||
};
|
|
||||||
|
|
||||||
const skipSource = (resolution.source.id === resolution.target.id
|
|
||||||
&& ['Invert', 'Banish'].includes(removeTier(event.skill)));
|
|
||||||
|
|
||||||
// Play Source Animation
|
|
||||||
if (!skipSource && resolution.source.id === construct.id && resolution.stages.includes('START_SKILL')) {
|
|
||||||
if (!avatarAnimation.source) {
|
|
||||||
setAvatarAnimation(true, avatarAnimation.target, resolution.id,
|
|
||||||
construct.id, 'sourceCast', getDirection());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds;
|
|
||||||
if (!(resolution.target.id === construct.id)
|
|
||||||
&& !(resolution.event[0] === 'AoeSkill' && targetTeam.includes(construct.id))) return false;
|
|
||||||
|
|
||||||
// Play Target animation
|
|
||||||
const anim = text => {
|
|
||||||
if (!text || !resolution.sequence[0].includes('END_SKILL')) return false;
|
|
||||||
const skill = removeTier(text);
|
|
||||||
switch (skill) {
|
switch (skill) {
|
||||||
// Attack base
|
// Attack base
|
||||||
case 'Attack': return <Strike colour={'#f5f5f5'} direction={getDirection()}/>;
|
case 'Attack': return <Strike colour={'#f5f5f5'} direction={direction}/>;
|
||||||
case 'Blast': return <Blast direction={getDirection()}/>;
|
case 'Blast': return <Blast direction={direction}/>;
|
||||||
case 'Siphon': return <Siphon />;
|
case 'Siphon': return <Siphon />;
|
||||||
case 'SiphonTick': return <SiphonTick />;
|
case 'SiphonTick': return <SiphonTick />;
|
||||||
case 'Strike': return <Strike colour={'#a52a2a'} direction={getDirection()}/>;
|
case 'Strike': return <Strike colour={'#a52a2a'} direction={direction}/>;
|
||||||
case 'Chaos': return <Chaos direction={getDirection()}/>;
|
case 'Chaos': return <Chaos direction={direction}/>;
|
||||||
case 'Slay': return <Slay direction={getDirection()}/>;
|
case 'Slay': return <Slay direction={direction}/>;
|
||||||
case 'Heal': return <Heal />;
|
case 'Heal': return <Heal />;
|
||||||
|
|
||||||
// Buff Base
|
// Buff Base
|
||||||
@ -116,22 +93,14 @@ function animations(props) {
|
|||||||
case 'Curse': return <Curse />;
|
case 'Curse': return <Curse />;
|
||||||
case 'Decay': return <Decay />;
|
case 'Decay': return <Decay />;
|
||||||
case 'DecayTick': return <Decay />;
|
case 'DecayTick': return <Decay />;
|
||||||
case 'Invert': {
|
// case 'Invert': return setAvatarAnimation(true, true, resolution.id, construct.id, 'invert', null);
|
||||||
if (!avatarAnimation.target) {
|
|
||||||
setAvatarAnimation(avatarAnimation.source, true, resolution.id, construct.id, 'invert', null);
|
|
||||||
} return false;
|
|
||||||
}
|
|
||||||
case 'Purge': return <Purge />;
|
case 'Purge': return <Purge />;
|
||||||
case 'Silence': return <Silence />;
|
case 'Silence': return <Silence />;
|
||||||
case 'Restrict': return <Restrict />;
|
case 'Restrict': return <Restrict />;
|
||||||
|
|
||||||
// Stun Base
|
// Stun Base
|
||||||
case 'Stun': return <Stun />;
|
case 'Stun': return <Stun />;
|
||||||
case 'Banish': {
|
// case 'Banish': return setAvatarAnimation(true, true, resolution.id, construct.id, 'banish', null);
|
||||||
if (!avatarAnimation.target) {
|
|
||||||
setAvatarAnimation(avatarAnimation.source, true, resolution.id, construct.id, 'banish', null);
|
|
||||||
} return false;
|
|
||||||
}
|
|
||||||
case 'Bash': return <Bash />;
|
case 'Bash': return <Bash />;
|
||||||
case 'Absorb': return <Absorb />;
|
case 'Absorb': return <Absorb />;
|
||||||
case 'Sleep': return <Sleep />;
|
case 'Sleep': return <Sleep />;
|
||||||
@ -140,26 +109,31 @@ function animations(props) {
|
|||||||
|
|
||||||
// Block Base
|
// Block Base
|
||||||
case 'Block': return <Block />;
|
case 'Block': return <Block />;
|
||||||
case 'Sustain': return <Sustain team={player} />;
|
case 'Sustain': return <Sustain player={player} />;
|
||||||
case 'Electrify': return <Electrify />;
|
case 'Electrify': return <Electrify />;
|
||||||
case 'Electrocute': return <Electrocute />;
|
case 'Electrocute': return <Electrocute />;
|
||||||
case 'ElectrocuteTick': return <Electrocute />;
|
case 'ElectrocuteTick': return <Electrocute />;
|
||||||
case 'Counter': return <Counter team={player} />;
|
case 'Counter': return <Counter player={player} />;
|
||||||
case 'Purify': return <Purify team={player} />;
|
case 'Purify': return <Purify player={player} />;
|
||||||
case 'Recharge': return <Recharge team={player} />;
|
case 'Recharge': return <Recharge player={player} />;
|
||||||
case 'Reflect': return <Refl team={player} />;
|
case 'Reflect': return <Refl player={player} />;
|
||||||
|
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const combatAnim = anim(event.skill);
|
const anim = chooseAnim(skill);
|
||||||
if (!combatAnim) return false;
|
if (!anim) return false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={'combat-anim'}>
|
<div class={'combat-anim'}>
|
||||||
{combatAnim}
|
{anim}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = animations;
|
|
||||||
|
module.exports = {
|
||||||
|
ConstructAnimation: addState(ConstructAnimation),
|
||||||
|
};
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class Hybrid extends Component {
|
|||||||
class="green-one"
|
class="green-one"
|
||||||
cx='50'
|
cx='50'
|
||||||
cy='150'
|
cy='150'
|
||||||
r='10'
|
r="15"
|
||||||
fill={COLOURS.GREEN}
|
fill={COLOURS.GREEN}
|
||||||
stroke="none"
|
stroke="none"
|
||||||
/>
|
/>
|
||||||
@ -41,7 +41,7 @@ class Hybrid extends Component {
|
|||||||
class="green-two"
|
class="green-two"
|
||||||
cx='250'
|
cx='250'
|
||||||
cy='150'
|
cy='150'
|
||||||
r='10'
|
r="15"
|
||||||
fill={COLOURS.GREEN}
|
fill={COLOURS.GREEN}
|
||||||
stroke="none"
|
stroke="none"
|
||||||
/>
|
/>
|
||||||
@ -49,7 +49,7 @@ class Hybrid extends Component {
|
|||||||
class="bluewhite-one"
|
class="bluewhite-one"
|
||||||
cx='150'
|
cx='150'
|
||||||
cy='50'
|
cy='50'
|
||||||
r='10'
|
r="15"
|
||||||
fill={COLOURS.BLUE}
|
fill={COLOURS.BLUE}
|
||||||
stroke="none"
|
stroke="none"
|
||||||
/>
|
/>
|
||||||
@ -65,7 +65,7 @@ class Hybrid extends Component {
|
|||||||
class="bluewhite-two"
|
class="bluewhite-two"
|
||||||
cx='150'
|
cx='150'
|
||||||
cy='250'
|
cy='250'
|
||||||
r='10'
|
r="15"
|
||||||
fill={COLOURS.BLUE}
|
fill={COLOURS.BLUE}
|
||||||
stroke="none"
|
stroke="none"
|
||||||
/>
|
/>
|
||||||
@ -77,7 +77,6 @@ class Hybrid extends Component {
|
|||||||
fill={COLOURS.WHITE}
|
fill={COLOURS.WHITE}
|
||||||
stroke="none"
|
stroke="none"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
@ -100,6 +99,7 @@ class Hybrid extends Component {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
|
r: [10, anime.random(10, 30)],
|
||||||
targets: ['#hybrid circle.green-one'],
|
targets: ['#hybrid circle.green-one'],
|
||||||
cx: [50, 250, 50, 250],
|
cx: [50, 250, 50, 250],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
delay: TIMES.TARGET_DELAY_MS,
|
||||||
@ -109,6 +109,7 @@ class Hybrid extends Component {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
|
r: [10, anime.random(10, 30)],
|
||||||
targets: ['#hybrid circle.green-two'],
|
targets: ['#hybrid circle.green-two'],
|
||||||
cy: [250, 50, 250, 50],
|
cy: [250, 50, 250, 50],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
delay: TIMES.TARGET_DELAY_MS,
|
||||||
@ -118,6 +119,7 @@ class Hybrid extends Component {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
|
r: [10, anime.random(10, 30)],
|
||||||
targets: ['#hybrid circle.bluewhite-one'],
|
targets: ['#hybrid circle.bluewhite-one'],
|
||||||
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
||||||
cy: [50, 250, 50, 250],
|
cy: [50, 250, 50, 250],
|
||||||
@ -128,6 +130,7 @@ class Hybrid extends Component {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
|
r: [10, anime.random(10, 30)],
|
||||||
targets: ['#hybrid circle.bluewhite-two'],
|
targets: ['#hybrid circle.bluewhite-two'],
|
||||||
cx: [250, 50, 250, 50],
|
cx: [250, 50, 250, 50],
|
||||||
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
||||||
|
|||||||
@ -70,10 +70,6 @@ class Sleep extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
anime.set('#sleep', {
|
|
||||||
translateY: 75,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#sleep'],
|
targets: ['#sleep'],
|
||||||
opacity: [
|
opacity: [
|
||||||
|
|||||||
@ -2,12 +2,12 @@ const anime = require('animejs').default;
|
|||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
function sourceCast(id, params) {
|
function sourceCast(id, direction) {
|
||||||
const { x, y } = params;
|
const { x, y } = direction;
|
||||||
return anime({
|
return anime({
|
||||||
targets: [document.getElementById(id)],
|
targets: [document.getElementById(id)],
|
||||||
translateX: x * 200,
|
translateX: [0, x * 200],
|
||||||
translateY: y * 200,
|
translateY: [0, y * 200],
|
||||||
easing: 'easeInOutElastic',
|
easing: 'easeInOutElastic',
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
duration: TIMES.SOURCE_DURATION_MS,
|
duration: TIMES.SOURCE_DURATION_MS,
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
const { connect } = require('preact-redux');
|
||||||
const anime = require('animejs').default;
|
|
||||||
|
// const { match } = require('./../utils');
|
||||||
|
|
||||||
const banish = require('./anims/banish');
|
const banish = require('./anims/banish');
|
||||||
const idleAnimation = require('./anims/idle');
|
const idleAnimation = require('./anims/idle');
|
||||||
@ -10,8 +11,8 @@ const sourceCast = require('./anims/source.cast');
|
|||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const { avatarAnimation } = state;
|
const { animSource, animTarget } = state;
|
||||||
return { avatarAnimation };
|
return { animSource, animTarget };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -21,9 +22,8 @@ class ConstructAvatar extends Component {
|
|||||||
// The animation ids are a check to ensure that animations are not repeated
|
// The animation ids are a check to ensure that animations are not repeated
|
||||||
// When a new construct animation is communicated with state it will have a corresponding Id
|
// When a new construct animation is communicated with state it will have a corresponding Id
|
||||||
// which is a count of how many resoluttions have passed
|
// which is a count of how many resoluttions have passed
|
||||||
this.animId = 0;
|
|
||||||
this.source = false;
|
|
||||||
this.animations = [];
|
this.animations = [];
|
||||||
|
this.resetAnimations = this.resetAnimations.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -37,38 +37,139 @@ class ConstructAvatar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const { animSource, animTarget, construct } = this.props;
|
||||||
|
|
||||||
|
// back to idle
|
||||||
|
if (!animTarget && !animSource) {
|
||||||
|
if (!this.idle) {
|
||||||
this.idle = idleAnimation(this.props.construct.id);
|
this.idle = idleAnimation(this.props.construct.id);
|
||||||
this.animations.push(this.idle);
|
this.animations.push(this.idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
return this.idle.play();
|
||||||
if (nextProps.avatarAnimation.id === -1) this.animId = 0; // The current set of resolutions ended reset to 0
|
}
|
||||||
if (nextProps.avatarAnimation.id !== this.animId && nextProps.avatarAnimation.animTargetId === this.props.construct.id) {
|
|
||||||
this.animId = nextProps.avatarAnimation.id;
|
const isSource = animSource && animSource.constructId === construct.id;
|
||||||
|
|
||||||
const selectAnim = () => {
|
const selectAnim = () => {
|
||||||
switch (nextProps.avatarAnimation.type) {
|
if (isSource) {
|
||||||
case 'banish': return banish(this.props.construct.id);
|
console.warn(construct.name, animSource);
|
||||||
case 'invert': return invert(this.props.construct.id);
|
return sourceCast(animSource.constructId, animSource.direction);
|
||||||
case 'sourceCast': return sourceCast(this.props.construct.id, nextProps.avatarAnimation.params);
|
}
|
||||||
|
|
||||||
|
switch (animTarget.skill) {
|
||||||
|
case 'banish': return banish(construct.id);
|
||||||
|
case 'invert': return invert(construct.id);
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const anim = selectAnim();
|
const anim = selectAnim();
|
||||||
if (anim) {
|
if (!anim) return false;
|
||||||
|
|
||||||
this.idle.pause();
|
this.idle.pause();
|
||||||
this.animations.push(anim);
|
this.animations.push(anim);
|
||||||
anim.finished.then(this.idle.play);
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentDidUpdate(prevProps) {
|
||||||
|
const { animSource, animTarget, construct } = this.props;
|
||||||
|
|
||||||
|
// back to idle
|
||||||
|
if (!animTarget && !animSource) {
|
||||||
|
return this.idle.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSource = animSource && animSource.constructId === construct.id;
|
||||||
|
|
||||||
|
const selectAnim = () => {
|
||||||
|
if (isSource) {
|
||||||
|
return sourceCast(animSource.constructId, animSource.direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (animTarget.skill) {
|
||||||
|
case 'Banish': return banish(construct.id);
|
||||||
|
case 'Invert': return invert(construct.id);
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const anim = selectAnim();
|
||||||
|
if (!anim) return false;
|
||||||
|
|
||||||
|
this.idle.pause();
|
||||||
|
this.animations.push(anim);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetAnimations() {
|
||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.resetAnimations();
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate({ animSource, animTarget, construct }) {
|
||||||
|
if (construct !== this.props.construct) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animSource === this.props.animSource && animTarget === this.props.animTarget) {
|
||||||
|
// console.warn(construct.name, 'thinks its same props')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// something has changed
|
||||||
|
// what do?
|
||||||
|
|
||||||
|
// this is the source
|
||||||
|
if (animSource && animSource.constructId === construct.id) {
|
||||||
|
// console.warn(construct.name, 'should update')
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is the target
|
||||||
|
if (animTarget && animTarget.constructId === construct.id) {
|
||||||
|
// console.warn(construct.name, 'should update')
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we were previously doing src anim
|
||||||
|
const prevSrc = this.props.animSource && this.props.animSource.constructId === construct.id;
|
||||||
|
if (prevSrc && !animSource) return true;
|
||||||
|
|
||||||
|
const prevTarget = this.props.animTarget && this.props.animTarget.constructId === construct.id;
|
||||||
|
if (prevTarget && !animTarget) return true;
|
||||||
|
|
||||||
|
// console.warn(construct.name, 'not updating');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const addStateText = connect(
|
||||||
|
function receiveState(state) {
|
||||||
|
const { animText } = state;
|
||||||
|
return { animText };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function constructText(props) {
|
||||||
|
const { construct, animText } = props;
|
||||||
|
if (!construct || !animText) return false;
|
||||||
|
|
||||||
|
const text = animText.constructId === construct.id
|
||||||
|
? animText.text
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return <div class={'combat-text'}>{text}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ConstructAvatar: addState(ConstructAvatar),
|
ConstructAvatar: addState(ConstructAvatar),
|
||||||
|
ConstructText: addStateText(constructText),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
const { connect } = require('preact-redux');
|
const { connect } = require('preact-redux');
|
||||||
|
const { Component } = require('preact');
|
||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const range = require('lodash/range');
|
const range = require('lodash/range');
|
||||||
|
|
||||||
const { STATS, eventClasses, getCombatText } = require('../utils');
|
const { STATS, eventClasses } = require('../utils');
|
||||||
const { ConstructAvatar } = require('./construct');
|
const { ConstructAvatar, ConstructText } = require('./construct');
|
||||||
const animations = require('./animations');
|
const { ConstructAnimation } = require('./animations');
|
||||||
const shapes = require('./shapes');
|
const shapes = require('./shapes');
|
||||||
|
|
||||||
|
|
||||||
@ -19,9 +20,10 @@ const addState = connect(
|
|||||||
ws,
|
ws,
|
||||||
game,
|
game,
|
||||||
account,
|
account,
|
||||||
resolution,
|
|
||||||
activeSkill,
|
activeSkill,
|
||||||
avatarAnimation,
|
resolution,
|
||||||
|
|
||||||
|
animText,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
function selectSkillTarget(targetConstructId) {
|
function selectSkillTarget(targetConstructId) {
|
||||||
@ -39,42 +41,38 @@ const addState = connect(
|
|||||||
game,
|
game,
|
||||||
account,
|
account,
|
||||||
resolution,
|
resolution,
|
||||||
|
animText,
|
||||||
activeSkill,
|
activeSkill,
|
||||||
avatarAnimation,
|
|
||||||
selectSkillTarget,
|
selectSkillTarget,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
function receiveDispatch(dispatch) {
|
|
||||||
function setAvatarAnimation(source, target, id, animTargetId, type, params) {
|
|
||||||
return dispatch(actions.setAvatarAnimation({ source, target, id, animTargetId, type, params }));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setAvatarAnimation,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
function GameConstruct(props) {
|
class GameConstruct extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.resolvedLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
const {
|
const {
|
||||||
i,
|
i,
|
||||||
game,
|
game,
|
||||||
account,
|
account,
|
||||||
construct,
|
construct,
|
||||||
player,
|
player,
|
||||||
resolution,
|
|
||||||
activeSkill,
|
activeSkill,
|
||||||
avatarAnimation,
|
|
||||||
setAvatarAnimation,
|
|
||||||
selectSkillTarget,
|
selectSkillTarget,
|
||||||
} = props;
|
|
||||||
|
|
||||||
|
// todo remove dep
|
||||||
|
resolution,
|
||||||
|
|
||||||
|
animText,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
const ko = construct.green_life.value === 0 ? 'ko' : '';
|
const ko = construct.green_life.value === 0 ? 'ko' : '';
|
||||||
const classes = eventClasses(game, account, resolution, construct);
|
const classes = eventClasses(game, account, resolution, construct, animText);
|
||||||
|
|
||||||
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
|
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
|
||||||
<div key={j} alt={STATS[s].stat}>
|
<div key={j} alt={STATS[s].stat}>
|
||||||
@ -93,8 +91,7 @@ function GameConstruct(props) {
|
|||||||
const effects = construct.effects.length
|
const effects = construct.effects.length
|
||||||
? construct.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>)
|
? construct.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>)
|
||||||
: <div> </div>;
|
: <div> </div>;
|
||||||
const combatAnim = animations({ game, account, resolution, player, construct, avatarAnimation, setAvatarAnimation });
|
|
||||||
const combatText = getCombatText(resolution, construct);
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={() => selectSkillTarget(construct.id)}
|
onClick={() => selectSkillTarget(construct.id)}
|
||||||
@ -104,11 +101,12 @@ function GameConstruct(props) {
|
|||||||
{crypSkills}
|
{crypSkills}
|
||||||
<div class="stats"> {stats} </div>
|
<div class="stats"> {stats} </div>
|
||||||
<ConstructAvatar construct={construct} />
|
<ConstructAvatar construct={construct} />
|
||||||
{combatAnim}
|
<ConstructAnimation construct={construct} />
|
||||||
<div class={'combat-text'}> {combatText} </div>
|
<ConstructText construct={construct} />
|
||||||
<div class="effects"> {effects} </div>
|
<div class="effects"> {effects} </div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(GameConstruct);
|
module.exports = addState(GameConstruct);
|
||||||
|
|||||||
@ -65,7 +65,6 @@ function Game(props) {
|
|||||||
|
|
||||||
if (!game) return <div>...</div>;
|
if (!game) return <div>...</div>;
|
||||||
|
|
||||||
console.log('running game');
|
|
||||||
const otherTeams = game.players.filter(t => t.id !== account.id);
|
const otherTeams = game.players.filter(t => t.id !== account.id);
|
||||||
const playerTeam = game.players.find(t => t.id === account.id);
|
const playerTeam = game.players.find(t => t.id === account.id);
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,6 @@ function Instance(args) {
|
|||||||
<main class={instanceClasses} onMouseOver={() => setInfo(null)} >
|
<main class={instanceClasses} onMouseOver={() => setInfo(null)} >
|
||||||
<Vbox />
|
<Vbox />
|
||||||
<InfoContainer />
|
<InfoContainer />
|
||||||
<EquipmentContainer />
|
|
||||||
<InstanceConstructsContainer />
|
<InstanceConstructsContainer />
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -81,11 +81,15 @@ function Construct(props) {
|
|||||||
sendUnequip,
|
sendUnequip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const fullInfo = itemInfo.items.find(i => i.item === itemEquip);
|
||||||
|
const isSkill = fullInfo && fullInfo.skill;
|
||||||
|
const isSpec = fullInfo && fullInfo.spec;
|
||||||
|
const equipping = itemEquip && (isSkill || isSpec);
|
||||||
|
|
||||||
function onClick(e) {
|
function onClick(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log('const click eA')
|
if (equipping) sendVboxApply(construct.id, itemEquip);
|
||||||
if (itemEquip !== null) sendVboxApply(construct.id, itemEquip);
|
|
||||||
setItemEquip(null);
|
setItemEquip(null);
|
||||||
return setActiveConstruct(construct);
|
return setActiveConstruct(construct);
|
||||||
}
|
}
|
||||||
@ -124,13 +128,11 @@ function Construct(props) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const action = skill ? '' : 'action';
|
const classes = `${equipping ? 'equipping' : ''}`;
|
||||||
const equip = skillList.includes(vbox.bound[itemEquip]) && !skill ? 'equipping' : '';
|
|
||||||
const classes = `${equip}`;
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={i}
|
key={i}
|
||||||
disabled={!skill && itemEquip === null}
|
disabled={!skill && !equipping}
|
||||||
class={classes}
|
class={classes}
|
||||||
onClick={skillClick}
|
onClick={skillClick}
|
||||||
onDblClick={skillDblClick}
|
onDblClick={skillDblClick}
|
||||||
@ -140,7 +142,7 @@ function Construct(props) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const specs = range(0, 6).map(i => {
|
const specs = range(0, 3).map(i => {
|
||||||
const s = construct.specs[i];
|
const s = construct.specs[i];
|
||||||
|
|
||||||
if (!s) {
|
if (!s) {
|
||||||
@ -153,8 +155,6 @@ function Construct(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const specInfo = itemInfo.items.find(i => i.item === s);
|
|
||||||
|
|
||||||
function specClick(e) {
|
function specClick(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setItemUnequip(s);
|
setItemUnequip(s);
|
||||||
|
|||||||
@ -26,10 +26,6 @@ const addState = connect(
|
|||||||
return ws.sendInstanceState(instance.id);
|
return ws.sendInstanceState(instance.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendAccountInstances() {
|
|
||||||
return ws.sendAccountInstances();
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendInstanceList() {
|
function sendInstanceList() {
|
||||||
return ws.sendInstanceList();
|
return ws.sendInstanceList();
|
||||||
}
|
}
|
||||||
@ -41,7 +37,6 @@ const addState = connect(
|
|||||||
game,
|
game,
|
||||||
ping,
|
ping,
|
||||||
sendInstanceState,
|
sendInstanceState,
|
||||||
sendAccountInstances,
|
|
||||||
sendInstanceList,
|
sendInstanceList,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -57,7 +52,7 @@ const addState = connect(
|
|||||||
function setNav(place) {
|
function setNav(place) {
|
||||||
dispatch(actions.setGame(null));
|
dispatch(actions.setGame(null));
|
||||||
dispatch(actions.setInstance(null));
|
dispatch(actions.setInstance(null));
|
||||||
dispatch(actions.setCombiner([null, null, null]));
|
dispatch(actions.setCombiner([]));
|
||||||
dispatch(actions.setReclaiming(false));
|
dispatch(actions.setReclaiming(false));
|
||||||
dispatch(actions.setActiveSkill(null));
|
dispatch(actions.setActiveSkill(null));
|
||||||
dispatch(actions.setActiveConstruct(null));
|
dispatch(actions.setActiveConstruct(null));
|
||||||
@ -90,7 +85,6 @@ function Nav(args) {
|
|||||||
team,
|
team,
|
||||||
|
|
||||||
sendInstanceState,
|
sendInstanceState,
|
||||||
sendAccountInstances,
|
|
||||||
sendInstanceList,
|
sendInstanceList,
|
||||||
|
|
||||||
setTestGame,
|
setTestGame,
|
||||||
@ -102,7 +96,6 @@ function Nav(args) {
|
|||||||
function navTo(p) {
|
function navTo(p) {
|
||||||
if (p === 'list') {
|
if (p === 'list') {
|
||||||
sendInstanceList();
|
sendInstanceList();
|
||||||
sendAccountInstances();
|
|
||||||
}
|
}
|
||||||
return setNav(p);
|
return setNav(p);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,8 @@ const saw = require('./svgs/saw');
|
|||||||
const square = require('./svgs/square');
|
const square = require('./svgs/square');
|
||||||
const squircle = require('./svgs/squircle');
|
const squircle = require('./svgs/squircle');
|
||||||
const triangle = require('./svgs/triangle');
|
const triangle = require('./svgs/triangle');
|
||||||
const vboxColour = require('./svgs/colour');
|
// const vboxColour = require('./svgs/colour');
|
||||||
|
const vboxColour = require('./svgs/vbox.colour');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
circle,
|
circle,
|
||||||
|
|||||||
15
client/src/components/svgs/vbox.colour.jsx
Normal file
15
client/src/components/svgs/vbox.colour.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
|
||||||
|
module.exports = function vboxColour(colour) {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" class={colour} >
|
||||||
|
<circle
|
||||||
|
cx={50}
|
||||||
|
cy={50}
|
||||||
|
r={50}
|
||||||
|
// stroke-width="2"
|
||||||
|
// stroke={colour}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,12 +1,13 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
const { connect } = require('preact-redux');
|
||||||
const anime = require('animejs').default;
|
// const anime = require('animejs').default;
|
||||||
|
|
||||||
const throttle = require('lodash/throttle');
|
const throttle = require('lodash/throttle');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
({ game, account, resolution }) => ({ game, account, resolution })
|
({ game, account, animTarget, animating }) =>
|
||||||
|
({ game, account, animTarget, animating })
|
||||||
);
|
);
|
||||||
|
|
||||||
class TargetSvg extends Component {
|
class TargetSvg extends Component {
|
||||||
@ -23,9 +24,27 @@ class TargetSvg extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(props, state) {
|
render(props, state) {
|
||||||
const { game, account, resolution } = props;
|
const { game, account, animating, animTarget } = props;
|
||||||
const { width, height } = state;
|
const { width, height } = state;
|
||||||
|
|
||||||
|
// resolutions happening
|
||||||
|
// just put skill name up
|
||||||
|
if (animating) {
|
||||||
|
if (!animTarget) return false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg id="targeting" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" class="targeting-arrows">
|
||||||
|
<text
|
||||||
|
x={`${(width / 2) - 50}`}
|
||||||
|
y={`${(height / 2) + 16}`}
|
||||||
|
font-family="Jura"
|
||||||
|
font-size="2em">
|
||||||
|
{animTarget.skill}
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const playerTeam = game.players.find(t => t.id === account.id);
|
const playerTeam = game.players.find(t => t.id === account.id);
|
||||||
const otherTeam = game.players.find(t => t.id !== account.id);
|
const otherTeam = game.players.find(t => t.id !== account.id);
|
||||||
|
|
||||||
@ -81,8 +100,7 @@ class TargetSvg extends Component {
|
|||||||
|
|
||||||
return <path d={path} />;
|
return <path d={path} />;
|
||||||
}
|
}
|
||||||
if (resolution === 'clear') return false;
|
|
||||||
if (!resolution) {
|
|
||||||
return (
|
return (
|
||||||
<svg id="targeting"
|
<svg id="targeting"
|
||||||
viewBox={`0 0 ${width} ${height}`}
|
viewBox={`0 0 ${width} ${height}`}
|
||||||
@ -93,21 +111,6 @@ class TargetSvg extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let skill = '';
|
|
||||||
if (resolution.event[1]) ([, { skill }] = resolution.event);
|
|
||||||
return (
|
|
||||||
<svg id="targeting" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" class="targeting-arrows">
|
|
||||||
<text
|
|
||||||
x={`${(width / 2) - 50}`}
|
|
||||||
y={`${(height / 2) + 16}`}
|
|
||||||
font-family="Jura"
|
|
||||||
font-size="2em">
|
|
||||||
{skill}
|
|
||||||
</text>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.addEventListener('resize', this.onResize);
|
window.addEventListener('resize', this.onResize);
|
||||||
this.onResize();
|
this.onResize();
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const range = require('lodash/range');
|
const range = require('lodash/range');
|
||||||
|
const without = require('lodash/without');
|
||||||
const { connect } = require('preact-redux');
|
const { connect } = require('preact-redux');
|
||||||
|
|
||||||
const shapes = require('./shapes');
|
const shapes = require('./shapes');
|
||||||
const { convertItem } = require('./../utils');
|
|
||||||
const actions = require('../actions');
|
const actions = require('../actions');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
@ -15,6 +15,7 @@ const addState = connect(
|
|||||||
combiner,
|
combiner,
|
||||||
reclaiming,
|
reclaiming,
|
||||||
vboxHighlight,
|
vboxHighlight,
|
||||||
|
vboxSelected,
|
||||||
itemInfo,
|
itemInfo,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ const addState = connect(
|
|||||||
sendVboxDiscard,
|
sendVboxDiscard,
|
||||||
sendVboxReclaim,
|
sendVboxReclaim,
|
||||||
vboxHighlight,
|
vboxHighlight,
|
||||||
|
vboxSelected,
|
||||||
itemInfo,
|
itemInfo,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -65,11 +67,21 @@ const addState = connect(
|
|||||||
return dispatch(actions.setVboxHighlight(v));
|
return dispatch(actions.setVboxHighlight(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setVboxSelected(v) {
|
||||||
|
return dispatch(actions.setVboxSelected(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setItemEquip(v) {
|
||||||
|
return dispatch(actions.setItemEquip(v));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setCombiner,
|
setCombiner,
|
||||||
setReclaiming,
|
setReclaiming,
|
||||||
setInfo,
|
setInfo,
|
||||||
setVboxHighlight,
|
setVboxHighlight,
|
||||||
|
setVboxSelected,
|
||||||
|
setItemEquip,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +102,12 @@ function Vbox(args) {
|
|||||||
|
|
||||||
setCombiner,
|
setCombiner,
|
||||||
setInfo,
|
setInfo,
|
||||||
|
|
||||||
|
vboxSelected,
|
||||||
|
setVboxSelected,
|
||||||
|
|
||||||
|
setItemEquip,
|
||||||
|
|
||||||
setReclaiming,
|
setReclaiming,
|
||||||
setVboxHighlight,
|
setVboxHighlight,
|
||||||
} = args;
|
} = args;
|
||||||
@ -105,6 +123,13 @@ function Vbox(args) {
|
|||||||
|
|
||||||
function combinerChange(newCombiner) {
|
function combinerChange(newCombiner) {
|
||||||
setCombiner(newCombiner);
|
setCombiner(newCombiner);
|
||||||
|
|
||||||
|
if (combiner.length === 1) {
|
||||||
|
setItemEquip(newCombiner[0]);
|
||||||
|
} else {
|
||||||
|
setItemEquip(null);
|
||||||
|
}
|
||||||
|
|
||||||
if (newCombiner.every(c => c === null)) return setVboxHighlight([]);
|
if (newCombiner.every(c => c === null)) return setVboxHighlight([]);
|
||||||
|
|
||||||
const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv);
|
const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv);
|
||||||
@ -124,39 +149,6 @@ function Vbox(args) {
|
|||||||
//
|
//
|
||||||
// VBOX
|
// VBOX
|
||||||
//
|
//
|
||||||
const free = [];
|
|
||||||
|
|
||||||
// Colours
|
|
||||||
free.push([vbox.free[0][0], vbox.free[0][1], vbox.free[0][2]]);
|
|
||||||
free.push([vbox.free[0][3], vbox.free[0][4], vbox.free[0][5]]);
|
|
||||||
// Skills
|
|
||||||
free.push([vbox.free[1][0], vbox.free[1][1], vbox.free[1][2]]);
|
|
||||||
// Specs
|
|
||||||
free.push([vbox.free[2][0], vbox.free[2][1], vbox.free[2][2]]);
|
|
||||||
|
|
||||||
let vboxTimer;
|
|
||||||
const LONG_TOUCH_TIME = 500;
|
|
||||||
function vboxTouchStart(e, i, j) {
|
|
||||||
vboxTimer = (setTimeout(() => {
|
|
||||||
sendVboxAccept(j, i);
|
|
||||||
vboxTimer = null;
|
|
||||||
}, LONG_TOUCH_TIME));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function vboxTouchEnd(e, i, j) {
|
|
||||||
if (vboxTimer) {
|
|
||||||
clearTimeout(vboxTimer);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function vboxTouchMove(e) {
|
|
||||||
if (vboxTimer) clearTimeout(vboxTimer);
|
|
||||||
e.stopPropagation();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function vboxHover(e, v) {
|
function vboxHover(e, v) {
|
||||||
if (v) {
|
if (v) {
|
||||||
setInfo(v);
|
setInfo(v);
|
||||||
@ -165,168 +157,170 @@ function Vbox(args) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const freeRows = free.map((row, i) => {
|
function availableBtn(v, group, index) {
|
||||||
const cells = row.map((c, j) => {
|
if (!v) return <button disabled class='empty' > </button>;
|
||||||
const highlighted = c && vboxHighlight.includes(c);
|
|
||||||
// First two rows are colours
|
|
||||||
const sendItemType = i > 1 ? i - 1 : 0;
|
|
||||||
const sendItemIndex = i === 1 ? j + 3 : j;
|
|
||||||
return <td
|
|
||||||
key={j}
|
|
||||||
class={`${highlighted ? 'highlight' : ''}`}
|
|
||||||
onTouchStart={e => vboxTouchStart(e, i, j)}
|
|
||||||
onTouchEnd={e => vboxTouchEnd(e, i, j)}
|
|
||||||
onTouchMove={e => vboxTouchMove(e)}
|
|
||||||
|
|
||||||
// onClick={freeClick}
|
function onClick() {
|
||||||
onDblClick={() => sendVboxAccept(sendItemType, sendItemIndex) }
|
// double clicked
|
||||||
onMouseOver={e => vboxHover(e, c)}
|
if (vboxSelected[0] === group && vboxSelected[1] === index) {
|
||||||
>
|
document.activeElement.blur();
|
||||||
{convertItem(c)}
|
setVboxSelected([]);
|
||||||
</td>;
|
return sendVboxAccept(group, index);
|
||||||
});
|
|
||||||
return (
|
|
||||||
<tr key={i}>
|
|
||||||
{cells}
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// INVENTORY
|
|
||||||
//
|
|
||||||
function boundClick(e, i) {
|
|
||||||
const value = vbox.bound[i];
|
|
||||||
if (reclaiming && value) return sendVboxReclaim(i);
|
|
||||||
if (value) {
|
|
||||||
const insert = combiner.findIndex(j => j === null);
|
|
||||||
if (insert === -1) return combinerChange([i, null, null]);
|
|
||||||
combiner[insert] = i;
|
|
||||||
return combinerChange(combiner);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const boundTds = range(0, 9).map(i => {
|
return setVboxSelected([group, index]);
|
||||||
const value = vbox.bound[i];
|
}
|
||||||
if (combiner.indexOf(i) > -1) {
|
|
||||||
|
if (['Red', 'Green', 'Blue'].includes(v)) {
|
||||||
return (
|
return (
|
||||||
<td
|
<button
|
||||||
key={i}>
|
onMouseOver={e => vboxHover(e, v)}
|
||||||
|
onClick={onClick}>
|
||||||
</td>
|
{shapes.vboxColour(v.toLowerCase())}
|
||||||
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const highlighted = value && vboxHighlight.includes(value);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<td
|
<button
|
||||||
key={i}
|
onClick={onClick}
|
||||||
class={`${highlighted ? 'highlight' : ''}`}
|
onMouseOver={e => vboxHover(e, v)}>
|
||||||
onMouseOver={(e) => vboxHover(e, value)}
|
{v}
|
||||||
onClick={e => boundClick(e, i, highlighted) }>
|
</button>
|
||||||
{convertItem(value)}
|
|
||||||
</td>
|
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
const boundRows = [
|
|
||||||
<tr key={0} >
|
|
||||||
{boundTds[0]}
|
|
||||||
{boundTds[1]}
|
|
||||||
{boundTds[2]}
|
|
||||||
</tr>,
|
|
||||||
<tr key={1}>
|
|
||||||
{boundTds[3]}
|
|
||||||
{boundTds[4]}
|
|
||||||
{boundTds[5]}
|
|
||||||
</tr>,
|
|
||||||
<tr key={2}>
|
|
||||||
{boundTds[6]}
|
|
||||||
{boundTds[7]}
|
|
||||||
{boundTds[8]}
|
|
||||||
</tr>,
|
|
||||||
];
|
|
||||||
|
|
||||||
//
|
|
||||||
// COMBINER
|
|
||||||
//
|
|
||||||
function combinerRmv(i) {
|
|
||||||
combiner[i] = null;
|
|
||||||
return combinerChange(combiner);
|
|
||||||
}
|
|
||||||
const combinerElement = (
|
|
||||||
<table class="vbox-table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td onClick={() => combinerRmv(0)}>
|
|
||||||
{combiner[0] !== null ? convertItem(vbox.bound[combiner[0]]) : shapes.vboxColour('gray')}
|
|
||||||
</td>
|
|
||||||
<td onClick={() => combinerRmv(1)}>
|
|
||||||
{combiner[1] !== null ? convertItem(vbox.bound[combiner[1]]) : shapes.vboxColour('gray')}
|
|
||||||
</td>
|
|
||||||
<td onClick={() => combinerRmv(2)}>
|
|
||||||
{convertItem(vbox.bound[combiner[2]])}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// EVERYTHING
|
|
||||||
//
|
|
||||||
|
|
||||||
function reclaimClick(e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
return setReclaiming(!reclaiming);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hoverInfo(e, info) {
|
|
||||||
e.stopPropagation();
|
|
||||||
return setInfo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
const classes = "vbox";
|
|
||||||
const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`;
|
|
||||||
|
|
||||||
|
function vboxElement() {
|
||||||
return (
|
return (
|
||||||
<div class={classes}>
|
<div class='vbox-vbox'
|
||||||
<div class='vbox-box'
|
|
||||||
onClick={() => setReclaiming(false)}
|
onClick={() => setReclaiming(false)}
|
||||||
onMouseOver={e => hoverInfo(e, 'vbox')}>
|
onMouseOver={e => hoverInfo(e, 'vbox')}>
|
||||||
<div class="vbox-hdr">
|
<div class="vbox-hdr">
|
||||||
<h3 onTouchStart={e => e.target.scrollIntoView(true)}>VBOX</h3>
|
<h3 onTouchStart={e => e.target.scrollIntoView(true)}>VBOX</h3>
|
||||||
<div class="bits" onMouseOver={e => hoverInfo(e, 'bits')} >{vbox.bits}b</div>
|
<div class="bits" onMouseOver={e => hoverInfo(e, 'bits')} >{vbox.bits}b</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: center"> Colours </div>
|
<div class="vbox-colours">
|
||||||
<table class="vbox-table">
|
{range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))}
|
||||||
<tbody>
|
</div>
|
||||||
{freeRows.slice(0, 2)}
|
<div class="vbox-items">
|
||||||
</tbody>
|
{range(0, 3).map(i => availableBtn(vbox.free[1][i], 1, i))}
|
||||||
</table>
|
{range(0, 3).map(i => availableBtn(vbox.free[2][i], 2, i))}
|
||||||
<div style="text-align: center"> Skills </div>
|
</div>
|
||||||
<table class="vbox-table">
|
|
||||||
<tbody>
|
|
||||||
{freeRows[2]}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div style="text-align: center"> Specs </div>
|
|
||||||
<table class="vbox-table">
|
|
||||||
<tbody>
|
|
||||||
{freeRows[3]}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<button
|
<button
|
||||||
|
class='vbox-btn'
|
||||||
onMouseOver={e => hoverInfo(e, 'reroll')}
|
onMouseOver={e => hoverInfo(e, 'reroll')}
|
||||||
onClick={() => sendVboxDiscard()}>
|
onClick={() => sendVboxDiscard()}>
|
||||||
Reroll
|
refill - 5b
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="vbox-arrow">⮞</div>
|
);
|
||||||
<div class="vbox-arrow-mobile">⮟</div>
|
}
|
||||||
<div class='vbox-inventory'
|
|
||||||
|
//
|
||||||
|
// INVENTORY
|
||||||
|
//
|
||||||
|
|
||||||
|
// const boundTds = range(0, 9).map(i => {
|
||||||
|
// const value = vbox.bound[i];
|
||||||
|
// if (combiner.indexOf(i) > -1) {
|
||||||
|
// return (
|
||||||
|
// <td
|
||||||
|
// key={i}>
|
||||||
|
//
|
||||||
|
// </td>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const highlighted = value && vboxHighlight.includes(value);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <td
|
||||||
|
// key={i}
|
||||||
|
// class={`${highlighted ? 'highlight' : ''}`}
|
||||||
|
// onMouseOver={(e) => vboxHover(e, value)}
|
||||||
|
// onClick={e => boundClick(e, i, highlighted) }>
|
||||||
|
// {convertItem(value)}
|
||||||
|
// </td>
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
function reclaimClick(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
return setReclaiming(!reclaiming);
|
||||||
|
}
|
||||||
|
|
||||||
|
const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`;
|
||||||
|
|
||||||
|
function inventoryBtn(v, i) {
|
||||||
|
if (!v && v !== 0) return <button disabled class='empty' > </button>;
|
||||||
|
|
||||||
|
function onClick(e) {
|
||||||
|
if (reclaiming) return sendVboxReclaim(i);
|
||||||
|
|
||||||
|
const combinerIndex = combiner.indexOf(i);
|
||||||
|
if (combinerIndex > -1) {
|
||||||
|
return combinerChange(without(combiner, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
combiner.push(i);
|
||||||
|
return combinerChange(combiner);
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlighted = combiner.indexOf(i) > -1;
|
||||||
|
const classes = `${highlighted ? 'highlight' : ''}`;
|
||||||
|
|
||||||
|
if (['Red', 'Green', 'Blue'].includes(v)) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
class={classes}
|
||||||
|
onMouseOver={e => vboxHover(e, v)}
|
||||||
|
onClick={onClick}>
|
||||||
|
{shapes.vboxColour(v.toLowerCase())}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
class={classes}
|
||||||
|
onClick={onClick}
|
||||||
|
onMouseOver={e => vboxHover(e, v)}>
|
||||||
|
{v}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function combinerBtn() {
|
||||||
|
let text = '';
|
||||||
|
|
||||||
|
if (combiner.length < 3) {
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
if (combiner.length > i) {
|
||||||
|
text += '■ ';
|
||||||
|
} else {
|
||||||
|
text += '▫ ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = 'combine';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
class='vbox-btn'
|
||||||
|
disabled={combiner.length !== 3}
|
||||||
|
onMouseOver={e => hoverInfo(e, 'refine')}
|
||||||
|
onClick={() => sendVboxCombine()}>
|
||||||
|
{text}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function inventoryElement() {
|
||||||
|
return (
|
||||||
|
<div class='vbox-section'
|
||||||
onClick={() => setReclaiming(false)}
|
onClick={() => setReclaiming(false)}
|
||||||
onMouseOver={e => hoverInfo(e, 'inventory')}>
|
onMouseOver={e => hoverInfo(e, 'inventory')}>
|
||||||
<div class="vbox-hdr">
|
<div class="vbox-hdr">
|
||||||
@ -338,21 +332,30 @@ function Vbox(args) {
|
|||||||
reclaim
|
reclaim
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<table class="vbox-table">
|
<div class='vbox-items'>
|
||||||
<tbody>
|
{range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))}
|
||||||
{boundRows}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="vbox-combiner-arrow" onTouchStart={e => e.target.scrollIntoView(true)}>⮟⮝</div>
|
{combinerBtn()}
|
||||||
<div class="vbox-combiner" onMouseOver={e => hoverInfo(e, 'combiner')} >
|
|
||||||
{combinerElement}
|
|
||||||
<button
|
|
||||||
onMouseOver={e => hoverInfo(e, 'refine')}
|
|
||||||
onClick={() => sendVboxCombine()}>
|
|
||||||
combine
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// EVERYTHING
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
function hoverInfo(e, info) {
|
||||||
|
e.stopPropagation();
|
||||||
|
return setInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
const classes = 'vbox';
|
||||||
|
return (
|
||||||
|
<div class={classes}>
|
||||||
|
{vboxElement()}
|
||||||
|
<div class="vbox-arrow">⮞</div>
|
||||||
|
{inventoryElement()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
|
|
||||||
const SOURCE_DURATION_MS = 1000;
|
const SOURCE_DURATION_MS = 1000;
|
||||||
const TARGET_DELAY_MS = 500;
|
const TARGET_DELAY_MS = 500;
|
||||||
const TARGET_DURATION_MS = 1500;
|
const TARGET_DURATION_MS = 1500;
|
||||||
|
const POST_SKILL_DELAY_MS = 2000;
|
||||||
const POST_SKILL_DURATION_MS = 1000;
|
const POST_SKILL_DURATION_MS = 1000;
|
||||||
const SOURCE_AND_TARGET_TOTAL_DURATION = TARGET_DELAY_MS + TARGET_DURATION_MS;
|
const SOURCE_AND_TARGET_TOTAL_DURATION = TARGET_DELAY_MS + TARGET_DURATION_MS + POST_SKILL_DURATION_MS;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
TIMES: {
|
TIMES: {
|
||||||
SOURCE_DURATION_MS,
|
SOURCE_DURATION_MS,
|
||||||
TARGET_DELAY_MS,
|
TARGET_DELAY_MS,
|
||||||
TARGET_DURATION_MS,
|
TARGET_DURATION_MS,
|
||||||
|
POST_SKILL_DELAY_MS,
|
||||||
POST_SKILL_DURATION_MS,
|
POST_SKILL_DURATION_MS,
|
||||||
SOURCE_AND_TARGET_TOTAL_DURATION,
|
SOURCE_AND_TARGET_TOTAL_DURATION,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3,7 +3,7 @@ const eachSeries = require('async/eachSeries');
|
|||||||
|
|
||||||
const actions = require('./actions');
|
const actions = require('./actions');
|
||||||
const { TIMES } = require('./constants');
|
const { TIMES } = require('./constants');
|
||||||
const { getCombatSequence } = require('./utils');
|
const animations = require('./animations.utils');
|
||||||
|
|
||||||
function registerEvents(store) {
|
function registerEvents(store) {
|
||||||
function setPing(ping) {
|
function setPing(ping) {
|
||||||
@ -42,57 +42,65 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setGame(game) {
|
function setGame(game) {
|
||||||
const { game: currentGame, ws } = store.getState();
|
const { game: currentGame, account, ws, animating } = store.getState();
|
||||||
|
|
||||||
|
if (animating) return false;
|
||||||
|
|
||||||
if (game && currentGame) {
|
if (game && currentGame) {
|
||||||
if (game.resolved.length !== currentGame.resolved.length) {
|
if (game.resolved.length !== currentGame.resolved.length) {
|
||||||
|
store.dispatch(actions.setAnimating(true));
|
||||||
|
|
||||||
// stop fetching the game state til animations are done
|
// stop fetching the game state til animations are done
|
||||||
const newRes = game.resolved.slice(currentGame.resolved.length);
|
const newRes = game.resolved.slice(currentGame.resolved.length);
|
||||||
let id = game.resolved.length - currentGame.resolved.length;
|
|
||||||
return eachSeries(newRes, (r, cb) => {
|
return eachSeries(newRes, (r, cb) => {
|
||||||
if (['Disable', 'TargetKo'].includes(r.event[0])) return cb();
|
if (['Disable', 'TargetKo'].includes(r.event[0])) return cb();
|
||||||
// Create sub events for combat animations
|
|
||||||
const sequence = getCombatSequence(r);
|
|
||||||
id += 1;
|
|
||||||
return eachSeries(sequence, (stages, sCb) => {
|
|
||||||
const stagedR = Object.create(r);
|
|
||||||
stagedR.sequence = sequence;
|
|
||||||
stagedR.stages = stages;
|
|
||||||
stagedR.id = id;
|
|
||||||
let timeout = 0;
|
|
||||||
if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) {
|
|
||||||
timeout = TIMES.SOURCE_AND_TARGET_TOTAL_DURATION;
|
|
||||||
} else if (stages.includes('START_SKILL')) timeout = TIMES.SOURCE_DURATION_MS;
|
|
||||||
else if (stages.includes('END_SKILL')) timeout = TIMES.TARGET_DURATION_MS;
|
|
||||||
else if (stages.includes('POST_SKILL')) timeout = TIMES.POST_SKILL_DURATION_MS;
|
|
||||||
store.dispatch(actions.setResolution(stagedR));
|
|
||||||
|
|
||||||
return setTimeout(sCb, timeout);
|
store.dispatch(actions.setResolution(r));
|
||||||
}, err => {
|
|
||||||
if (err) console.error(err);
|
// convert server enum into anims keywords
|
||||||
// Clear the anim classes
|
// todo make serersideonly
|
||||||
store.dispatch(actions.setResolution('clear'));
|
const sequence = animations.getSequence(r);
|
||||||
store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false }));
|
const timeout = animations.getTime(sequence);
|
||||||
// Finished this resolution small delay for reset
|
const anims = animations.getObjects(r, sequence, game, account);
|
||||||
return setTimeout(cb, 5);
|
const text = animations.getText(r, sequence);
|
||||||
});
|
|
||||||
|
if (sequence.includes('START_SKILL')) store.dispatch(actions.setAnimSource(anims.animSource));
|
||||||
|
if (sequence.includes('END_SKILL')) store.dispatch(actions.setAnimTarget(anims.animTarget));
|
||||||
|
if (sequence.includes('POST_SKILL')) {
|
||||||
|
// timeout to prevent text classes from being added too soon
|
||||||
|
setTimeout(
|
||||||
|
() => store.dispatch(actions.setAnimText(text)),
|
||||||
|
timeout - 1000,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setTimeout(() => {
|
||||||
|
store.dispatch(actions.setAnimSource(null));
|
||||||
|
store.dispatch(actions.setAnimTarget(null));
|
||||||
|
store.dispatch(actions.setAnimText(null));
|
||||||
|
return cb();
|
||||||
|
}, timeout);
|
||||||
|
|
||||||
}, err => {
|
}, err => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
store.dispatch(actions.setAvatarAnimation({ id: -1, source: false, target: false }));
|
// clear animation state
|
||||||
store.dispatch(actions.setResolution(null));
|
store.dispatch(actions.setAnimSource(null));
|
||||||
// stop skipping resolutions
|
store.dispatch(actions.setAnimTarget(null));
|
||||||
|
store.dispatch(actions.setAnimText(null));
|
||||||
|
store.dispatch(actions.setAnimating(false));
|
||||||
|
|
||||||
store.dispatch(actions.setSkip(false));
|
store.dispatch(actions.setSkip(false));
|
||||||
// update the game
|
store.dispatch(actions.setResolution(null));
|
||||||
|
|
||||||
|
// set the game state so resolutions don't fire twice
|
||||||
store.dispatch(actions.setGame(game));
|
store.dispatch(actions.setGame(game));
|
||||||
// get the latest state and restart polling
|
ws.sendGameState(game.id);
|
||||||
ws.sendGameState(currentGame.id);
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return store.dispatch(actions.setGame(game));
|
return store.dispatch(actions.setGame(game));
|
||||||
return console.log('EVENT ->', 'game', game);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAccount(account) {
|
function setAccount(account) {
|
||||||
@ -105,7 +113,7 @@ function registerEvents(store) {
|
|||||||
|
|
||||||
function clearCombiner() {
|
function clearCombiner() {
|
||||||
store.dispatch(actions.setInfo([]));
|
store.dispatch(actions.setInfo([]));
|
||||||
store.dispatch(actions.setCombiner([null, null, null]));
|
store.dispatch(actions.setCombiner([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearConstructRename() {
|
function clearConstructRename() {
|
||||||
@ -131,7 +139,7 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clearInstance() {
|
function clearInstance() {
|
||||||
store.dispatch(actions.setCombiner([null, null, null]));
|
store.dispatch(actions.setCombiner([]));
|
||||||
store.dispatch(actions.setReclaiming(false));
|
store.dispatch(actions.setReclaiming(false));
|
||||||
store.dispatch(actions.setActiveSkill(null));
|
store.dispatch(actions.setActiveSkill(null));
|
||||||
store.dispatch(actions.setActiveConstruct(null));
|
store.dispatch(actions.setActiveConstruct(null));
|
||||||
|
|||||||
@ -4,7 +4,7 @@ const actions = require('./actions');
|
|||||||
function setupKeys(store) {
|
function setupKeys(store) {
|
||||||
console.log('binding keys');
|
console.log('binding keys');
|
||||||
key.unbind('esc');
|
key.unbind('esc');
|
||||||
key('esc', () => store.dispatch(actions.setCombiner([null, null, null])));
|
key('esc', () => store.dispatch(actions.setCombiner([])));
|
||||||
key('esc', () => store.dispatch(actions.setReclaiming(false)));
|
key('esc', () => store.dispatch(actions.setReclaiming(false)));
|
||||||
key('esc', () => store.dispatch(actions.setActiveSkill(null)));
|
key('esc', () => store.dispatch(actions.setActiveSkill(null)));
|
||||||
key('esc', () => store.dispatch(actions.setActiveConstruct(null)));
|
key('esc', () => store.dispatch(actions.setActiveConstruct(null)));
|
||||||
|
|||||||
@ -15,8 +15,13 @@ module.exports = {
|
|||||||
activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'),
|
activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'),
|
||||||
activeItem: createReducer(null, 'SET_ACTIVE_VAR'),
|
activeItem: createReducer(null, 'SET_ACTIVE_VAR'),
|
||||||
activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'),
|
activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'),
|
||||||
avatarAnimation: createReducer({ id: -1, source: false, target: false }, 'SET_AVATAR_ANIMATION'),
|
|
||||||
combiner: createReducer([null, null, null], 'SET_COMBINER'),
|
animating: createReducer(false, 'SET_ANIMATING'),
|
||||||
|
animSource: createReducer(null, 'SET_ANIM_SOURCE'),
|
||||||
|
animTarget: createReducer(null, 'SET_ANIM_TARGET'),
|
||||||
|
animText: createReducer(null, 'SET_ANIM_TEXT'),
|
||||||
|
|
||||||
|
combiner: createReducer([], 'SET_COMBINER'),
|
||||||
constructs: createReducer([], 'SET_CONSTRUCTS'),
|
constructs: createReducer([], 'SET_CONSTRUCTS'),
|
||||||
constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'),
|
constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'),
|
||||||
constructRename: createReducer(null, 'SET_CONSTRUCT_RENAME'),
|
constructRename: createReducer(null, 'SET_CONSTRUCT_RENAME'),
|
||||||
@ -39,5 +44,8 @@ module.exports = {
|
|||||||
shop: createReducer(false, 'SET_SHOP'),
|
shop: createReducer(false, 'SET_SHOP'),
|
||||||
team: createReducer([null, null, null], 'SET_SELECTED_CONSTRUCTS'),
|
team: createReducer([null, null, null], 'SET_SELECTED_CONSTRUCTS'),
|
||||||
vboxHighlight: createReducer([], 'SET_VBOX_HIGHLIGHT'),
|
vboxHighlight: createReducer([], 'SET_VBOX_HIGHLIGHT'),
|
||||||
|
|
||||||
|
vboxSelected: createReducer([], 'SET_VBOX_SELECTED'),
|
||||||
|
|
||||||
ws: createReducer(null, 'SET_WS'),
|
ws: createReducer(null, 'SET_WS'),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,6 +35,7 @@ function testGame(uuid) {
|
|||||||
"constructs": [
|
"constructs": [
|
||||||
{
|
{
|
||||||
"id": "82e8b940-411c-42a1-8fc2-484ec7207734",
|
"id": "82e8b940-411c-42a1-8fc2-484ec7207734",
|
||||||
|
"img": "8446736d-d682-4588-b8a0-5b7ba53bdb55",
|
||||||
"account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1",
|
"account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1",
|
||||||
"red_damage": {
|
"red_damage": {
|
||||||
"base": 256,
|
"base": 256,
|
||||||
@ -108,6 +109,7 @@ function testGame(uuid) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "96ca4a0e-fed2-4ea2-9ec5-ae308f8dde4b",
|
"id": "96ca4a0e-fed2-4ea2-9ec5-ae308f8dde4b",
|
||||||
|
"img": "8446736d-d682-4588-b8a0-5b7ba53bdb55",
|
||||||
"account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1",
|
"account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1",
|
||||||
"red_damage": {
|
"red_damage": {
|
||||||
"base": 256,
|
"base": 256,
|
||||||
@ -184,6 +186,7 @@ function testGame(uuid) {
|
|||||||
{
|
{
|
||||||
"id": "ea302c35-d326-475c-a867-8ad5b162165a",
|
"id": "ea302c35-d326-475c-a867-8ad5b162165a",
|
||||||
"account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1",
|
"account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1",
|
||||||
|
"img": "8446736d-d682-4588-b8a0-5b7ba53bdb55",
|
||||||
"red_damage": {
|
"red_damage": {
|
||||||
"base": 256,
|
"base": 256,
|
||||||
"value": Math.floor(Math.random() * 10000),
|
"value": Math.floor(Math.random() * 10000),
|
||||||
@ -299,6 +302,7 @@ function testGame(uuid) {
|
|||||||
{
|
{
|
||||||
"id": "3aa0f284-1e1b-4054-b38a-b2d50db471bd",
|
"id": "3aa0f284-1e1b-4054-b38a-b2d50db471bd",
|
||||||
"account": uuid,
|
"account": uuid,
|
||||||
|
"img": "8446736d-d682-4588-b8a0-5b7ba53bdb55",
|
||||||
"red_damage": {
|
"red_damage": {
|
||||||
"base": 256,
|
"base": 256,
|
||||||
"value": Math.floor(Math.random() * 10000),
|
"value": Math.floor(Math.random() * 10000),
|
||||||
@ -385,6 +389,7 @@ function testGame(uuid) {
|
|||||||
{
|
{
|
||||||
"id": "50e5d94e-8ebe-495c-a916-3eb509ff4683",
|
"id": "50e5d94e-8ebe-495c-a916-3eb509ff4683",
|
||||||
"account": uuid,
|
"account": uuid,
|
||||||
|
"img": "8446736d-d682-4588-b8a0-5b7ba53bdb55",
|
||||||
"red_damage": {
|
"red_damage": {
|
||||||
"base": 256,
|
"base": 256,
|
||||||
"value": Math.floor(Math.random() * 10000),
|
"value": Math.floor(Math.random() * 10000),
|
||||||
@ -465,6 +470,7 @@ function testGame(uuid) {
|
|||||||
{
|
{
|
||||||
"id": "5d49fe65-27f0-4372-90a3-334ef906a0f5",
|
"id": "5d49fe65-27f0-4372-90a3-334ef906a0f5",
|
||||||
"account": uuid,
|
"account": uuid,
|
||||||
|
"img": "8446736d-d682-4588-b8a0-5b7ba53bdb55",
|
||||||
"red_damage": {
|
"red_damage": {
|
||||||
"base": 256,
|
"base": 256,
|
||||||
"value": Math.floor(Math.random() * 10000),
|
"value": Math.floor(Math.random() * 10000),
|
||||||
|
|||||||
@ -4,6 +4,17 @@ const toast = require('izitoast');
|
|||||||
|
|
||||||
const shapes = require('./components/shapes');
|
const shapes = require('./components/shapes');
|
||||||
|
|
||||||
|
function match(value, patterns) {
|
||||||
|
for (let i = 0; i < patterns.length; i++) {
|
||||||
|
if (value === patterns[i][0]) {
|
||||||
|
return patterns[i][1]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn('default match - return null', value, patterns);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const stringSort = (k, desc) => {
|
const stringSort = (k, desc) => {
|
||||||
if (desc) {
|
if (desc) {
|
||||||
return (a, b) => {
|
return (a, b) => {
|
||||||
@ -74,9 +85,8 @@ const STATS = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function eventClasses(game, account, resolution, construct) {
|
function eventClasses(game, account, resolution, construct, postSkill) {
|
||||||
if (!resolution || resolution === 'clear') return '';
|
if (!resolution) return '';
|
||||||
const postSkill = resolution.stages.includes('POST_SKILL');
|
|
||||||
const source = construct.id === resolution.source.id;
|
const source = construct.id === resolution.source.id;
|
||||||
const target = construct.id === resolution.target.id;
|
const target = construct.id === resolution.target.id;
|
||||||
// not involved at all. blur them
|
// not involved at all. blur them
|
||||||
@ -102,7 +112,7 @@ function eventClasses(game, account, resolution, construct) {
|
|||||||
|
|
||||||
if (type === 'Damage') {
|
if (type === 'Damage') {
|
||||||
const { colour } = event;
|
const { colour } = event;
|
||||||
if (target && postSkill) {
|
if (target) {
|
||||||
construct.green_life.value = resolution.target.green;
|
construct.green_life.value = resolution.target.green;
|
||||||
if (colour === 'Red') {
|
if (colour === 'Red') {
|
||||||
construct.red_life.value = resolution.target.red;
|
construct.red_life.value = resolution.target.red;
|
||||||
@ -158,98 +168,6 @@ function eventClasses(game, account, resolution, construct) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCombatSequence(resolution) {
|
|
||||||
if (!resolution.event) return false;
|
|
||||||
if (resolution.event[0] === 'Inversion') return false;
|
|
||||||
if (['Skill', 'AoeSkill'].includes(resolution.event[0])) return [['START_SKILL', 'END_SKILL']];
|
|
||||||
if (resolution.event[0] === 'Ko') return [['POST_SKILL']];
|
|
||||||
|
|
||||||
switch (resolution.stages) {
|
|
||||||
case 1: return [['START_SKILL', 'END_SKILL']];
|
|
||||||
case 2: return [['START_SKILL'], ['POST_SKILL']];
|
|
||||||
case 3: return [['START_SKILL']];
|
|
||||||
case 4: return [['END_SKILL'], ['POST_SKILL']];
|
|
||||||
case 5: return [['END_SKILL']];
|
|
||||||
case 6: return [['POST_SKILL']];
|
|
||||||
case 7: return false;
|
|
||||||
default: return [['START_SKILL', 'END_SKILL'], ['POST_SKILL']];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCombatText(resolution, construct) {
|
|
||||||
if (!resolution || resolution === 'clear') return false;
|
|
||||||
if (!resolution.stages.includes('POST_SKILL')) return false;
|
|
||||||
if (construct.id !== resolution.target.id) return false;
|
|
||||||
|
|
||||||
const [type, event] = resolution.event;
|
|
||||||
if (type === 'Ko') {
|
|
||||||
return 'KO!';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Disable') {
|
|
||||||
const { disable } = event;
|
|
||||||
return `${disable}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Immunity') {
|
|
||||||
return 'IMMUNE';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Damage') {
|
|
||||||
const { mitigation, colour } = event;
|
|
||||||
let { amount } = event;
|
|
||||||
if (colour === 'Green') amount *= -1;
|
|
||||||
const mitigationText = mitigation
|
|
||||||
? `(${mitigation})`
|
|
||||||
: '';
|
|
||||||
return `${amount} ${mitigationText}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Healing') {
|
|
||||||
const { amount, overhealing } = event;
|
|
||||||
return `${amount} (${overhealing} OH)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Inversion') {
|
|
||||||
return 'INVERT';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Reflection') {
|
|
||||||
return 'REFLECT';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Effect') {
|
|
||||||
const { effect, duration } = event;
|
|
||||||
return `+ ${effect} ${duration}T`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Recharge') {
|
|
||||||
const { red, blue } = event;
|
|
||||||
return [`+${red}R ${blue}B`, ''];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Removal') {
|
|
||||||
const { effect } = event;
|
|
||||||
return `-${effect}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertItem(v) {
|
|
||||||
if (['Red', 'Green', 'Blue'].includes(v)) {
|
|
||||||
return (
|
|
||||||
shapes.vboxColour(v.toLowerCase())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return v || <span> </span>;
|
|
||||||
// uncomment for double borders in vbox;
|
|
||||||
// if (v) {
|
|
||||||
// return <div>{v}</div>;
|
|
||||||
// }
|
|
||||||
// return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const COLOURS = [
|
const COLOURS = [
|
||||||
'#a52a2a',
|
'#a52a2a',
|
||||||
'#1FF01F',
|
'#1FF01F',
|
||||||
@ -379,15 +297,26 @@ function errorToast(message) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convertItem(v) {
|
||||||
|
if (['Red', 'Green', 'Blue'].includes(v)) {
|
||||||
|
return (
|
||||||
|
shapes.vboxColour(v.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return v || <span> </span>;
|
||||||
|
// uncomment for double borders in vbox;
|
||||||
|
// if (v) {
|
||||||
|
// return <div>{v}</div>;
|
||||||
|
// }
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
stringSort,
|
stringSort,
|
||||||
convertItem,
|
|
||||||
numSort,
|
numSort,
|
||||||
eventClasses,
|
eventClasses,
|
||||||
getCombatSequence,
|
|
||||||
getCombatText,
|
|
||||||
postData,
|
postData,
|
||||||
|
convertItem,
|
||||||
errorToast,
|
errorToast,
|
||||||
NULL_UUID,
|
NULL_UUID,
|
||||||
STATS,
|
STATS,
|
||||||
@ -395,4 +324,5 @@ module.exports = {
|
|||||||
TARGET_COLOURS,
|
TARGET_COLOURS,
|
||||||
randomPoints,
|
randomPoints,
|
||||||
removeTier,
|
removeTier,
|
||||||
|
match,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -277,7 +277,7 @@ impl Construct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn spec_add(&mut self, spec: Spec) -> Result<&mut Construct, Error> {
|
pub fn spec_add(&mut self, spec: Spec) -> Result<&mut Construct, Error> {
|
||||||
if self.specs.len() >= 6 {
|
if self.specs.len() >= 3 {
|
||||||
return Err(err_msg("maximum specs equipped"));
|
return Err(err_msg("maximum specs equipped"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rand::{thread_rng};
|
use rand::{thread_rng};
|
||||||
|
|
||||||
const FIRSTS: [&'static str; 25] = [
|
const FIRSTS: [&'static str; 33] = [
|
||||||
|
"artificial",
|
||||||
|
"ambient",
|
||||||
"borean",
|
"borean",
|
||||||
"brewing",
|
"brewing",
|
||||||
"bristling",
|
"bristling",
|
||||||
"compressed",
|
"compressed",
|
||||||
|
"chromatic",
|
||||||
"concave",
|
"concave",
|
||||||
"convex",
|
"convex",
|
||||||
"distorted",
|
"distorted",
|
||||||
@ -15,9 +18,13 @@ const FIRSTS: [&'static str; 25] = [
|
|||||||
"leafy",
|
"leafy",
|
||||||
"lurking",
|
"lurking",
|
||||||
"metallic",
|
"metallic",
|
||||||
|
"mossy",
|
||||||
"mighty",
|
"mighty",
|
||||||
|
"modulated",
|
||||||
"nocturnal",
|
"nocturnal",
|
||||||
|
"noisy",
|
||||||
"nutritious",
|
"nutritious",
|
||||||
|
"powerful",
|
||||||
"obscure",
|
"obscure",
|
||||||
"organic",
|
"organic",
|
||||||
"piscine",
|
"piscine",
|
||||||
@ -25,39 +32,47 @@ const FIRSTS: [&'static str; 25] = [
|
|||||||
"recalcitrant",
|
"recalcitrant",
|
||||||
"rogue",
|
"rogue",
|
||||||
"subterranean",
|
"subterranean",
|
||||||
|
"synthetic",
|
||||||
"sweet",
|
"sweet",
|
||||||
"weary",
|
"weary",
|
||||||
];
|
];
|
||||||
|
|
||||||
const LASTS: [&'static str; 34] = [
|
const LASTS: [&'static str; 41] = [
|
||||||
"artifact",
|
"artifact",
|
||||||
"assembly",
|
"assembly",
|
||||||
"console",
|
"console",
|
||||||
"construct",
|
"construct",
|
||||||
"design",
|
"design",
|
||||||
|
"drone",
|
||||||
|
"energy",
|
||||||
"entropy",
|
"entropy",
|
||||||
"foilage",
|
"foilage",
|
||||||
"forest",
|
"forest",
|
||||||
"form",
|
"form",
|
||||||
|
"fossil",
|
||||||
"frequency",
|
"frequency",
|
||||||
"function",
|
"function",
|
||||||
"information",
|
"information",
|
||||||
"insulator",
|
"insulator",
|
||||||
"kaffe",
|
|
||||||
"layout",
|
"layout",
|
||||||
"lens",
|
"lens",
|
||||||
"mechanism",
|
"mechanism",
|
||||||
"mountain",
|
"mountain",
|
||||||
"nectar",
|
"nectar",
|
||||||
"oak",
|
"oak",
|
||||||
|
"pattern",
|
||||||
"plant",
|
"plant",
|
||||||
"poseidon",
|
"poseidon",
|
||||||
"problem",
|
"problem",
|
||||||
|
"receiver",
|
||||||
"replicant",
|
"replicant",
|
||||||
"river",
|
"river",
|
||||||
"river",
|
"river",
|
||||||
|
"scaffold",
|
||||||
"shape",
|
"shape",
|
||||||
"signal",
|
"signal",
|
||||||
|
"synthesiser",
|
||||||
|
"system",
|
||||||
"tower",
|
"tower",
|
||||||
"transmitter",
|
"transmitter",
|
||||||
"traveller",
|
"traveller",
|
||||||
|
|||||||
@ -405,15 +405,15 @@ pub struct EventConstruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
pub enum LogStages {
|
pub enum EventStages {
|
||||||
AllStages, // 0 Anim Anim Anim
|
AllStages, // Anim Anim Anim
|
||||||
StartEnd, // 1 Anim Anim Skip
|
StartEnd, // Anim Anim Skip
|
||||||
StartPost, // 2 Anim Skip Anim
|
StartPost, // Anim Skip Anim
|
||||||
StartOnly, // 3 Anim Skip Skip
|
StartOnly, // Anim Skip Skip
|
||||||
EndPost, // 4 Skip Anim Anim
|
EndPost, // Skip Anim Anim
|
||||||
EndOnly, // 5 Skip Anim Skip
|
EndOnly, // Skip Anim Skip
|
||||||
PostOnly, // 6 Skip Skip Anim
|
PostOnly, // Skip Skip Anim
|
||||||
None, // 7 Skip Skip Skip
|
None, // Skip Skip Skip
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
@ -421,7 +421,7 @@ pub struct Resolution {
|
|||||||
pub source: EventConstruct,
|
pub source: EventConstruct,
|
||||||
pub target: EventConstruct,
|
pub target: EventConstruct,
|
||||||
pub event: Event,
|
pub event: Event,
|
||||||
pub stages: u8,
|
pub stages: EventStages,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolution {
|
impl Resolution {
|
||||||
@ -440,7 +440,7 @@ impl Resolution {
|
|||||||
blue: target.blue_life(),
|
blue: target.blue_life(),
|
||||||
},
|
},
|
||||||
event: Event::Incomplete,
|
event: Event::Incomplete,
|
||||||
stages: LogStages::AllStages as u8,
|
stages: EventStages::AllStages,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,8 +449,8 @@ impl Resolution {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stages(mut self, s: LogStages) -> Resolution {
|
fn stages(mut self, s: EventStages) -> Resolution {
|
||||||
self.stages = s as u8;
|
self.stages = s;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1268,7 +1268,7 @@ fn bash(source: &mut Construct, target: &mut Construct, mut results: Resolutions
|
|||||||
let amount = source.red_power().pct(skill.multiplier().pct(100 + 45u64.saturating_mul(cds)));
|
let amount = source.red_power().pct(skill.multiplier().pct(100 + 45u64.saturating_mul(cds)));
|
||||||
target.deal_red_damage(skill, amount)
|
target.deal_red_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
@ -1282,7 +1282,7 @@ fn sleep(source: &mut Construct, target: &mut Construct, mut results: Resolution
|
|||||||
let amount = source.green_power().pct(skill.multiplier());
|
let amount = source.green_power().pct(skill.multiplier());
|
||||||
target.deal_green_damage(skill, amount)
|
target.deal_green_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly)));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -1298,7 +1298,7 @@ fn intercept(source: &mut Construct, target: &mut Construct, mut results: Resolu
|
|||||||
results.push(Resolution::new(source, target).event(target.recharge(skill, red_amount, 0)));
|
results.push(Resolution::new(source, target).event(target.recharge(skill, red_amount, 0)));
|
||||||
|
|
||||||
let intercept = skill.effect()[0];
|
let intercept = skill.effect()[0];
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, intercept)).stages(LogStages::PostOnly));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, intercept)).stages(EventStages::PostOnly));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1306,7 +1306,7 @@ fn break_(source: &mut Construct, target: &mut Construct, mut results: Resolutio
|
|||||||
let stun = skill.effect()[0];
|
let stun = skill.effect()[0];
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, stun)));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, stun)));
|
||||||
let vuln = skill.effect()[1];
|
let vuln = skill.effect()[1];
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, vuln)).stages(LogStages::PostOnly));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, vuln)).stages(EventStages::PostOnly));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -1314,7 +1314,7 @@ fn break_(source: &mut Construct, target: &mut Construct, mut results: Resolutio
|
|||||||
fn block(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn block(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.add_effect(skill, skill.effect()[0]))
|
.event(target.add_effect(skill, skill.effect()[0]))
|
||||||
.stages(LogStages::StartEnd));
|
.stages(EventStages::StartEnd));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1328,11 +1328,11 @@ fn counter(source: &mut Construct, target: &mut Construct, mut results: Resoluti
|
|||||||
let red_amount = source.red_power().pct(skill.multiplier());
|
let red_amount = source.red_power().pct(skill.multiplier());
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.recharge(skill, red_amount, 0))
|
.event(target.recharge(skill, red_amount, 0))
|
||||||
.stages(LogStages::StartEnd));
|
.stages(EventStages::StartEnd));
|
||||||
|
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.add_effect(skill, skill.effect()[0]))
|
.event(target.add_effect(skill, skill.effect()[0]))
|
||||||
.stages(LogStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -1341,7 +1341,7 @@ fn riposte(source: &mut Construct, target: &mut Construct, mut results: Resoluti
|
|||||||
let amount = source.red_power().pct(skill.multiplier());
|
let amount = source.red_power().pct(skill.multiplier());
|
||||||
target.deal_red_damage(skill, amount)
|
target.deal_red_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::StartPost)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::StartPost)));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -1360,7 +1360,7 @@ fn restrict(source: &mut Construct, target: &mut Construct, mut results: Resolut
|
|||||||
let amount = source.red_power().pct(skill.multiplier()).pct(s_multi);
|
let amount = source.red_power().pct(skill.multiplier()).pct(s_multi);
|
||||||
target.deal_red_damage(skill, amount)
|
target.deal_red_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly)));
|
||||||
|
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
@ -1376,7 +1376,7 @@ fn slay(source: &mut Construct, target: &mut Construct, mut results: Resolutions
|
|||||||
results.push(Resolution::new(source, target).event(e));
|
results.push(Resolution::new(source, target).event(e));
|
||||||
let heal = source.deal_green_damage(skill, amount);
|
let heal = source.deal_green_damage(skill, amount);
|
||||||
for h in heal {
|
for h in heal {
|
||||||
results.push(Resolution::new(source, source).event(h).stages(LogStages::PostOnly));
|
results.push(Resolution::new(source, source).event(h).stages(EventStages::PostOnly));
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
_ => results.push(Resolution::new(source, target).event(e)),
|
_ => results.push(Resolution::new(source, target).event(e)),
|
||||||
@ -1409,7 +1409,7 @@ fn triage_tick(source: &mut Construct, target: &mut Construct, mut results: Reso
|
|||||||
let amount = source.green_power().pct(skill.multiplier());
|
let amount = source.green_power().pct(skill.multiplier());
|
||||||
target.deal_green_damage(skill, amount)
|
target.deal_green_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost)));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1424,7 +1424,7 @@ fn chaos(source: &mut Construct, target: &mut Construct, mut results: Resolution
|
|||||||
let amount = source.red_power().pct(skill.multiplier()).pct(r_rng);
|
let amount = source.red_power().pct(skill.multiplier()).pct(r_rng);
|
||||||
target.deal_red_damage(skill, amount)
|
target.deal_red_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly)));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1464,7 +1464,7 @@ fn decay(source: &mut Construct, target: &mut Construct, mut results: Resolution
|
|||||||
let decay = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill));
|
let decay = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill));
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.add_effect(skill, decay))
|
.event(target.add_effect(skill, decay))
|
||||||
.stages(LogStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
|
|
||||||
return decay_tick(source, target, results, tick_skill);
|
return decay_tick(source, target, results, tick_skill);
|
||||||
}
|
}
|
||||||
@ -1473,7 +1473,7 @@ fn decay_tick(source: &mut Construct, target: &mut Construct, mut results: Resol
|
|||||||
let amount = source.blue_power().pct(skill.multiplier());
|
let amount = source.blue_power().pct(skill.multiplier());
|
||||||
target.deal_blue_damage(skill, amount)
|
target.deal_blue_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost)));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1495,7 +1495,7 @@ fn electrocute(source: &mut Construct, target: &mut Construct, mut results: Reso
|
|||||||
let electrocute = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill));
|
let electrocute = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill));
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.add_effect(skill, electrocute))
|
.event(target.add_effect(skill, electrocute))
|
||||||
.stages(LogStages::StartPost));
|
.stages(EventStages::StartPost));
|
||||||
return electrocute_tick(source, target, results, tick_skill);
|
return electrocute_tick(source, target, results, tick_skill);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1503,14 +1503,14 @@ fn electrocute_tick(source: &mut Construct, target: &mut Construct, mut results:
|
|||||||
let amount = source.blue_power().pct(skill.multiplier());
|
let amount = source.blue_power().pct(skill.multiplier());
|
||||||
target.deal_blue_damage(skill, amount)
|
target.deal_blue_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost)));
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ruin(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn ruin(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.add_effect(skill, skill.effect()[0]))
|
.event(target.add_effect(skill, skill.effect()[0]))
|
||||||
.stages(LogStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
return results;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1529,7 +1529,7 @@ fn absorption(source: &mut Construct, target: &mut Construct, mut results: Resol
|
|||||||
let absorb = skill.effect()[0].set_meta(EffectMeta::AddedDamage(amount));
|
let absorb = skill.effect()[0].set_meta(EffectMeta::AddedDamage(amount));
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.add_effect(reflect_skill, absorb))
|
.event(target.add_effect(reflect_skill, absorb))
|
||||||
.stages(LogStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
return results;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1554,7 +1554,7 @@ fn reflect(source: &mut Construct, target: &mut Construct, mut results: Resoluti
|
|||||||
let blue_amount = source.blue_power().pct(skill.multiplier());
|
let blue_amount = source.blue_power().pct(skill.multiplier());
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(target.recharge(skill, 0, blue_amount))
|
.event(target.recharge(skill, 0, blue_amount))
|
||||||
.stages(LogStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
|
|
||||||
return results;;
|
return results;;
|
||||||
}
|
}
|
||||||
@ -1586,13 +1586,13 @@ fn siphon_tick(source: &mut Construct, target: &mut Construct, mut results: Reso
|
|||||||
for e in siphon_events {
|
for e in siphon_events {
|
||||||
match e {
|
match e {
|
||||||
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
|
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
|
||||||
results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost));
|
results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost));
|
||||||
let heal = source.deal_green_damage(skill, amount);
|
let heal = source.deal_green_damage(skill, amount);
|
||||||
for h in heal {
|
for h in heal {
|
||||||
results.push(Resolution::new(source, source).event(h).stages(LogStages::PostOnly));
|
results.push(Resolution::new(source, source).event(h).stages(EventStages::PostOnly));
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
_ => results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)),
|
_ => results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1604,7 +1604,7 @@ fn link(source: &mut Construct, target: &mut Construct, mut results: Resolutions
|
|||||||
results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount)));
|
results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount)));
|
||||||
|
|
||||||
let link = skill.effect()[0].set_meta(EffectMeta::LinkTarget(target.id));
|
let link = skill.effect()[0].set_meta(EffectMeta::LinkTarget(target.id));
|
||||||
results.push(Resolution::new(source, target).event(source.add_effect(skill, link)).stages(LogStages::PostOnly));
|
results.push(Resolution::new(source, target).event(source.add_effect(skill, link)).stages(EventStages::PostOnly));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -1625,7 +1625,7 @@ fn link_hit(source: &Construct, target: &Construct, mut results: Resolutions, ga
|
|||||||
|
|
||||||
results.push(Resolution::new(target, link_target).event(Event::Skill { skill: Skill::LinkI }));
|
results.push(Resolution::new(target, link_target).event(Event::Skill { skill: Skill::LinkI }));
|
||||||
res.into_iter().for_each(|e| results.push(Resolution::new(&source, &link_target)
|
res.into_iter().for_each(|e| results.push(Resolution::new(&source, &link_target)
|
||||||
.event(e).stages(LogStages::EndPost)));
|
.event(e).stages(EventStages::EndPost)));
|
||||||
} else {
|
} else {
|
||||||
panic!("not a link target {:?}", link);
|
panic!("not a link target {:?}", link);
|
||||||
}
|
}
|
||||||
@ -1649,7 +1649,7 @@ fn silence(source: &mut Construct, target: &mut Construct, mut results: Resoluti
|
|||||||
let amount = source.blue_power().pct(skill.multiplier()).pct(s_multi);
|
let amount = source.blue_power().pct(skill.multiplier()).pct(s_multi);
|
||||||
target.deal_blue_damage(skill, amount)
|
target.deal_blue_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly)));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -1700,10 +1700,10 @@ fn purify(source: &mut Construct, target: &mut Construct, mut results: Resolutio
|
|||||||
let ce = target.effects.remove(i);
|
let ce = target.effects.remove(i);
|
||||||
results.push(Resolution::new(source, target)
|
results.push(Resolution::new(source, target)
|
||||||
.event(Event::Removal { effect: ce.effect, construct_effects: target.effects.clone() })
|
.event(Event::Removal { effect: ce.effect, construct_effects: target.effects.clone() })
|
||||||
.stages(LogStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
target.deal_green_damage(skill, amount)
|
target.deal_green_damage(skill, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user