Merge branch 'release/1.12.2'
This commit is contained in:
commit
db753e5e97
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.12.1",
|
"version": "1.12.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -15,3 +15,5 @@ cd $MNML_PATH/ops && npm --allow-same-version --no-git-tag-version version "$VER
|
|||||||
cd $MNML_PATH/client && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
cd $MNML_PATH/client && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
||||||
cd $MNML_PATH/acp && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
cd $MNML_PATH/acp && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
||||||
cd $MNML_PATH/studios && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
cd $MNML_PATH/studios && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
||||||
|
|
||||||
|
git commit -am "v$VERSION"
|
||||||
@ -112,7 +112,7 @@ section {
|
|||||||
figure {
|
figure {
|
||||||
letter-spacing: 0.25em;
|
letter-spacing: 0.25em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 125%;
|
font-size: 1.5em;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
}
|
}
|
||||||
@ -138,27 +138,14 @@ section {
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.ready:enabled {
|
|
||||||
color: forestgreen;
|
|
||||||
border-color: forestgreen;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: forestgreen;
|
|
||||||
color: black;
|
|
||||||
border-color: forestgreen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// // all green
|
|
||||||
// button.ready:enabled {
|
// button.ready:enabled {
|
||||||
// background: forestgreen;
|
// color: forestgreen;
|
||||||
// color: black;
|
|
||||||
// border-color: forestgreen;
|
// border-color: forestgreen;
|
||||||
|
|
||||||
// &:hover {
|
// &:hover {
|
||||||
// color: forestgreen;
|
// background: forestgreen;
|
||||||
|
// color: black;
|
||||||
// border-color: forestgreen;
|
// border-color: forestgreen;
|
||||||
// background: 0;
|
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -173,6 +173,19 @@ button, input {
|
|||||||
// &:active {
|
// &:active {
|
||||||
// filter: url("#noiseFilter");
|
// filter: url("#noiseFilter");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// all green
|
||||||
|
&.ready:enabled {
|
||||||
|
background: forestgreen;
|
||||||
|
color: black;
|
||||||
|
border-color: forestgreen;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: forestgreen;
|
||||||
|
border-color: forestgreen;
|
||||||
|
background: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@ -269,6 +282,10 @@ figure.gray {
|
|||||||
@media (max-width: 1500px) {
|
@media (max-width: 1500px) {
|
||||||
#mnml {
|
#mnml {
|
||||||
font-size: 75%;
|
font-size: 75%;
|
||||||
|
|
||||||
|
&.front-page main {
|
||||||
|
padding: 0 10%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.12.1",
|
"version": "1.12.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class Amplify extends Component {
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 200 200">
|
viewBox="0 0 200 200">
|
||||||
<filter id="amplifyFilter">
|
<filter id="amplifyFilter">
|
||||||
<feTurbulence type="turbulence" baseFrequency="0.4" numOctaves="2" result="turbulence"></feTurbulence>
|
<feTurbulence type="turbulence" baseFrequency="0.1" numOctaves="2" result="turbulence"></feTurbulence>
|
||||||
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="2" xChannelSelector="R" yChannelSelector="G"></feDisplacementMap>
|
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="2" xChannelSelector="R" yChannelSelector="G"></feDisplacementMap>
|
||||||
</filter>
|
</filter>
|
||||||
<path filter='url("#amplifyFilter")' d={path} />
|
<path filter='url("#amplifyFilter")' d={path} />
|
||||||
|
|||||||
@ -6,8 +6,8 @@ function sourceCast(id, direction, idle) {
|
|||||||
const { x, y } = direction;
|
const { x, y } = direction;
|
||||||
return anime({
|
return anime({
|
||||||
targets: [document.getElementById(id)],
|
targets: [document.getElementById(id)],
|
||||||
translateX: x * window.screen.width * 0.1,
|
translateX: x * window.innerWidth * 0.1,
|
||||||
translateY: y * window.screen.height * 0.1,
|
translateY: y * window.innerHeight * 0.1,
|
||||||
easing: 'easeInOutElastic',
|
easing: 'easeInOutElastic',
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
duration: TIMES.SOURCE_DURATION_MS,
|
duration: TIMES.SOURCE_DURATION_MS,
|
||||||
|
|||||||
@ -69,7 +69,11 @@ class ConstructAvatar extends Component {
|
|||||||
const type = resolution.event[0];
|
const type = resolution.event[0];
|
||||||
// only trigger the wiggle on damage and ko events rather than spam it on everything
|
// only trigger the wiggle on damage and ko events rather than spam it on everything
|
||||||
// also stops wiggle triggering when invert effect is applied
|
// also stops wiggle triggering when invert effect is applied
|
||||||
if (['Damage', 'Ko'].includes(type)) return wiggle(construct.id, this.idle);
|
const wiggleEvents = [
|
||||||
|
'Damage',
|
||||||
|
// 'Ko'
|
||||||
|
];
|
||||||
|
if (wiggleEvents.includes(type)) return wiggle(construct.id, this.idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// different source object and source construct
|
// different source object and source construct
|
||||||
|
|||||||
@ -63,6 +63,8 @@ class AnimText extends preact.Component {
|
|||||||
}
|
}
|
||||||
case 'Ko': return <h1><span>KO!</span></h1>;
|
case 'Ko': return <h1><span>KO!</span></h1>;
|
||||||
case 'Reflection': return <h1><span>REFLECT</span></h1>;
|
case 'Reflection': return <h1><span>REFLECT</span></h1>;
|
||||||
|
case 'CooldownIncrease': return <h1>+{event.turns}T cooldowns</h1>;
|
||||||
|
case 'CooldownDecrease': return <h1>-{event.turns}T cooldowns</h1>;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -82,9 +82,11 @@ function Skill(props) {
|
|||||||
|
|
||||||
const border = buttons[removeTier(s.skill)] ? buttons[removeTier(s.skill)]() : '';
|
const border = buttons[removeTier(s.skill)] ? buttons[removeTier(s.skill)]() : '';
|
||||||
|
|
||||||
|
const notSkill = game.phase !== 'Skill';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
disabled={cdText || s.disabled || ko}
|
disabled={cdText || s.disabled || ko || notSkill}
|
||||||
class={`${(targeting || highlight) ? 'active' : ''} ${border}`}
|
class={`${(targeting || highlight) ? 'active' : ''} ${border}`}
|
||||||
onMouseOver={e => hoverInfo(e, { skill: s.skill, constructId: construct.id })}
|
onMouseOver={e => hoverInfo(e, { skill: s.skill, constructId: construct.id })}
|
||||||
onMouseOut={e => hoverInfo(e, null)}
|
onMouseOut={e => hoverInfo(e, null)}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ const addState = connect(
|
|||||||
chatShow,
|
chatShow,
|
||||||
instance,
|
instance,
|
||||||
account,
|
account,
|
||||||
|
tutorial,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
function sendReady() {
|
function sendReady() {
|
||||||
@ -21,6 +22,7 @@ const addState = connect(
|
|||||||
instance,
|
instance,
|
||||||
chatShow,
|
chatShow,
|
||||||
account,
|
account,
|
||||||
|
tutorial,
|
||||||
|
|
||||||
sendReady,
|
sendReady,
|
||||||
};
|
};
|
||||||
@ -42,17 +44,17 @@ function InstanceCtrlBtns(args) {
|
|||||||
instance,
|
instance,
|
||||||
chatShow,
|
chatShow,
|
||||||
account,
|
account,
|
||||||
|
tutorial,
|
||||||
sendReady,
|
sendReady,
|
||||||
setChatShow,
|
setChatShow,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
const finished = instance && instance.phase === 'Finished';
|
const finished = instance && instance.phase === 'Finished';
|
||||||
|
const tutorialDisable = tutorial && tutorial < 8;
|
||||||
return (
|
return (
|
||||||
<div class="instance-ctrl-btns">
|
<div class="instance-ctrl-btns">
|
||||||
<button disabled={!account.subscribed} onClick={() => setChatShow(!chatShow)}>Chat</button>
|
<button disabled={!account.subscribed} onClick={() => setChatShow(!chatShow)}>Chat</button>
|
||||||
<button disabled={finished} class="ready" onClick={() => sendReady()}>Ready</button>
|
<button disabled={finished || tutorialDisable} class="ready" onClick={() => sendReady()}>Ready</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,7 +95,7 @@ function Play(args) {
|
|||||||
type="submit">
|
type="submit">
|
||||||
Invite
|
Invite
|
||||||
</button>
|
</button>
|
||||||
<figcaption>Invite a Friend</figcaption>
|
<figcaption>Play against friend</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
);
|
);
|
||||||
@ -221,13 +221,15 @@ function Play(args) {
|
|||||||
<div>
|
<div>
|
||||||
<h1 class="credits">¤ {account.balance}</h1>
|
<h1 class="credits">¤ {account.balance}</h1>
|
||||||
<div class='list'>
|
<div class='list'>
|
||||||
{subscription}
|
<figure>{subscription}</figure>
|
||||||
<button
|
<figure>
|
||||||
onClick={() => setNav('shop')}
|
<button
|
||||||
class="yellow-btn"
|
onClick={() => setNav('shop')}
|
||||||
role="link">
|
class="yellow-btn"
|
||||||
Get Credits
|
role="link">
|
||||||
</button>
|
Get Credits
|
||||||
|
</button>
|
||||||
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Join our Discord server to find opponents and talk to the devs. <br />
|
Join our Discord server to find opponents and talk to the devs. <br />
|
||||||
|
|||||||
@ -89,6 +89,7 @@ function Reshape(args) {
|
|||||||
return (
|
return (
|
||||||
<section class="top" onClick={() => setMtxActive(null)}>
|
<section class="top" onClick={() => setMtxActive(null)}>
|
||||||
<div class="news">
|
<div class="news">
|
||||||
|
<h1> Customise your Constructs </h1>
|
||||||
<p class="play-p">Use credits to modify your construct names and appearance.</p>
|
<p class="play-p">Use credits to modify your construct names and appearance.</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
@ -106,19 +107,19 @@ function Reshape(args) {
|
|||||||
<div>
|
<div>
|
||||||
<h1 class="credits">¤ {account.balance}</h1>
|
<h1 class="credits">¤ {account.balance}</h1>
|
||||||
<div class='list'>
|
<div class='list'>
|
||||||
{subscription}
|
<figure>{subscription}</figure>
|
||||||
<button
|
<figure>
|
||||||
onClick={() => setNav('shop')}
|
<button
|
||||||
class="yellow-btn"
|
onClick={() => setNav('shop')}
|
||||||
role="link">
|
class="yellow-btn"
|
||||||
Get Credits
|
role="link">
|
||||||
</button>
|
Get Credits
|
||||||
<div id="error-message"></div>
|
</button>
|
||||||
</div>
|
</figure>
|
||||||
<div class='list'>
|
|
||||||
{shop.owned.map(useMtx)}
|
{shop.owned.map(useMtx)}
|
||||||
{shop.available.map(availableMtx)}
|
{shop.available.map(availableMtx)}
|
||||||
</div>
|
</div>
|
||||||
|
<div id="error-message"></div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -27,7 +27,7 @@ function Shop(args) {
|
|||||||
return (
|
return (
|
||||||
<section class="top">
|
<section class="top">
|
||||||
<div class="news">
|
<div class="news">
|
||||||
<h1>Support the game</h1>
|
<h1>Support MNML</h1>
|
||||||
<p>
|
<p>
|
||||||
<b>Credits</b> are in game currency used to change your team appearance:
|
<b>Credits</b> are in game currency used to change your team appearance:
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@ -5,8 +5,8 @@ const { tutorialStage } = require('../tutorial.utils');
|
|||||||
const { genItemInfo } = require('./vbox.utils');
|
const { genItemInfo } = require('./vbox.utils');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
({ info, player, tutorial, vboxInfo, itemInfo, instance, comboPreview }) => ({
|
({ info, player, tutorial, vboxInfo, itemInfo, instance, comboPreview, authenticated }) => ({
|
||||||
info, player, tutorial, vboxInfo, itemInfo, instance, comboPreview,
|
info, player, tutorial, vboxInfo, itemInfo, instance, comboPreview, authenticated
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
@ -35,12 +35,13 @@ class Info extends preact.Component {
|
|||||||
itemInfo,
|
itemInfo,
|
||||||
instance,
|
instance,
|
||||||
comboPreview,
|
comboPreview,
|
||||||
|
authenticated,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
// dispaly priority
|
// dispaly priority
|
||||||
// tutorial -> comboPreview -> vboxInfo -> info
|
// tutorial -> comboPreview -> vboxInfo -> info
|
||||||
if (tutorial) {
|
if (tutorial) {
|
||||||
const tutorialStageInfo = tutorialStage(tutorial, clearTutorial, instance);
|
const tutorialStageInfo = tutorialStage(authenticated, tutorial, clearTutorial, instance);
|
||||||
if (tutorialStageInfo) return tutorialStageInfo;
|
if (tutorialStageInfo) return tutorialStageInfo;
|
||||||
}
|
}
|
||||||
if (comboPreview) return genItemInfo(comboPreview, itemInfo, player);
|
if (comboPreview) return genItemInfo(comboPreview, itemInfo, player);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const buttons = require('./buttons');
|
|||||||
const { removeTier } = require('../utils');
|
const { removeTier } = require('../utils');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
({ itemUnequip, vboxHighlight, vboxSelected }) => ({ itemUnequip, vboxHighlight, vboxSelected }));
|
({ itemUnequip, vboxHighlight, vboxSelected, tutorial }) => ({ itemUnequip, vboxHighlight, vboxSelected, tutorial }));
|
||||||
|
|
||||||
class stashElement extends preact.Component {
|
class stashElement extends preact.Component {
|
||||||
shouldComponentUpdate(newProps) {
|
shouldComponentUpdate(newProps) {
|
||||||
@ -23,6 +23,7 @@ class stashElement extends preact.Component {
|
|||||||
if (newProps.itemUnequip !== this.props.itemUnequip) return true;
|
if (newProps.itemUnequip !== this.props.itemUnequip) return true;
|
||||||
if (newProps.vboxHighlight !== this.props.vboxHighlight) return true;
|
if (newProps.vboxHighlight !== this.props.vboxHighlight) return true;
|
||||||
if (newProps.vboxSelected !== this.props.vboxSelected) return true;
|
if (newProps.vboxSelected !== this.props.vboxSelected) return true;
|
||||||
|
if (newProps.tutorial !== this.props.tutorial) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ class stashElement extends preact.Component {
|
|||||||
itemUnequip,
|
itemUnequip,
|
||||||
vboxHighlight,
|
vboxHighlight,
|
||||||
vboxSelected,
|
vboxSelected,
|
||||||
|
tutorial,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const { storeSelect, stashSelect } = vboxSelected;
|
const { storeSelect, stashSelect } = vboxSelected;
|
||||||
@ -95,7 +97,7 @@ class stashElement extends preact.Component {
|
|||||||
: `${border} ${notValidCombo ? 'fade' : ''}`;
|
: `${border} ${notValidCombo ? 'fade' : ''}`;
|
||||||
|
|
||||||
const invObject = shapes[v] ? shapes[v]() : v;
|
const invObject = shapes[v] ? shapes[v]() : v;
|
||||||
|
const tutorialDisable = tutorial === 1;
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
key={i}
|
key={i}
|
||||||
@ -108,7 +110,9 @@ class stashElement extends preact.Component {
|
|||||||
class={classes}
|
class={classes}
|
||||||
onMouseOver={e => vboxHover(e, v)}
|
onMouseOver={e => vboxHover(e, v)}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
onMouseDown={e => onClick('click', e)}>
|
onMouseDown={e => onClick('click', e)}
|
||||||
|
disabled={tutorialDisable}
|
||||||
|
>
|
||||||
{invObject}
|
{invObject}
|
||||||
</button>
|
</button>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@ -77,21 +77,24 @@ function registerEvents(store) {
|
|||||||
|
|
||||||
if (game && currentGame) {
|
if (game && currentGame) {
|
||||||
if (game.resolutions.length !== currentGame.resolutions.length) {
|
if (game.resolutions.length !== currentGame.resolutions.length) {
|
||||||
|
// stop fetching the game state til animations are done
|
||||||
store.dispatch(actions.setAnimating(true));
|
store.dispatch(actions.setAnimating(true));
|
||||||
store.dispatch(actions.setGameSkillInfo(null));
|
store.dispatch(actions.setGameSkillInfo(null));
|
||||||
// stop fetching the game state til animations are done
|
|
||||||
const newRes = game.resolutions[game.resolutions.length - 1];
|
const newTurns = game.resolutions.slice(currentGame.resolutions.length);
|
||||||
return eachSeries(newRes, (r, cb) => {
|
return eachSeries(newTurns, (turn, turnCb) => {
|
||||||
if (r.delay === 0) return cb(); // TargetKo etc
|
return eachSeries(turn, (r, cb) => {
|
||||||
setAnimations(r, store);
|
if (r.delay === 0) return cb(); // TargetKo etc
|
||||||
return setTimeout(cb, r.delay);
|
setAnimations(r, store);
|
||||||
|
return setTimeout(cb, r.delay);
|
||||||
|
}, turnCb);
|
||||||
}, err => {
|
}, err => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
clearAnimations(store);
|
clearAnimations(store);
|
||||||
// set the game state so resolutions don't fire twice
|
// set the game state so resolutions don't fire twice
|
||||||
store.dispatch(actions.setGame(game));
|
store.dispatch(actions.setGame(game));
|
||||||
ws.sendGameState(game.id);
|
ws.sendGameState(game.id);
|
||||||
return true;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +116,6 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch(actions.setAccount(account));
|
store.dispatch(actions.setAccount(account));
|
||||||
store.dispatch(actions.setTutorial(null));
|
|
||||||
store.dispatch(actions.setAuthenticated(true));
|
store.dispatch(actions.setAuthenticated(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +180,7 @@ function registerEvents(store) {
|
|||||||
setPvp(false);
|
setPvp(false);
|
||||||
const player = v.players.find(p => p.id === account.id);
|
const player = v.players.find(p => p.id === account.id);
|
||||||
store.dispatch(actions.setPlayer(player));
|
store.dispatch(actions.setPlayer(player));
|
||||||
|
|
||||||
if (tutorial) tutorialVbox(player, store, tutorial);
|
if (tutorial) tutorialVbox(player, store, tutorial);
|
||||||
|
|
||||||
if (v.phase === 'Finished') {
|
if (v.phase === 'Finished') {
|
||||||
@ -186,7 +188,6 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return store.dispatch(actions.setInstance(v));
|
return store.dispatch(actions.setInstance(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -106,7 +106,7 @@ function tutorialVbox(player, store, tutorial) {
|
|||||||
store.dispatch(actions.setTutorial(stage));
|
store.dispatch(actions.setTutorial(stage));
|
||||||
}
|
}
|
||||||
|
|
||||||
function tutorialStage(tutorial, clearTutorial, instance) {
|
function tutorialStage(authenticated, tutorial, clearTutorial, instance) {
|
||||||
if (!(instance.time_control === 'Practice' && instance.rounds.length === 1)) return false;
|
if (!(instance.time_control === 'Practice' && instance.rounds.length === 1)) return false;
|
||||||
|
|
||||||
const exit = () => clearTutorial();
|
const exit = () => clearTutorial();
|
||||||
@ -116,10 +116,9 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h1>Welcome to MNML</h1>
|
<h1>Welcome to MNML</h1>
|
||||||
<p> This is the <b>VBOX Phase</b> tutorial.</p>
|
<p> This is the <b>VBOX Phase</b> where you customise your team. </p>
|
||||||
<p> In the <b>VBOX Phase</b> you customise your constructs' skills and specialisations. </p>
|
|
||||||
<p> Colours are used to create powerful combinations with base items. </p>
|
|
||||||
<p> Buy the two colours from the store to continue. </p>
|
<p> Buy the two colours from the store to continue. </p>
|
||||||
|
<p> <b>PRO TIP:</b> While selecting an item in the shop, click the stash to buy it. </p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -128,8 +127,9 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Combining Items</h2>
|
<h2>Combining Items</h2>
|
||||||
<p> You start the game with the base <b>Attack</b> skill item. </p>
|
<p> You start the game with the <b>Attack</b> base skill item. </p>
|
||||||
<p> Highlight the <b>Attack</b> and the two <b> colours</b> then click <b> combine</b> </p>
|
<p> Create powerful combinations by combining colours with base items. </p>
|
||||||
|
<p> Select <b>all three items</b> to <b> combine</b>. </p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -141,8 +141,7 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
<h2>Equipping Items</h2>
|
<h2>Equipping Items</h2>
|
||||||
<p> The first construct on your team is <b>{constructOne}</b>. </p>
|
<p> The first construct on your team is <b>{constructOne}</b>. </p>
|
||||||
<p> Skill items can be equipped to your constructs to be used in the combat phase. </p>
|
<p> Skill items can be equipped to your constructs to be used in the combat phase. </p>
|
||||||
<p> Click your new skill from the stash. <br />
|
<p> Select your new skill from the stash and then click the flashing <b>SKILL</b> slot or the construct image to equip. </p>
|
||||||
Once selected click the flashing <b>SKILL</b> slot or the construct img to equip the skill. </p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -162,11 +161,10 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Specialisations</h2>
|
<h2>Specialisations</h2>
|
||||||
<p> Equipping specialisation items will increase the stats of your constructs.</p>
|
<p> Specialisation items increase the stats of your constructs. <br/ >
|
||||||
<p> These can also be combined with colours for further specialisation. </p>
|
They can be combined further with colours to optimise your team strategy.</p>
|
||||||
<p> Click the specialisation item in the stash.<br />
|
<p> Slect the item in the stash, once selected click the flashing <b>SPEC</b> slot to equip. </p>
|
||||||
Once selected click the flashing <b>SPEC</b> slot to equip the specialisation. </p>
|
<p> <b>PRO TIP:</b> While selecting an item in the shop, click on your construct to buy and equip in one step. </p>
|
||||||
<p> <b>PRO TIP:</b> while selecting an item in the shop, click on your construct to buy and equip in one step. </p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -178,8 +176,7 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Skills</h2>
|
<h2>Skills</h2>
|
||||||
<p> You have now created a construct with an upgraded skill and base spec. </p>
|
<p> You have now created a construct with an upgraded skill and base spec. </p>
|
||||||
<p> The goal is to create three powerful constructs for combat. </p>
|
<p> Equip your other constructs <b>{constructTwo}</b> and <b>{constructThree}</b> with skills. <br />
|
||||||
<p> Equip your other constructs <b>{constructTwo}</b> and <b>{constructThree}</b> with the Attack skill. <br />
|
|
||||||
Ensure each construct has a single skill to continue. </p>
|
Ensure each construct has a single skill to continue. </p>
|
||||||
<p> <b>PRO TIP:</b> Select a skill or spec on a construct and click another construct to swap it. </p>
|
<p> <b>PRO TIP:</b> Select a skill or spec on a construct and click another construct to swap it. </p>
|
||||||
</div>
|
</div>
|
||||||
@ -203,7 +200,6 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
if (window.innerWidth < 1000) {
|
if (window.innerWidth < 1000) {
|
||||||
return exit();
|
return exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>GLHF</h2>
|
<h2>GLHF</h2>
|
||||||
@ -213,6 +209,7 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -223,11 +220,18 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
onMouseDown={exit}> Continue </button>
|
onMouseDown={exit}> Continue </button>
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
const skipTutorial = authenticated && !exitTutorial ?
|
||||||
|
<button
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
onMouseDown={exit}> Skip Tutorial </button>
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='tutorial'>
|
<div class='tutorial'>
|
||||||
{tutorialText()}
|
{tutorialText()}
|
||||||
<figure>
|
<figure>
|
||||||
{exitTutorial}
|
{exitTutorial}
|
||||||
|
{skipTutorial}
|
||||||
</figure>
|
</figure>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mnml_core"
|
name = "mnml_core"
|
||||||
version = "1.12.1"
|
version = "1.12.2"
|
||||||
authors = ["ntr <ntr@smokestack.io>", "mashy <mashy@mnml.gg>"]
|
authors = ["ntr <ntr@smokestack.io>", "mashy <mashy@mnml.gg>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -470,24 +470,26 @@ impl Construct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn increase_cooldowns(&mut self, turns: usize) -> Vec<Event> {
|
pub fn increase_cooldowns(&mut self, turns: usize) -> Vec<Event> {
|
||||||
let mut events = vec![];
|
let mut cd_event = false;
|
||||||
|
|
||||||
for skill in self.skills.iter_mut() {
|
for skill in self.skills.iter_mut() {
|
||||||
if skill.skill.base_cd().is_some() { // if has a cooldown
|
if skill.skill.base_cd().is_some() { // if has a cooldown
|
||||||
|
cd_event = true;
|
||||||
match skill.cd {
|
match skill.cd {
|
||||||
Some(cd) => {
|
Some(cd) => {
|
||||||
skill.cd = Some(cd.saturating_add(turns));
|
skill.cd = Some(cd.saturating_add(turns));
|
||||||
events.push(Event::CooldownIncrease { construct: self.id, turns })
|
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
skill.cd = Some(turns);
|
skill.cd = Some(turns);
|
||||||
events.push(Event::CooldownIncrease { construct: self.id, turns })
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return events;
|
if cd_event {
|
||||||
|
return vec![Event::CooldownIncrease { construct: self.id, turns }];
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec![];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reduce_cooldowns(&mut self) -> &mut Construct {
|
pub fn reduce_cooldowns(&mut self) -> &mut Construct {
|
||||||
@ -909,7 +911,7 @@ impl Construct {
|
|||||||
construct: self.id,
|
construct: self.id,
|
||||||
amount: healing,
|
amount: healing,
|
||||||
overhealing,
|
overhealing,
|
||||||
colour: Colour::Red,
|
colour: Colour::Blue,
|
||||||
display: EventConstruct::new(self),
|
display: EventConstruct::new(self),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -931,7 +933,7 @@ impl Construct {
|
|||||||
construct: self.id,
|
construct: self.id,
|
||||||
amount: blue_damage_amount,
|
amount: blue_damage_amount,
|
||||||
mitigation: blue_mitigation,
|
mitigation: blue_mitigation,
|
||||||
colour: Colour::Red,
|
colour: Colour::Blue,
|
||||||
display: EventConstruct::new(self),
|
display: EventConstruct::new(self),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2082,7 +2082,7 @@ impl Purify {
|
|||||||
|
|
||||||
fn purify(cast: Cast, game: &mut Game, values: Purify) {
|
fn purify(cast: Cast, game: &mut Game, values: Purify) {
|
||||||
let gp = game.value(Value::Stat { construct: cast.source, stat: Stat::GreenPower });
|
let gp = game.value(Value::Stat { construct: cast.source, stat: Stat::GreenPower });
|
||||||
let rms = game.value(Value::Removals { construct: cast.target });
|
let rms = game.value(Value::Effects { construct: cast.target });
|
||||||
let amount = gp.pct(values.green_heal_base().saturating_mul(rms));
|
let amount = gp.pct(values.green_heal_base().saturating_mul(rms));
|
||||||
|
|
||||||
game.action(cast,
|
game.action(cast,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-ops",
|
"name": "mnml-ops",
|
||||||
"version": "1.12.1",
|
"version": "1.12.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mnml"
|
name = "mnml"
|
||||||
version = "1.12.1"
|
version = "1.12.2"
|
||||||
authors = ["ntr <ntr@smokestack.io>"]
|
authors = ["ntr <ntr@smokestack.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -530,7 +530,7 @@ pub fn img_check(account: &Account) -> Result<Uuid, Error> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tutorial(tx: &mut Transaction, account: &Account) -> Result<Option<Instance>, Error> {
|
pub fn _tutorial(tx: &mut Transaction, account: &Account) -> Result<Option<Instance>, Error> {
|
||||||
let query = "
|
let query = "
|
||||||
SELECT count(id)
|
SELECT count(id)
|
||||||
FROM players
|
FROM players
|
||||||
|
|||||||
@ -25,7 +25,7 @@ use payments::{stripe};
|
|||||||
|
|
||||||
pub const TOKEN_HEADER: &str = "x-auth-token";
|
pub const TOKEN_HEADER: &str = "x-auth-token";
|
||||||
pub const AUTH_CLEAR: &str =
|
pub const AUTH_CLEAR: &str =
|
||||||
"x-auth-token=; HttpOnly; SameSite=Strict; Path=/; Max-Age=-1;";
|
"x-auth-token=; HttpOnly; SameSite=None; Path=/; Max-Age=-1;";
|
||||||
|
|
||||||
#[derive(Clone, Copy, Fail, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Fail, Debug, Serialize, Deserialize)]
|
||||||
pub enum MnmlHttpError {
|
pub enum MnmlHttpError {
|
||||||
@ -191,7 +191,7 @@ impl AfterMiddleware for ErrorHandler {
|
|||||||
fn token_res(token: String) -> Response {
|
fn token_res(token: String) -> Response {
|
||||||
let v = Cookie::build(TOKEN_HEADER, token)
|
let v = Cookie::build(TOKEN_HEADER, token)
|
||||||
.http_only(true)
|
.http_only(true)
|
||||||
.same_site(SameSite::Strict)
|
.same_site(SameSite::None)
|
||||||
.path("/")
|
.path("/")
|
||||||
.max_age(Duration::weeks(1)) // 1 week aligns with db set
|
.max_age(Duration::weeks(1)) // 1 week aligns with db set
|
||||||
.finish();
|
.finish();
|
||||||
@ -354,7 +354,7 @@ fn recover(req: &mut Request) -> IronResult<Response> {
|
|||||||
|
|
||||||
let v = Cookie::build(TOKEN_HEADER, token)
|
let v = Cookie::build(TOKEN_HEADER, token)
|
||||||
.http_only(true)
|
.http_only(true)
|
||||||
.same_site(SameSite::Strict)
|
.same_site(SameSite::None)
|
||||||
.path("/")
|
.path("/")
|
||||||
.max_age(Duration::weeks(1)) // 1 week aligns with db set
|
.max_age(Duration::weeks(1)) // 1 week aligns with db set
|
||||||
.finish();
|
.finish();
|
||||||
|
|||||||
@ -232,6 +232,12 @@ pub fn set(tx: &mut Transaction, account: Uuid, email: &String) -> Result<(Uuid,
|
|||||||
RETURNING id;
|
RETURNING id;
|
||||||
";
|
";
|
||||||
|
|
||||||
|
let select_query = "
|
||||||
|
SELECT *
|
||||||
|
FROM emails
|
||||||
|
WHERE account = $1;
|
||||||
|
";
|
||||||
|
|
||||||
let update_query = "
|
let update_query = "
|
||||||
UPDATE emails
|
UPDATE emails
|
||||||
SET email = $1, confirm_token = $2, confirmed = false, recover_token = $3
|
SET email = $1, confirm_token = $2, confirmed = false, recover_token = $3
|
||||||
@ -239,18 +245,11 @@ pub fn set(tx: &mut Transaction, account: Uuid, email: &String) -> Result<(Uuid,
|
|||||||
RETURNING id;
|
RETURNING id;
|
||||||
";
|
";
|
||||||
|
|
||||||
let result = match tx.query(insert_query, &[&id, &account, &email, &confirm_token, &recover_token]) {
|
let existing = tx.query(select_query, &[&id])?;
|
||||||
Ok(r) => r,
|
|
||||||
// email update probably
|
let result = match existing.iter().next() {
|
||||||
Err(_) => {
|
Some(_) => tx.query(insert_query, &[&id, &account, &email, &confirm_token, &recover_token])?,
|
||||||
match tx.query(update_query, &[&email, &confirm_token, &recover_token, &account]) {
|
None => tx.query(update_query, &[&email, &confirm_token, &recover_token, &account])?,
|
||||||
Ok(r) => r,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("{:?}", e);
|
|
||||||
return Err(err_msg("no email set"));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match result.iter().next() {
|
match result.iter().next() {
|
||||||
|
|||||||
@ -128,6 +128,7 @@ pub enum RpcRequest {
|
|||||||
pub trait User {
|
pub trait User {
|
||||||
fn receive(&mut self, data: Vec<u8>, stripe: &StripeClient) -> Result<RpcMessage, Error>;
|
fn receive(&mut self, data: Vec<u8>, stripe: &StripeClient) -> Result<RpcMessage, Error>;
|
||||||
fn connected(&mut self) -> Result<(), Error>;
|
fn connected(&mut self) -> Result<(), Error>;
|
||||||
|
fn disconnected(&self) -> Result<(), Error>;
|
||||||
fn send(&mut self, msg: RpcMessage) -> Result<(), Error>;
|
fn send(&mut self, msg: RpcMessage) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,8 +171,8 @@ impl Handler for Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_close(&mut self, _: CloseCode, _: &str) {
|
fn on_close(&mut self, _: CloseCode, _: &str) {
|
||||||
info!("websocket disconnected id={:?}", self.id);
|
|
||||||
self.events.send(Event::Disconnect(self.id)).unwrap();
|
self.events.send(Event::Disconnect(self.id)).unwrap();
|
||||||
|
self.user.disconnected().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_request(&mut self, req: &Request) -> ws::Result<Response> {
|
fn on_request(&mut self, req: &Request) -> ws::Result<Response> {
|
||||||
@ -198,7 +199,10 @@ impl Handler for Connection {
|
|||||||
if cookie.name() == TOKEN_HEADER {
|
if cookie.name() == TOKEN_HEADER {
|
||||||
let db = self.pool.get().unwrap();
|
let db = self.pool.get().unwrap();
|
||||||
match account::from_token(&db, &cookie.value().to_string()) {
|
match account::from_token(&db, &cookie.value().to_string()) {
|
||||||
Ok(a) => self.user = Box::new(Authenticated::new(a, self.ws.clone(), self.events.clone(), self.pool.clone())),
|
Ok(a) => {
|
||||||
|
self.id = a.id;
|
||||||
|
self.user = Box::new(Authenticated::new(a, self.ws.clone(), self.events.clone(), self.pool.clone()));
|
||||||
|
},
|
||||||
Err(_) => return unauth(),
|
Err(_) => return unauth(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,6 +74,10 @@ impl User for Anonymous {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn disconnected(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn receive(&mut self, data: Vec<u8>, _stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
fn receive(&mut self, data: Vec<u8>, _stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||||
match from_slice::<RpcRequest>(&data) {
|
match from_slice::<RpcRequest>(&data) {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
|
|||||||
@ -128,9 +128,9 @@ impl User for Authenticated {
|
|||||||
let wheel = account::chat_wheel(&db, a.id)?;
|
let wheel = account::chat_wheel(&db, a.id)?;
|
||||||
self.ws.send(RpcMessage::ChatWheel(wheel))?;
|
self.ws.send(RpcMessage::ChatWheel(wheel))?;
|
||||||
|
|
||||||
if let Some(instance) = account::tutorial(&mut tx, &a)? {
|
// if let Some(instance) = account::tutorial(&mut tx, &a)? {
|
||||||
self.ws.send(RpcMessage::InstanceState(instance))?;
|
// self.ws.send(RpcMessage::InstanceState(instance))?;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// tx should do nothing
|
// tx should do nothing
|
||||||
tx.commit()?;
|
tx.commit()?;
|
||||||
@ -138,6 +138,11 @@ impl User for Authenticated {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn disconnected(&self) -> Result<(), Error> {
|
||||||
|
info!("user disconnected account={:?}", self.account);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn receive(&mut self, data: Vec<u8>, stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
fn receive(&mut self, data: Vec<u8>, stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
||||||
// cast the msg to this type to receive method name
|
// cast the msg to this type to receive method name
|
||||||
let begin = Instant::now();
|
let begin = Instant::now();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-studios",
|
"name": "mnml-studios",
|
||||||
"version": "1.12.1",
|
"version": "1.12.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user