Merge branch 'release/1.8.3'
This commit is contained in:
commit
ef790b2f73
27
CHANGELOG.md
27
CHANGELOG.md
@ -1,4 +1,29 @@
|
|||||||
## [1.8.1] - 2019-11-07
|
## [1.8.3] - 2019-11-10
|
||||||
|
### Added
|
||||||
|
- Preview combos by hovering over recipes
|
||||||
|
- Condensed recipe display
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Construct display on info / demo page
|
||||||
|
- Case where a skill could send multiple ko events to target
|
||||||
|
- Resizing of vbox when you buy / create certain items
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Automatically shows a preview of combo item when you have 3 items selected for combining
|
||||||
|
- Only highlight the first available item slot when equipping
|
||||||
|
- Amplify no longer increase GreenPower
|
||||||
|
- Purify
|
||||||
|
- Now removes all effects on target
|
||||||
|
- Applies "Pure" increasing healing taken
|
||||||
|
- Purge
|
||||||
|
- Now removes all effects on target
|
||||||
|
|
||||||
|
|
||||||
|
## [1.8.2] - 2019-11-10
|
||||||
|
### Fixed
|
||||||
|
- Duplicate button issue in reshape tab
|
||||||
|
|
||||||
|
## [1.8.1] - 2019-11-09
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- An issue where skills would not be put on cooldown after being used.
|
- An issue where skills would not be put on cooldown after being used.
|
||||||
|
|||||||
@ -6,9 +6,15 @@
|
|||||||
* can't reset password without knowing password =\
|
* can't reset password without knowing password =\
|
||||||
* ws gzip encoding
|
* ws gzip encoding
|
||||||
|
|
||||||
* mobile info page
|
* Graphics
|
||||||
|
* Img
|
||||||
|
* Skill Icons
|
||||||
|
* Buttons / General UI Theming
|
||||||
|
* Front Page
|
||||||
|
|
||||||
## SOON
|
## SOON
|
||||||
|
* Graphical status effects instead of text
|
||||||
|
* Improve colour contrast / buttons
|
||||||
|
|
||||||
* supporter gold name in instance (anyone whos put any money into game)
|
* supporter gold name in instance (anyone whos put any money into game)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.8.1",
|
"version": "1.8.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ npm i
|
|||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
cp tos.html dist/
|
cp tos.html dist/
|
||||||
|
cp changelog.html dist/
|
||||||
|
|
||||||
# echo "Building acp version $VERSION"
|
# echo "Building acp version $VERSION"
|
||||||
# cd $MNML_PATH/acp
|
# cd $MNML_PATH/acp
|
||||||
|
|||||||
@ -2457,9 +2457,9 @@
|
|||||||
borderopacity="1.0"
|
borderopacity="1.0"
|
||||||
inkscape:pageopacity="1"
|
inkscape:pageopacity="1"
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:zoom="0.53357639"
|
inkscape:zoom="0.53546627"
|
||||||
inkscape:cx="411.32817"
|
inkscape:cx="561.25984"
|
||||||
inkscape:cy="1018.5983"
|
inkscape:cy="793.70079"
|
||||||
inkscape:document-units="mm"
|
inkscape:document-units="mm"
|
||||||
inkscape:current-layer="layer1"
|
inkscape:current-layer="layer1"
|
||||||
showgrid="true"
|
showgrid="true"
|
||||||
@ -2539,8 +2539,8 @@
|
|||||||
transform="translate(-472.60042,755.1467)"
|
transform="translate(-472.60042,755.1467)"
|
||||||
style="display:inline">
|
style="display:inline">
|
||||||
<rect
|
<rect
|
||||||
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.01528859;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:20.98234558;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
id="rect5015"
|
id="rect5144"
|
||||||
width="297"
|
width="297"
|
||||||
height="420"
|
height="420"
|
||||||
x="472.60043"
|
x="472.60043"
|
||||||
@ -2548,7 +2548,7 @@
|
|||||||
<g
|
<g
|
||||||
id="g4946"
|
id="g4946"
|
||||||
style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
|
style="stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
transform="translate(0,24.99999)">
|
transform="translate(0,2.7646743)">
|
||||||
<path
|
<path
|
||||||
inkscape:connector-curvature="0"
|
inkscape:connector-curvature="0"
|
||||||
id="path4913"
|
id="path4913"
|
||||||
@ -2566,28 +2566,69 @@
|
|||||||
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
</g>
|
</g>
|
||||||
<g
|
<g
|
||||||
id="g5001"
|
id="g5142"
|
||||||
transform="translate(25)">
|
transform="translate(0,-47.235375)">
|
||||||
|
<g
|
||||||
|
transform="translate(25)"
|
||||||
|
id="g5001">
|
||||||
<path
|
<path
|
||||||
inkscape:connector-curvature="0"
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
id="path4948"
|
|
||||||
d="m 522.60042,-435.14668 v -75.00001 h 50 v 75.00001 h -50"
|
d="m 522.60042,-435.14668 v -75.00001 h 50 v 75.00001 h -50"
|
||||||
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
id="path4948"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
<path
|
<path
|
||||||
inkscape:connector-curvature="0"
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:2.9685142;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
id="path4978"
|
|
||||||
d="m 532.60042,-500.14669 h 30 v 55 h -30 z"
|
d="m 532.60042,-500.14669 h 30 v 55 h -30 z"
|
||||||
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:2.9685142;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
id="path4978"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
<path
|
<path
|
||||||
inkscape:connector-curvature="0"
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:2.9685142;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
id="path4988"
|
|
||||||
d="m 542.60042,-490.1467 h 10 v 35 h -10 v -35"
|
d="m 542.60042,-490.1467 h 10 v 35 h -10 v -35"
|
||||||
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:2.9685142;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
id="path4988"
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:2.9685142;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
d="m 697.60042,-460.14669 -25,25.00001 -25,-25.00001 25,25.00001 v -75.00001 h -25"
|
|
||||||
id="path5003"
|
|
||||||
inkscape:connector-curvature="0" />
|
inkscape:connector-curvature="0" />
|
||||||
</g>
|
</g>
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5003"
|
||||||
|
d="m 697.60042,-460.14669 -25,25.00001 -25,-25.00001 25,25.00001 v -75.00001 h -25"
|
||||||
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:2.9685142;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g5123"
|
||||||
|
transform="matrix(0.23529412,0,0,0.23529412,411.40033,-377.05346)"
|
||||||
|
style="stroke:#f5f5f5;stroke-width:12.75;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5068"
|
||||||
|
d="m 472.60042,-185.14671 v -49.99998 h 100 v 25 h -100 l 100,24.99998"
|
||||||
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:12.75;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5075"
|
||||||
|
d="m 622.60042,-185.14671 v -49.99998 h 100 v 49.99998 z"
|
||||||
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:12.75;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5082"
|
||||||
|
d="m 772.60042,-235.14669 h 99.99999 -50.00001 l 2e-5,50"
|
||||||
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:12.75;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5096"
|
||||||
|
d="m 922.60041,-185.14671 v 0 -49.99998 h 99.99999 v 49.99998 -24.99998 h -99.99999"
|
||||||
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:12.75;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5103"
|
||||||
|
d="m 1072.6004,-235.14669 h 100 -50 v 49.99998"
|
||||||
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:12.75;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5110"
|
||||||
|
d="m 1322.6004,-185.14669 -100,-2e-5 v -24.99998 h 75 -75 v -25 h 100"
|
||||||
|
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#f5f5f5;stroke-width:12.75;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 99 KiB |
@ -122,6 +122,15 @@ svg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes border-co {
|
||||||
|
0% {
|
||||||
|
border-color: @gray-box;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
border-color: @gray-hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes co {
|
@keyframes co {
|
||||||
from {
|
from {
|
||||||
background: @black;
|
background: @black;
|
||||||
|
|||||||
@ -94,7 +94,7 @@
|
|||||||
justify-items: center;
|
justify-items: center;
|
||||||
|
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: minmax(min-content, 1fr) min-content;
|
grid-template-rows: min-content 1fr;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"left"
|
"left"
|
||||||
"right";
|
"right";
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
@media (max-width: 1920px) {
|
@media (max-width: 1920px) {
|
||||||
.instance .info table td svg {
|
.instance .info table td svg {
|
||||||
height: 50%;
|
// height: 50%;
|
||||||
stroke-width: 8px;
|
stroke-width: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,15 +33,57 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.instance .info {
|
.instance .info {
|
||||||
/*font-size: 75%;*/
|
|
||||||
margin: 0 0 0 1em;
|
margin: 0 0 0 1em;
|
||||||
grid-area: info;
|
grid-area: info;
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
// white-space: pre-wrap;
|
|
||||||
|
|
||||||
> *:first-child {
|
display: grid;
|
||||||
margin-bottom: 1em;
|
grid-template-rows: 13em min-content;
|
||||||
|
grid-template-areas:
|
||||||
|
"item"
|
||||||
|
"combos";
|
||||||
|
|
||||||
|
.combos {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(6, 1fr);
|
||||||
|
align-content: center;
|
||||||
|
|
||||||
|
.table-button {
|
||||||
|
display: grid;
|
||||||
|
text-align: center;
|
||||||
|
align-content: center;
|
||||||
|
border-bottom: 2px solid #222;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
"item"
|
||||||
|
"ingr";
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: whitesmoke;
|
||||||
|
background-color: @gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
border-top: 2px solid #222;
|
||||||
|
border-bottom: 2px solid #222;
|
||||||
|
flex: 1;
|
||||||
|
grid-area: item;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
border-right: 2px solid #222;
|
||||||
|
svg {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
div {
|
||||||
|
border-left: 2px solid #222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +434,10 @@
|
|||||||
&.winner {
|
&.winner {
|
||||||
animation: win 2s ease-in-out 0s 1;
|
animation: win 2s ease-in-out 0s 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cancelled {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tutorial {
|
.tutorial {
|
||||||
|
|||||||
@ -122,6 +122,10 @@ section {
|
|||||||
// height: 3em;
|
// height: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.sub {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
&.play {
|
&.play {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|||||||
2
client/assets/styles/skeleton.css
vendored
2
client/assets/styles/skeleton.css
vendored
@ -269,7 +269,7 @@ textarea:focus,
|
|||||||
select:focus {
|
select:focus {
|
||||||
border: 1px solid #33C3F0;
|
border: 1px solid #33C3F0;
|
||||||
outline: 0; }
|
outline: 0; }
|
||||||
label,
|
|
||||||
legend {
|
legend {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: .5rem;
|
margin-bottom: .5rem;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
.vbox {
|
.vbox {
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
|
line-height: 0;
|
||||||
.vbox-hdr {
|
.vbox-hdr {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
@ -53,7 +53,7 @@
|
|||||||
&, &:hover, &:active {
|
&, &:hover, &:active {
|
||||||
background: @red;
|
background: @red;
|
||||||
color: black;
|
color: black;
|
||||||
border: 1px solid black;
|
border: 2px solid black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
svg {
|
svg {
|
||||||
|
|||||||
1211
client/changelog.html
Normal file
1211
client/changelog.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.8.1",
|
"version": "1.8.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
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 setAnimating = value => ({ type: 'SET_ANIMATING', value });
|
export const setAnimating = value => ({ type: 'SET_ANIMATING', value });
|
||||||
export const setAnimCb = value => ({ type: 'SET_ANIM_CB', value });
|
export const setAnimCb = value => ({ type: 'SET_ANIM_CB', value });
|
||||||
@ -40,9 +39,9 @@ export const setPing = value => ({ type: 'SET_PING', value });
|
|||||||
export const setPlayer = value => ({ type: 'SET_PLAYER', value });
|
export const setPlayer = value => ({ type: 'SET_PLAYER', value });
|
||||||
export const setReclaiming = value => ({ type: 'SET_RECLAIMING', value });
|
export const setReclaiming = value => ({ type: 'SET_RECLAIMING', value });
|
||||||
export const setShowLog = value => ({ type: 'SET_SHOW_LOG', value });
|
export const setShowLog = value => ({ type: 'SET_SHOW_LOG', value });
|
||||||
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 setSubscription = value => ({ type: 'SET_SUBSCRIPTION', value });
|
export const setSubscription = value => ({ type: 'SET_SUBSCRIPTION', value });
|
||||||
|
export const setPvp = value => ({ type: 'SET_PVP', value });
|
||||||
|
|
||||||
export const setTeam = value => ({ type: 'SET_TEAM', value: Array.from(value) });
|
export const setTeam = value => ({ type: 'SET_TEAM', value: Array.from(value) });
|
||||||
export const setTeamPage = value => ({ type: 'SET_TEAM_PAGE', value });
|
export const setTeamPage = value => ({ type: 'SET_TEAM_PAGE', value });
|
||||||
|
|||||||
@ -78,7 +78,6 @@ function createSocket(store) {
|
|||||||
store.dispatch(actions.setAnimText(null));
|
store.dispatch(actions.setAnimText(null));
|
||||||
store.dispatch(actions.setAnimating(false));
|
store.dispatch(actions.setAnimating(false));
|
||||||
store.dispatch(actions.setGameEffectInfo(null));
|
store.dispatch(actions.setGameEffectInfo(null));
|
||||||
store.dispatch(actions.setSkip(false));
|
|
||||||
|
|
||||||
// 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));
|
||||||
|
|||||||
@ -168,6 +168,9 @@ function getText(resolution) {
|
|||||||
|
|
||||||
if (type === 'Removal') {
|
if (type === 'Removal') {
|
||||||
const { effect, construct_effects: effects } = event;
|
const { effect, construct_effects: effects } = event;
|
||||||
|
if (!effect) {
|
||||||
|
return { text: 'Effect Removal', css: '', effects };
|
||||||
|
}
|
||||||
return { text: `-${effect}`, css: '', effects };
|
return { text: `-${effect}`, css: '', effects };
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -36,7 +36,6 @@ const addState = connect(
|
|||||||
dispatch(actions.setCombiner([]));
|
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.setInfo(null));
|
dispatch(actions.setInfo(null));
|
||||||
dispatch(actions.setItemEquip(null));
|
dispatch(actions.setItemEquip(null));
|
||||||
dispatch(actions.setItemUnequip([]));
|
dispatch(actions.setItemUnequip([]));
|
||||||
|
|||||||
@ -20,6 +20,7 @@ function projectile(x, y, radius, colour) {
|
|||||||
cx={x}
|
cx={x}
|
||||||
cy={y}
|
cy={y}
|
||||||
r={radius}
|
r={radius}
|
||||||
|
stroke="none"
|
||||||
fill={colour}
|
fill={colour}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -80,6 +80,12 @@ class Faceoff extends preact.Component {
|
|||||||
}
|
}
|
||||||
function faceoffText() {
|
function faceoffText() {
|
||||||
if (!instance.winner) {
|
if (!instance.winner) {
|
||||||
|
if (instance.phase === 'Finished') return (
|
||||||
|
<div class="faceoff-text">
|
||||||
|
<div class="cancelled"> game cancelled </div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="faceoff-text">
|
<div class="faceoff-text">
|
||||||
<div class="opponent-text"> {otherTeam.name} </div>
|
<div class="opponent-text"> {otherTeam.name} </div>
|
||||||
|
|||||||
@ -148,7 +148,7 @@ class GameConstruct extends Component {
|
|||||||
return (
|
return (
|
||||||
<div class="skill-description">
|
<div class="skill-description">
|
||||||
<h2><span> {gameSkillInfo.skill} </span></h2>
|
<h2><span> {gameSkillInfo.skill} </span></h2>
|
||||||
<span>{infoDescription} </span>
|
<span>{infoDescription} </span> <br />
|
||||||
{speed}
|
{speed}
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,6 @@ const addState = connect(
|
|||||||
account,
|
account,
|
||||||
animating,
|
animating,
|
||||||
activeSkill,
|
activeSkill,
|
||||||
activeConstruct,
|
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
function selectSkillTarget(targetConstructId) {
|
function selectSkillTarget(targetConstructId) {
|
||||||
@ -34,7 +33,6 @@ const addState = connect(
|
|||||||
account,
|
account,
|
||||||
animating,
|
animating,
|
||||||
activeSkill,
|
activeSkill,
|
||||||
activeConstruct,
|
|
||||||
selectSkillTarget,
|
selectSkillTarget,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -44,11 +42,7 @@ const addState = connect(
|
|||||||
dispatch(actions.setActiveSkill(constructId, skill));
|
dispatch(actions.setActiveSkill(constructId, skill));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setActiveConstruct(construct) {
|
return { setActiveSkill };
|
||||||
dispatch(actions.setActiveConstruct(construct));
|
|
||||||
}
|
|
||||||
|
|
||||||
return { setActiveSkill, setActiveConstruct };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
@ -59,7 +53,6 @@ function Game(props) {
|
|||||||
account,
|
account,
|
||||||
animating,
|
animating,
|
||||||
setActiveSkill,
|
setActiveSkill,
|
||||||
setActiveConstruct,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (!game) return <div>...</div>;
|
if (!game) return <div>...</div>;
|
||||||
@ -91,7 +84,6 @@ function Game(props) {
|
|||||||
|
|
||||||
function gameClick(e) {
|
function gameClick(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setActiveConstruct(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -35,7 +35,6 @@ const addState = connect(
|
|||||||
dispatch(actions.setCombiner([]));
|
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.setInfo(null));
|
dispatch(actions.setInfo(null));
|
||||||
dispatch(actions.setItemEquip(null));
|
dispatch(actions.setItemEquip(null));
|
||||||
dispatch(actions.setItemUnequip([]));
|
dispatch(actions.setItemUnequip([]));
|
||||||
|
|||||||
@ -9,15 +9,22 @@ const shapes = require('./shapes');
|
|||||||
|
|
||||||
|
|
||||||
class InfoComponent extends preact.Component {
|
class InfoComponent extends preact.Component {
|
||||||
shouldComponentUpdate(newProps) {
|
shouldComponentUpdate(newProps, newState) {
|
||||||
if (newProps.tutorial !== this.props.tutorial) return true;
|
if (newProps.tutorial !== this.props.tutorial) return true;
|
||||||
// We don't care about info during tutorial
|
// We don't care about info during tutorial
|
||||||
if (newProps.tutorial && this.props.instance.time_control === 'Practice'
|
if (newProps.tutorial && this.props.instance.time_control === 'Practice'
|
||||||
&& this.props.instance.rounds.length === 1) return false;
|
&& this.props.instance.rounds.length === 1) return false;
|
||||||
if (newProps.info !== this.props.info) return true;
|
if (newProps.info !== this.props.info) return true;
|
||||||
|
if (newState.comboItem !== this.state.comboItem) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
// Catch case where mouse events don't properly clear state and info changed
|
||||||
|
if (prevProps.info !== this.props.info && this.state.comboItem) this.setState({ comboItem: null });
|
||||||
|
}
|
||||||
|
|
||||||
render(args) {
|
render(args) {
|
||||||
const {
|
const {
|
||||||
// Variables that will change
|
// Variables that will change
|
||||||
@ -33,7 +40,7 @@ class InfoComponent extends preact.Component {
|
|||||||
setInfo,
|
setInfo,
|
||||||
setTutorialNull,
|
setTutorialNull,
|
||||||
} = args;
|
} = args;
|
||||||
|
const { comboItem } = this.state;
|
||||||
function Info() {
|
function Info() {
|
||||||
if (tutorial) {
|
if (tutorial) {
|
||||||
const tutorialStageInfo = tutorialStage(tutorial, ws, setTutorialNull, instance);
|
const tutorialStageInfo = tutorialStage(tutorial, ws, setTutorialNull, instance);
|
||||||
@ -42,7 +49,7 @@ class InfoComponent extends preact.Component {
|
|||||||
if (!info) return false;
|
if (!info) return false;
|
||||||
if (info.includes('constructName')) {
|
if (info.includes('constructName')) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2> {info.replace('constructName ', '')} </h2>
|
<h2> {info.replace('constructName ', '')} </h2>
|
||||||
<p> This is the name of your construct. <br />
|
<p> This is the name of your construct. <br />
|
||||||
Names are randomly generated and are purely cosmetic. <br />
|
Names are randomly generated and are purely cosmetic. <br />
|
||||||
@ -54,7 +61,7 @@ class InfoComponent extends preact.Component {
|
|||||||
|
|
||||||
if (info.includes('constructAvatar')) {
|
if (info.includes('constructAvatar')) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2> {info.replace('constructAvatar ', '')} </h2>
|
<h2> {info.replace('constructAvatar ', '')} </h2>
|
||||||
<p> This is your construct avatar. <br />
|
<p> This is your construct avatar. <br />
|
||||||
Avatars are randomly generated and are purely cosmetic. <br />
|
Avatars are randomly generated and are purely cosmetic. <br />
|
||||||
@ -63,7 +70,9 @@ class InfoComponent extends preact.Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const fullInfo = itemInfo.items.find(i => i.item === info) || INFO[info];
|
const fullInfo = comboItem
|
||||||
|
? itemInfo.items.find(i => i.item === comboItem) || INFO[comboItem]
|
||||||
|
: itemInfo.items.find(i => i.item === info) || INFO[info];
|
||||||
if (!fullInfo) return false;
|
if (!fullInfo) return false;
|
||||||
const isSkill = fullInfo.skill;
|
const isSkill = fullInfo.skill;
|
||||||
const isSpec = fullInfo.spec;
|
const isSpec = fullInfo.spec;
|
||||||
@ -75,16 +84,17 @@ class InfoComponent extends preact.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isSkill || isSpec) {
|
if (isSkill || isSpec) {
|
||||||
let infoName = info;
|
let infoName = fullInfo.item;
|
||||||
while (infoName.includes('Plus')) infoName = infoName.replace('Plus', '+');
|
while (infoName.includes('Plus')) infoName = infoName.replace('Plus', '+');
|
||||||
|
|
||||||
const header = isSkill ? <h3> SKILL </h3> : <h3> SPEC </h3>;
|
const itemSource = itemInfo.combos.filter(c => c.item === removeTier(fullInfo.item));
|
||||||
|
|
||||||
const itemSource = itemInfo.combos.filter(c => c.item === removeTier(info));
|
let itemSourceInfo = itemSource.length && !isSpec
|
||||||
let itemSourceInfo = itemSource.length
|
|
||||||
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
|
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
let header = null;
|
||||||
|
if (!itemSource.length) header = isSkill ? <h3> SKILL </h3> : <h3> SPEC </h3>;
|
||||||
if (itemSourceInfo) {
|
if (itemSourceInfo) {
|
||||||
while (itemSourceInfo.includes('Plus')) itemSourceInfo = itemSourceInfo.replace('Plus', '+');
|
while (itemSourceInfo.includes('Plus')) itemSourceInfo = itemSourceInfo.replace('Plus', '+');
|
||||||
const itemRegEx = /(Red|Blue|Green)/;
|
const itemRegEx = /(Red|Blue|Green)/;
|
||||||
@ -100,7 +110,7 @@ class InfoComponent extends preact.Component {
|
|||||||
const thresholds = isSpec ? specThresholds(player, fullInfo, info) : null;
|
const thresholds = isSpec ? specThresholds(player, fullInfo, info) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={isSkill ? 'info-skill' : 'info-spec'}>
|
<div class={isSkill ? 'info-item' : 'info-item'}>
|
||||||
<h2>{infoName} {fullInfo.cost}b</h2>
|
<h2>{infoName} {fullInfo.cost}b</h2>
|
||||||
{header}
|
{header}
|
||||||
{itemSourceInfo}
|
{itemSourceInfo}
|
||||||
@ -120,7 +130,7 @@ class InfoComponent extends preact.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Combos() {
|
const Combos = () => {
|
||||||
if (tutorial && instance.time_control === 'Practice' && instance.rounds.length === 1) return false;
|
if (tutorial && instance.time_control === 'Practice' && instance.rounds.length === 1) return false;
|
||||||
const generalNotes = (
|
const generalNotes = (
|
||||||
<div>
|
<div>
|
||||||
@ -137,22 +147,33 @@ class InfoComponent extends preact.Component {
|
|||||||
const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info));
|
const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info));
|
||||||
if (vboxCombos.length > 6 || vboxCombos.length === 0) return generalNotes;
|
if (vboxCombos.length > 6 || vboxCombos.length === 0) return generalNotes;
|
||||||
|
|
||||||
|
const comboTable = vboxCombos.map((c, i) => {
|
||||||
|
const mouseOver = e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.setState({ comboItem: c.item });
|
||||||
|
};
|
||||||
|
const componentTable = (c.components.some(ci => ['Red', 'Blue', 'Green'].includes(ci)))
|
||||||
|
? [<div key="0">{convertItem(c.components[0])} {convertItem(c.components[1])}</div>,
|
||||||
|
<div key="1">{convertItem(c.components[2])}</div>]
|
||||||
|
: c.components.map((u, j) => <div key={j} >{convertItem(u)}</div>);
|
||||||
return (
|
return (
|
||||||
<table class="combos">
|
<div key={i} onMouseOver={mouseOver} class="table-button" onClick={() => setInfo(c.item)}>
|
||||||
<tbody>
|
<div class="item">
|
||||||
{vboxCombos.map((c, i) =>
|
{convertItem(c.item)}
|
||||||
<tr key={i} >
|
</div>
|
||||||
<td class="highlight" onClick={() => setInfo(c.item)} >{convertItem(c.item)}</td>
|
{componentTable}
|
||||||
{c.components.map((u, j) => <td key={j} >{convertItem(u)}</td>)}
|
</div>
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
return (
|
||||||
|
<div class="combos">
|
||||||
|
{comboTable}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='info' >
|
<div class='info' onMouseOver={() => this.setState({ comboItem: null })}>
|
||||||
<Info />
|
<Info />
|
||||||
<Combos />
|
<Combos />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -66,10 +66,6 @@ const addState = connect(
|
|||||||
dispatch(actions.setInfo(item));
|
dispatch(actions.setInfo(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setActiveConstruct(value) {
|
|
||||||
dispatch(actions.setActiveConstruct(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
function setItemEquip(v) {
|
function setItemEquip(v) {
|
||||||
return dispatch(actions.setItemEquip(v));
|
return dispatch(actions.setItemEquip(v));
|
||||||
}
|
}
|
||||||
@ -78,7 +74,7 @@ const addState = connect(
|
|||||||
return dispatch(actions.setItemUnequip(v));
|
return dispatch(actions.setItemUnequip(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
return { quit, setInfo, setActiveConstruct, setItemUnequip, setItemEquip };
|
return { quit, setInfo, setItemUnequip, setItemEquip };
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
@ -101,7 +97,6 @@ function Construct(props) {
|
|||||||
sendVboxAcceptEquip,
|
sendVboxAcceptEquip,
|
||||||
sendVboxUnequipApply,
|
sendVboxUnequipApply,
|
||||||
sendUnequip,
|
sendUnequip,
|
||||||
setActiveConstruct,
|
|
||||||
setItemUnequip,
|
setItemUnequip,
|
||||||
setItemEquip,
|
setItemEquip,
|
||||||
setInfo,
|
setInfo,
|
||||||
@ -144,7 +139,6 @@ function Construct(props) {
|
|||||||
function skillClick(e) {
|
function skillClick(e) {
|
||||||
if (!skill) return false;
|
if (!skill) return false;
|
||||||
setItemUnequip([construct.id, skill.skill]);
|
setItemUnequip([construct.id, skill.skill]);
|
||||||
setActiveConstruct(construct);
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -152,7 +146,6 @@ function Construct(props) {
|
|||||||
function skillDblClick(e) {
|
function skillDblClick(e) {
|
||||||
if (!skill) return false;
|
if (!skill) return false;
|
||||||
sendUnequip(construct.id, skill.skill);
|
sendUnequip(construct.id, skill.skill);
|
||||||
setActiveConstruct(null);
|
|
||||||
setItemUnequip([]);
|
setItemUnequip([]);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -160,7 +153,7 @@ function Construct(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const equipping = skillList.includes(vbox.bound[itemEquip]) && !skill
|
const equipping = skillList.includes(vbox.bound[itemEquip]) && !skill
|
||||||
&& !tutorialDisableEquip && !duplicateSkill;
|
&& !tutorialDisableEquip && !duplicateSkill && i === construct.skills.length;
|
||||||
const border = () => {
|
const border = () => {
|
||||||
if (!skill) return '';
|
if (!skill) return '';
|
||||||
const borderFn = buttons[removeTier(skill.skill)];
|
const borderFn = buttons[removeTier(skill.skill)];
|
||||||
@ -173,7 +166,7 @@ function Construct(props) {
|
|||||||
<label onDragStart={ev => {
|
<label onDragStart={ev => {
|
||||||
ev.dataTransfer.setData('text', '');
|
ev.dataTransfer.setData('text', '');
|
||||||
skillClick(ev);
|
skillClick(ev);
|
||||||
}} key={i} draggable="true" onDragEnd={() => setItemUnequip([])}>
|
}} key={i} draggable={skill} onDragEnd={() => setItemUnequip([])}>
|
||||||
<button
|
<button
|
||||||
key={i}
|
key={i}
|
||||||
disabled={!skill && !equipping}
|
disabled={!skill && !equipping}
|
||||||
@ -191,7 +184,7 @@ function Construct(props) {
|
|||||||
const s = construct.specs[i];
|
const s = construct.specs[i];
|
||||||
|
|
||||||
if (!s) {
|
if (!s) {
|
||||||
const equipping = specList.includes(vbox.bound[itemEquip]);
|
const equipping = specList.includes(vbox.bound[itemEquip]) && i === construct.specs.length;
|
||||||
const classes = `${equipping ? 'equipping' : 'gray'} empty`;
|
const classes = `${equipping ? 'equipping' : 'gray'} empty`;
|
||||||
return (
|
return (
|
||||||
<button key={i} class={classes} disabled={!equipping} >
|
<button key={i} class={classes} disabled={!equipping} >
|
||||||
@ -203,12 +196,10 @@ function Construct(props) {
|
|||||||
function specClick(e) {
|
function specClick(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setItemUnequip([construct.id, s]);
|
setItemUnequip([construct.id, s]);
|
||||||
setActiveConstruct(construct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function specDblClick(e) {
|
function specDblClick(e) {
|
||||||
sendUnequip(construct.id, s);
|
sendUnequip(construct.id, s);
|
||||||
setActiveConstruct(null);
|
|
||||||
setItemUnequip([]);
|
setItemUnequip([]);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -247,7 +238,7 @@ function Construct(props) {
|
|||||||
</div>;
|
</div>;
|
||||||
});
|
});
|
||||||
|
|
||||||
const classes = `instance-construct`;
|
const classes = 'instance-construct';
|
||||||
const avatarMouseOver = e => hoverInfo(e, `constructAvatar ${construct.name}`);
|
const avatarMouseOver = e => hoverInfo(e, `constructAvatar ${construct.name}`);
|
||||||
return (
|
return (
|
||||||
<div key={construct.id} class={classes} onClick={onClick} onDragOver={ev => ev.preventDefault()} onDrop={onClick}>
|
<div key={construct.id} class={classes} onClick={onClick} onDragOver={ev => ev.preventDefault()} onDrop={onClick}>
|
||||||
@ -291,7 +282,6 @@ class InstanceConstructs extends preact.Component {
|
|||||||
itemInfo,
|
itemInfo,
|
||||||
// Function calls
|
// Function calls
|
||||||
setInfo,
|
setInfo,
|
||||||
setActiveConstruct,
|
|
||||||
sendVboxApply,
|
sendVboxApply,
|
||||||
sendVboxAcceptEquip,
|
sendVboxAcceptEquip,
|
||||||
sendVboxUnequipApply,
|
sendVboxUnequipApply,
|
||||||
@ -321,7 +311,6 @@ class InstanceConstructs extends preact.Component {
|
|||||||
sendVboxAcceptEquip,
|
sendVboxAcceptEquip,
|
||||||
sendVboxUnequipApply,
|
sendVboxUnequipApply,
|
||||||
setInfo,
|
setInfo,
|
||||||
setActiveConstruct,
|
|
||||||
itemInfo,
|
itemInfo,
|
||||||
setVboxHighlight,
|
setVboxHighlight,
|
||||||
sendUnequip,
|
sendUnequip,
|
||||||
@ -331,7 +320,7 @@ class InstanceConstructs extends preact.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='construct-list' onClick={() => setActiveConstruct(null)}>
|
<div class='construct-list'>
|
||||||
{constructs}
|
{constructs}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -17,16 +17,11 @@ const addState = connect(
|
|||||||
return ws.sendInstanceReady(instance.id);
|
return ws.sendInstanceReady(instance.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendAbandon() {
|
|
||||||
return ws.sendInstanceAbandon(instance.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
instance,
|
instance,
|
||||||
chatShow,
|
chatShow,
|
||||||
account,
|
account,
|
||||||
|
|
||||||
sendAbandon,
|
|
||||||
sendReady,
|
sendReady,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -48,22 +43,12 @@ function InstanceCtrlBtns(args) {
|
|||||||
chatShow,
|
chatShow,
|
||||||
account,
|
account,
|
||||||
|
|
||||||
sendAbandon,
|
|
||||||
sendReady,
|
sendReady,
|
||||||
setChatShow,
|
setChatShow,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
const finished = instance && instance.phase === 'Finished';
|
const finished = instance && instance.phase === 'Finished';
|
||||||
|
|
||||||
// cheeky to make sure nubs don't just abandon their first game
|
|
||||||
const beingNub = instance.phase_end
|
|
||||||
&& instance.phase === 'Lobby'
|
|
||||||
&& Date.parse(instance.phase_end) - Date.now() < 2000;
|
|
||||||
|
|
||||||
if (beingNub) {
|
|
||||||
sendReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
||||||
|
|||||||
@ -36,7 +36,6 @@ const addState = connect(
|
|||||||
dispatch(actions.setCombiner([]));
|
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.setInfo(null));
|
dispatch(actions.setInfo(null));
|
||||||
dispatch(actions.setItemEquip(null));
|
dispatch(actions.setItemEquip(null));
|
||||||
dispatch(actions.setItemUnequip([]));
|
dispatch(actions.setItemUnequip([]));
|
||||||
|
|||||||
@ -14,6 +14,7 @@ const addState = connect(
|
|||||||
account,
|
account,
|
||||||
instances,
|
instances,
|
||||||
invite,
|
invite,
|
||||||
|
pvp,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
function sendInstanceState(id) {
|
function sendInstanceState(id) {
|
||||||
@ -32,15 +33,21 @@ const addState = connect(
|
|||||||
ws.sendInstanceInvite();
|
ws.sendInstanceInvite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendInstanceLeave() {
|
||||||
|
ws.sendInstanceLeave();
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account,
|
account,
|
||||||
instances,
|
instances,
|
||||||
invite,
|
invite,
|
||||||
|
pvp,
|
||||||
|
|
||||||
sendInstanceState,
|
sendInstanceState,
|
||||||
sendInstanceQueue,
|
sendInstanceQueue,
|
||||||
sendInstancePractice,
|
sendInstancePractice,
|
||||||
sendInstanceInvite,
|
sendInstanceInvite,
|
||||||
|
sendInstanceLeave,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -67,11 +74,13 @@ function Play(args) {
|
|||||||
account,
|
account,
|
||||||
instances,
|
instances,
|
||||||
invite,
|
invite,
|
||||||
|
pvp,
|
||||||
|
|
||||||
sendInstanceState,
|
sendInstanceState,
|
||||||
sendInstanceQueue,
|
sendInstanceQueue,
|
||||||
sendInstancePractice,
|
sendInstancePractice,
|
||||||
sendInstanceInvite,
|
sendInstanceInvite,
|
||||||
|
sendInstanceLeave,
|
||||||
|
|
||||||
setNav,
|
setNav,
|
||||||
} = args;
|
} = args;
|
||||||
@ -125,6 +134,31 @@ function Play(args) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pvpBtn = () => {
|
||||||
|
if (pvp) return (
|
||||||
|
<figure>
|
||||||
|
<button
|
||||||
|
class="ready"
|
||||||
|
onClick={() => sendInstanceLeave()}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<figcaption>Finding Opponent</figcaption>
|
||||||
|
</figure>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<figure>
|
||||||
|
<button
|
||||||
|
class="ready"
|
||||||
|
onClick={() => sendInstanceQueue()}>
|
||||||
|
PVP
|
||||||
|
</button>
|
||||||
|
<figcaption>Matchmaking</figcaption>
|
||||||
|
</figure>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const subscription = account.subscribed
|
const subscription = account.subscribed
|
||||||
? <button
|
? <button
|
||||||
class="yellow-btn"
|
class="yellow-btn"
|
||||||
@ -142,14 +176,7 @@ function Play(args) {
|
|||||||
if (!instances.length) {
|
if (!instances.length) {
|
||||||
return (
|
return (
|
||||||
<div class='list play'>
|
<div class='list play'>
|
||||||
<figure>
|
{pvpBtn()}
|
||||||
<button
|
|
||||||
class="ready"
|
|
||||||
onClick={() => sendInstanceQueue()}>
|
|
||||||
PVP
|
|
||||||
</button>
|
|
||||||
<figcaption>Matchmaking</figcaption>
|
|
||||||
</figure>
|
|
||||||
{inviteBtn()}
|
{inviteBtn()}
|
||||||
<figure>
|
<figure>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -56,7 +56,7 @@ function Reshape(args) {
|
|||||||
const useMtx = (item, i) => {
|
const useMtx = (item, i) => {
|
||||||
const price = item === 'Rename' ? 5 : 1;
|
const price = item === 'Rename' ? 5 : 1;
|
||||||
return (
|
return (
|
||||||
<figure key={i} onClick={e => {
|
<figure key={i * 2} onClick={e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setMtxActive(item);
|
setMtxActive(item);
|
||||||
}}>
|
}}>
|
||||||
@ -67,7 +67,7 @@ function Reshape(args) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const availableMtx = (item, i) => (
|
const availableMtx = (item, i) => (
|
||||||
<figure key={i}>
|
<figure key={i * 2 + 1}>
|
||||||
<figcaption>Enable {item.variant}</figcaption>
|
<figcaption>Enable {item.variant}</figcaption>
|
||||||
<button onClick={() => mtxBuy(item)} disabled={account.balance < item.credits}>¤{item.credits}</button>
|
<button onClick={() => mtxBuy(item)} disabled={account.balance < item.credits}>¤{item.credits}</button>
|
||||||
</figure>
|
</figure>
|
||||||
|
|||||||
@ -44,21 +44,26 @@ function BitsBtn(args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const subscription = account.subscribed
|
const subscription = account.subscribed
|
||||||
? <button
|
? <figure>
|
||||||
|
<figcaption>Thank you for your support</figcaption>
|
||||||
|
<button
|
||||||
class="yellow-btn"
|
class="yellow-btn"
|
||||||
disabled>
|
disabled>
|
||||||
Subscribed
|
Subscribed
|
||||||
</button>
|
</button>
|
||||||
: <button
|
</figure>
|
||||||
onClick={subscribeClick}
|
: <figure onClick={subscribeClick}>
|
||||||
|
<figcaption>¤150 / month + Chat Wheel + more</figcaption>
|
||||||
|
<button
|
||||||
class="yellow-btn"
|
class="yellow-btn"
|
||||||
role="link">
|
role="link">
|
||||||
Subscribe
|
Subscribe
|
||||||
</button>;
|
</button>
|
||||||
|
</figure>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div class='list'>
|
<div class='list sub'>
|
||||||
{subscription}
|
{subscription}
|
||||||
</div>
|
</div>
|
||||||
<div class='list'>
|
<div class='list'>
|
||||||
|
|||||||
@ -213,6 +213,7 @@ class Vbox extends preact.Component {
|
|||||||
const classes = `${v.toLowerCase()} ${selected ? 'highlight' : ''} ${comboHighlight}`;
|
const classes = `${v.toLowerCase()} ${selected ? 'highlight' : ''} ${comboHighlight}`;
|
||||||
|
|
||||||
const vboxObject = shapes[v] ? shapes[v]() : v;
|
const vboxObject = shapes[v] ? shapes[v]() : v;
|
||||||
|
const disabled = vbox.bits <= group;
|
||||||
return (
|
return (
|
||||||
<label draggable='true'
|
<label draggable='true'
|
||||||
onDragStart={ev => {
|
onDragStart={ev => {
|
||||||
@ -223,6 +224,7 @@ class Vbox extends preact.Component {
|
|||||||
onDragEnd={clearVboxSelected}>
|
onDragEnd={clearVboxSelected}>
|
||||||
<button
|
<button
|
||||||
class={classes}
|
class={classes}
|
||||||
|
disabled={disabled}
|
||||||
onMouseOver={e => vboxHover(e, v)}
|
onMouseOver={e => vboxHover(e, v)}
|
||||||
onMouseDown={onClick}
|
onMouseDown={onClick}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
@ -244,7 +246,7 @@ class Vbox extends preact.Component {
|
|||||||
onTouchStart={e => e.target.scrollIntoView(true)}
|
onTouchStart={e => e.target.scrollIntoView(true)}
|
||||||
onMouseOver={e => hoverInfo(e, 'vbox')}> VBOX
|
onMouseOver={e => hoverInfo(e, 'vbox')}> VBOX
|
||||||
</h3>
|
</h3>
|
||||||
<div class="bits" onMouseOver={e => hoverInfo(e, 'bits')} >{vbox.bits}b</div>
|
<div class={`bits ${vbox.bits < 3 ? 'red' : false}`} onMouseOver={e => hoverInfo(e, 'bits')} >{vbox.bits}b</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="vbox-colours">
|
<div class="vbox-colours">
|
||||||
{range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))}
|
{range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))}
|
||||||
@ -285,7 +287,7 @@ class Vbox extends preact.Component {
|
|||||||
const combinerItems = combiner.map(j => vbox.bound[j]);
|
const combinerItems = combiner.map(j => vbox.bound[j]);
|
||||||
const combinerCount = countBy(combinerItems, co => co);
|
const combinerCount = countBy(combinerItems, co => co);
|
||||||
|
|
||||||
const comboHighlight = combinerItems.length > 0 && itemInfo.combos.some(combo => {
|
const comboItem = itemInfo.combos.find(combo => {
|
||||||
if (combo.components.includes(v)) {
|
if (combo.components.includes(v)) {
|
||||||
return combinerItems.every(c => {
|
return combinerItems.every(c => {
|
||||||
if (!combo.components.includes(c)) return false;
|
if (!combo.components.includes(c)) return false;
|
||||||
@ -295,7 +297,8 @@ class Vbox extends preact.Component {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
} return false;
|
} return false;
|
||||||
}) ? 'combo-border' : '';
|
});
|
||||||
|
const comboHighlight = combinerItems.length > 0 && comboItem ? 'combo-border' : '';
|
||||||
|
|
||||||
function onClick(type) {
|
function onClick(type) {
|
||||||
if (vboxSelecting) clearVboxSelected();
|
if (vboxSelecting) clearVboxSelected();
|
||||||
@ -321,6 +324,7 @@ class Vbox extends preact.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
combiner.push(i);
|
combiner.push(i);
|
||||||
|
if (combiner.length === 3) setInfo(comboItem.item);
|
||||||
return combinerChange(combiner);
|
return combinerChange(combiner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ module.exports = {
|
|||||||
Colours - 1b<br />
|
Colours - 1b<br />
|
||||||
Skills - 2b<br />
|
Skills - 2b<br />
|
||||||
Specs - 3b<br />
|
Specs - 3b<br />
|
||||||
At the beginning of each round you receive 18 bits increasing by 6 bits per round.</p>,
|
At the beginning of each round you receive 30 bits.</p>,
|
||||||
},
|
},
|
||||||
ready: {
|
ready: {
|
||||||
item: 'READY',
|
item: 'READY',
|
||||||
|
|||||||
@ -30,6 +30,10 @@ function registerEvents(store) {
|
|||||||
store.dispatch(actions.setPing(ping));
|
store.dispatch(actions.setPing(ping));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setPvp(v) {
|
||||||
|
store.dispatch(actions.setPvp(v));
|
||||||
|
}
|
||||||
|
|
||||||
function setNav(v) {
|
function setNav(v) {
|
||||||
store.dispatch(actions.setNav(v));
|
store.dispatch(actions.setNav(v));
|
||||||
}
|
}
|
||||||
@ -120,7 +124,6 @@ function registerEvents(store) {
|
|||||||
store.dispatch(actions.setAnimText(null));
|
store.dispatch(actions.setAnimText(null));
|
||||||
store.dispatch(actions.setAnimating(false));
|
store.dispatch(actions.setAnimating(false));
|
||||||
store.dispatch(actions.setGameEffectInfo(null));
|
store.dispatch(actions.setGameEffectInfo(null));
|
||||||
store.dispatch(actions.setSkip(false));
|
|
||||||
|
|
||||||
// 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));
|
||||||
@ -177,7 +180,6 @@ function registerEvents(store) {
|
|||||||
|
|
||||||
function clearInfo() {
|
function clearInfo() {
|
||||||
store.dispatch(actions.setInfo(null));
|
store.dispatch(actions.setInfo(null));
|
||||||
store.dispatch(actions.setActiveConstruct(null));
|
|
||||||
console.log('event clear item');
|
console.log('event clear item');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +187,6 @@ function registerEvents(store) {
|
|||||||
store.dispatch(actions.setCombiner([]));
|
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.setInfo(null));
|
store.dispatch(actions.setInfo(null));
|
||||||
store.dispatch(actions.setItemEquip(null));
|
store.dispatch(actions.setItemEquip(null));
|
||||||
store.dispatch(actions.setItemUnequip([]));
|
store.dispatch(actions.setItemUnequip([]));
|
||||||
@ -209,16 +210,16 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setInstance(v) {
|
function setInstance(v) {
|
||||||
const { account, instance, ws, tutorial } = store.getState();
|
const { account, ws, tutorial } = store.getState();
|
||||||
if (v) {
|
if (v) {
|
||||||
setInvite(null);
|
setInvite(null);
|
||||||
|
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 (!instance || v.id !== instance.id) {
|
const skip = v.time_control === 'Practice' && v.phase === 'Lobby';
|
||||||
store.dispatch(actions.setNav('vbox'));
|
if (skip) {
|
||||||
const first = player.constructs[0];
|
ws.sendInstanceReady(v.id);
|
||||||
store.dispatch(actions.setActiveConstruct(first));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v.phase === 'Finished') {
|
if (v.phase === 'Finished') {
|
||||||
@ -364,6 +365,7 @@ function registerEvents(store) {
|
|||||||
setItemInfo,
|
setItemInfo,
|
||||||
setInvite,
|
setInvite,
|
||||||
setPing,
|
setPing,
|
||||||
|
setPvp,
|
||||||
setShop,
|
setShop,
|
||||||
setTeam,
|
setTeam,
|
||||||
setSubscription,
|
setSubscription,
|
||||||
|
|||||||
@ -9,7 +9,6 @@ function setupKeys(store) {
|
|||||||
key('esc', () => store.dispatch(actions.setCombiner([])));
|
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.setInfo(null)));
|
key('esc', () => store.dispatch(actions.setInfo(null)));
|
||||||
key('esc', () => store.dispatch(actions.setItemEquip(null)));
|
key('esc', () => store.dispatch(actions.setItemEquip(null)));
|
||||||
key('esc', () => store.dispatch(actions.setItemUnequip([])));
|
key('esc', () => store.dispatch(actions.setItemUnequip([])));
|
||||||
|
|||||||
@ -10,7 +10,6 @@ function createReducer(defaultState, actionType) {
|
|||||||
/* eslint-disable key-spacing */
|
/* eslint-disable key-spacing */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
account: createReducer(null, 'SET_ACCOUNT'),
|
account: createReducer(null, 'SET_ACCOUNT'),
|
||||||
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'),
|
||||||
|
|
||||||
@ -48,8 +47,8 @@ module.exports = {
|
|||||||
ping: createReducer(null, 'SET_PING'),
|
ping: createReducer(null, 'SET_PING'),
|
||||||
player: createReducer(null, 'SET_PLAYER'),
|
player: createReducer(null, 'SET_PLAYER'),
|
||||||
reclaiming: createReducer(false, 'SET_RECLAIMING'),
|
reclaiming: createReducer(false, 'SET_RECLAIMING'),
|
||||||
skip: createReducer(false, 'SET_SKIP'),
|
|
||||||
shop: createReducer(false, 'SET_SHOP'),
|
shop: createReducer(false, 'SET_SHOP'),
|
||||||
|
pvp: createReducer(null, 'SET_PVP'),
|
||||||
|
|
||||||
subscription: createReducer(null, 'SET_SUBSCRIPTION'),
|
subscription: createReducer(null, 'SET_SUBSCRIPTION'),
|
||||||
|
|
||||||
|
|||||||
@ -151,6 +151,10 @@ function createSocket(events) {
|
|||||||
send(['InstanceQueue', {}]);
|
send(['InstanceQueue', {}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendInstanceLeave() {
|
||||||
|
send(['InstanceLeave', {}]);
|
||||||
|
}
|
||||||
|
|
||||||
function sendInstanceInvite() {
|
function sendInstanceInvite() {
|
||||||
send(['InstanceInvite', {}]);
|
send(['InstanceInvite', {}]);
|
||||||
}
|
}
|
||||||
@ -274,8 +278,16 @@ function createSocket(events) {
|
|||||||
Pong: onPong,
|
Pong: onPong,
|
||||||
Demo: onDemo,
|
Demo: onDemo,
|
||||||
|
|
||||||
QueueRequested: () => events.notify('PVP queue request received.'),
|
// QueueRequested: () => events.notify('PVP queue request received.'),
|
||||||
QueueJoined: () => events.notify('You have joined the PVP queue.'),
|
QueueRequested: () => true,
|
||||||
|
QueueJoined: () => {
|
||||||
|
events.notify('You have joined the PVP queue.');
|
||||||
|
events.setPvp(true);
|
||||||
|
},
|
||||||
|
QueueLeft: () => {
|
||||||
|
events.notify('You have left the PVP queue.');
|
||||||
|
events.setPvp(false);
|
||||||
|
},
|
||||||
QueueFound: () => events.notify('Your PVP game has started.'),
|
QueueFound: () => events.notify('Your PVP game has started.'),
|
||||||
InviteRequested: () => events.notify('PVP invite request received.'),
|
InviteRequested: () => events.notify('PVP invite request received.'),
|
||||||
Invite: code => events.setInvite(code),
|
Invite: code => events.setInvite(code),
|
||||||
@ -318,11 +330,8 @@ function createSocket(events) {
|
|||||||
return handlers[msgType](params);
|
return handlers[msgType](params);
|
||||||
}
|
}
|
||||||
|
|
||||||
let attempts = 1;
|
|
||||||
|
|
||||||
// Connection opened
|
// Connection opened
|
||||||
function onOpen() {
|
function onOpen() {
|
||||||
attempts = 0;
|
|
||||||
toast.info({
|
toast.info({
|
||||||
message: 'connected',
|
message: 'connected',
|
||||||
position: 'topRight',
|
position: 'topRight',
|
||||||
@ -341,21 +350,12 @@ function createSocket(events) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onClose(event) {
|
function onClose(event) {
|
||||||
attempts *= 2;
|
|
||||||
if (attempts > 10) {
|
|
||||||
toast.warning({
|
|
||||||
message: 'unable to connect, refreshing...',
|
|
||||||
position: 'topRight',
|
|
||||||
});
|
|
||||||
setTimeout(() => window.location.reload(true), 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error('WebSocket closed', event);
|
console.error('WebSocket closed', event);
|
||||||
toast.warning({
|
toast.warning({
|
||||||
message: 'disconnected',
|
message: 'disconnected',
|
||||||
position: 'topRight',
|
position: 'topRight',
|
||||||
});
|
});
|
||||||
return setTimeout(connect, attempts * 1000);
|
return setTimeout(connect, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function connect() {
|
function connect() {
|
||||||
@ -402,6 +402,7 @@ function createSocket(events) {
|
|||||||
sendInstanceInvite,
|
sendInstanceInvite,
|
||||||
sendInstanceJoin,
|
sendInstanceJoin,
|
||||||
sendInstanceChat,
|
sendInstanceChat,
|
||||||
|
sendInstanceLeave,
|
||||||
|
|
||||||
sendVboxAccept,
|
sendVboxAccept,
|
||||||
sendVboxAcceptEquip,
|
sendVboxAcceptEquip,
|
||||||
|
|||||||
@ -109,7 +109,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
const tutorialText = () => {
|
const tutorialText = () => {
|
||||||
if (tutorial === 1) {
|
if (tutorial === 1) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</h2>
|
||||||
<p> Welcome to the vbox phase tutorial.</p>
|
<p> Welcome to the vbox phase tutorial.</p>
|
||||||
<p> Colours are used to create powerful combinations. </p>
|
<p> Colours are used to create powerful combinations. </p>
|
||||||
@ -121,7 +121,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
|
|
||||||
if (tutorial === 2) {
|
if (tutorial === 2) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</h2>
|
||||||
<p> In a normal game you start with three base <b>Attack</b> skill items. </p>
|
<p> In a normal game you start with three base <b>Attack</b> skill items. </p>
|
||||||
<p> The <b>Attack</b> item can be combined with <b>colours</b> to create a new skill. </p>
|
<p> The <b>Attack</b> item can be combined with <b>colours</b> to create a new skill. </p>
|
||||||
@ -135,7 +135,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
if (tutorial === 3) {
|
if (tutorial === 3) {
|
||||||
const constructOne = instance.players[0].constructs[0].name;
|
const constructOne = instance.players[0].constructs[0].name;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</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>
|
||||||
@ -147,7 +147,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
|
|
||||||
if (tutorial === 4) {
|
if (tutorial === 4) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</h2>
|
||||||
<p> You can also buy specialisation items for your constructs. <br />
|
<p> You can also buy specialisation items for your constructs. <br />
|
||||||
Specialisation items increase stats including power, speed and life. </p>
|
Specialisation items increase stats including power, speed and life. </p>
|
||||||
@ -159,7 +159,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
|
|
||||||
if (tutorial === 5) {
|
if (tutorial === 5) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</h2>
|
||||||
<p> Equipping specialisation items will increase the stats of your constructs.</p>
|
<p> Equipping specialisation items will increase the stats of your constructs.</p>
|
||||||
<p> These can also be combined with colours for further specialisation. </p>
|
<p> These can also be combined with colours for further specialisation. </p>
|
||||||
@ -173,7 +173,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
const constructTwo = instance.players[0].constructs[1].name;
|
const constructTwo = instance.players[0].constructs[1].name;
|
||||||
const constructThree = instance.players[0].constructs[2].name;
|
const constructThree = instance.players[0].constructs[2].name;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</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> The goal is to create three powerful constructs for combat. </p>
|
||||||
@ -185,7 +185,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
|
|
||||||
if (tutorial === 7) {
|
if (tutorial === 7) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</h2>
|
||||||
<p> Each round you start with a vbox full of different skills, specs and colours. </p>
|
<p> Each round you start with a vbox full of different skills, specs and colours. </p>
|
||||||
<p> Bits are your currency for buying skills, specs and colours from the vbox. <br />
|
<p> Bits are your currency for buying skills, specs and colours from the vbox. <br />
|
||||||
@ -204,7 +204,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Tutorial</h2>
|
||||||
<p>You've completed the tutorial! Try to create more skill and spec combinations. </p>
|
<p>You've completed the tutorial! Try to create more skill and spec combinations. </p>
|
||||||
<p>You can unequip skills and specs back into the inventory by double clicking. <br />
|
<p>You can unequip skills and specs back into the inventory by double clicking. <br />
|
||||||
@ -216,7 +216,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const classes = tutorial === 8 ? 'focus' : '';
|
const classes = tutorial === 8 ? 'focus' : '';
|
||||||
const text = tutorial === 8 ? 'Continue' : 'Close Tutorial'
|
const text = tutorial === 8 ? 'Continue' : 'Skip Tutorial'
|
||||||
const exitTutorial = <button
|
const exitTutorial = <button
|
||||||
class={classes}
|
class={classes}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
@ -235,5 +235,5 @@ module.exports = {
|
|||||||
tutorialConstructDisplay,
|
tutorialConstructDisplay,
|
||||||
tutorialVbox,
|
tutorialVbox,
|
||||||
tutorialStage,
|
tutorialStage,
|
||||||
tutorialShouldDisableEquip
|
tutorialShouldDisableEquip,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -266,7 +266,7 @@ function effectInfo(i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (i.effect) {
|
switch (i.effect) {
|
||||||
case 'Amplify': return `Increases construct RedPower BluePower GreenPower by ${i.meta[1] - 100}%`;
|
case 'Amplify': return `Increases construct RedPower BluePower by ${i.meta[1] - 100}%`;
|
||||||
case 'Banish': return 'Banished construct cannot cast or take damage';
|
case 'Banish': return 'Banished construct cannot cast or take damage';
|
||||||
case 'Block': return `Reduces construct red damage and blue damage taken by ${100 - i.meta[1]}%`;
|
case 'Block': return `Reduces construct red damage and blue damage taken by ${100 - i.meta[1]}%`;
|
||||||
case 'Buff': return `Increases construct RedPower BluePower SpeedStat by ${i.meta[1] - 100}%`;
|
case 'Buff': return `Increases construct RedPower BluePower SpeedStat by ${i.meta[1] - 100}%`;
|
||||||
@ -282,6 +282,7 @@ function effectInfo(i) {
|
|||||||
case 'Restrict': return 'Disable construct from casting any red skills';
|
case 'Restrict': return 'Disable construct from casting any red skills';
|
||||||
case 'Stun': return 'Stunned construct cannot use skills';
|
case 'Stun': return 'Stunned construct cannot use skills';
|
||||||
case 'Intercept': return 'Redirect any skills on team to this target construct';
|
case 'Intercept': return 'Redirect any skills on team to this target construct';
|
||||||
|
case 'Pure': return `Construct will take ${i.meta[1] - 100}% increased healing`;
|
||||||
case 'Vulnerable': return `Construct will take ${i.meta[1] - 100}% increased red damage`;
|
case 'Vulnerable': return `Construct will take ${i.meta[1] - 100}% increased red damage`;
|
||||||
case 'Silence': return 'Disable construct from casting any blue skills';
|
case 'Silence': return 'Disable construct from casting any blue skills';
|
||||||
case 'Wither': return `Construct will take ${100 - i.meta[1]}% reduced healing`; //
|
case 'Wither': return `Construct will take ${100 - i.meta[1]}% reduced healing`; //
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=mnml game server
|
Description=mnml game server
|
||||||
User=mnml
|
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
User=mnml
|
||||||
ExecStart=/usr/local/mnml/bin/mnml
|
ExecStart=/usr/local/mnml/bin/mnml
|
||||||
KillMode=process
|
KillMode=process
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartPreventExitStatus=255
|
RestartPreventExitStatus=255
|
||||||
|
|
||||||
|
#StandardOutput=file:/var/log/mnml/mnml.log
|
||||||
|
StandardOutput=null
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
@ -295,11 +295,13 @@
|
|||||||
## Uncomment to remove deprecated metrics.
|
## Uncomment to remove deprecated metrics.
|
||||||
# fielddrop = ["uptime_format"]
|
# fielddrop = ["uptime_format"]
|
||||||
|
|
||||||
[[inputs.tail]]
|
# [[inputs.tail]]
|
||||||
files = ["/var/log/mnml/mnml.log"]
|
# files = ["/var/log/mnml/mnml.log"]
|
||||||
name_override = "mnml_log"
|
# name_override = "mnml_log"
|
||||||
data_format = "json"
|
# data_format = "json"
|
||||||
json_time_key = "time"
|
# json_time_key = "time"
|
||||||
json_time_format = "2006-01-02T15:04:05.999999999Z07:00"
|
# json_time_format = "2006-01-02T15:04:05.999999999Z07:00"
|
||||||
json_string_fields = ["level", "module", "msg"]
|
# json_string_fields = ["level", "module", "msg"]
|
||||||
|
|
||||||
|
[[inputs.syslog]]
|
||||||
|
server = "tcp://:6514"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-ops",
|
"name": "mnml-ops",
|
||||||
"version": "1.8.1",
|
"version": "1.8.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mnml"
|
name = "mnml"
|
||||||
version = "1.8.1"
|
version = "1.8.3"
|
||||||
authors = ["ntr <ntr@smokestack.io>"]
|
authors = ["ntr <ntr@smokestack.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -23,7 +23,8 @@ failure = "0.1"
|
|||||||
|
|
||||||
dotenv = "0.9.0"
|
dotenv = "0.9.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
fern = { version = "0.5", features = ["colored"] }
|
fern = { version = "0.5", features = ["colored", "syslog-4"] }
|
||||||
|
syslog = "4"
|
||||||
|
|
||||||
iron = "0.6"
|
iron = "0.6"
|
||||||
bodyparser = "0.8"
|
bodyparser = "0.8"
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use http::MnmlHttpError;
|
|||||||
use names::{name as generate_name};
|
use names::{name as generate_name};
|
||||||
use construct::{Construct, ConstructSkeleton, construct_spawn};
|
use construct::{Construct, ConstructSkeleton, construct_spawn};
|
||||||
use instance::{Instance, instance_delete};
|
use instance::{Instance, instance_delete};
|
||||||
|
use instance;
|
||||||
use mtx::{Mtx, FREE_MTX};
|
use mtx::{Mtx, FREE_MTX};
|
||||||
use pg::Db;
|
use pg::Db;
|
||||||
use img;
|
use img;
|
||||||
@ -21,6 +22,7 @@ use failure::Error;
|
|||||||
use failure::{err_msg, format_err};
|
use failure::{err_msg, format_err};
|
||||||
|
|
||||||
static PASSWORD_MIN_LEN: usize = 3;
|
static PASSWORD_MIN_LEN: usize = 3;
|
||||||
|
static PASSWORD_ROUNDS: u32 = 10;
|
||||||
|
|
||||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
@ -69,11 +71,11 @@ pub fn chat_wheel(_db: &Db, _id: Uuid) -> Result<Vec<String>, Error> {
|
|||||||
return Ok(vec![
|
return Ok(vec![
|
||||||
"gg".to_string(),
|
"gg".to_string(),
|
||||||
"glhf".to_string(),
|
"glhf".to_string(),
|
||||||
"hmm".to_string(),
|
"ez".to_string(),
|
||||||
"ok".to_string(),
|
|
||||||
"rekt".to_string(),
|
"rekt".to_string(),
|
||||||
"thx".to_string(),
|
"wow".to_string(),
|
||||||
"nice".to_string(),
|
"wp".to_string(),
|
||||||
|
"ok".to_string(),
|
||||||
"...".to_string(),
|
"...".to_string(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@ -225,8 +227,7 @@ pub fn set_password(tx: &mut Transaction, id: Uuid, current: &String, password:
|
|||||||
return Err(MnmlHttpError::BadRequest);
|
return Err(MnmlHttpError::BadRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
let rounds = 8;
|
let password = hash(&password, PASSWORD_ROUNDS)?;
|
||||||
let password = hash(&password, rounds)?;
|
|
||||||
|
|
||||||
let query = "
|
let query = "
|
||||||
UPDATE accounts
|
UPDATE accounts
|
||||||
@ -326,10 +327,13 @@ pub fn create(name: &String, password: &String, tx: &mut Transaction) -> Result<
|
|||||||
return Err(MnmlHttpError::AccountNameNotProvided);
|
return Err(MnmlHttpError::AccountNameNotProvided);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if name.len() > 20 {
|
||||||
|
return Err(MnmlHttpError::AccountNameUnacceptable);
|
||||||
|
}
|
||||||
|
|
||||||
let id = Uuid::new_v4();
|
let id = Uuid::new_v4();
|
||||||
let img = Uuid::new_v4();
|
let img = Uuid::new_v4();
|
||||||
let rounds = 12;
|
let password = hash(&password, PASSWORD_ROUNDS)?;
|
||||||
let password = hash(&password, rounds)?;
|
|
||||||
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let token: String = iter::repeat(())
|
let token: String = iter::repeat(())
|
||||||
@ -502,3 +506,25 @@ pub fn img_check(account: &Account) -> Result<Uuid, Error> {
|
|||||||
false => Ok(account.img),
|
false => Ok(account.img),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tutorial(tx: &mut Transaction, account: &Account) -> Result<Option<Instance>, Error> {
|
||||||
|
let query = "
|
||||||
|
SELECT count(id)
|
||||||
|
FROM players
|
||||||
|
WHERE account = $1;
|
||||||
|
";
|
||||||
|
|
||||||
|
let result = tx
|
||||||
|
.query(query, &[&account.id])?;
|
||||||
|
|
||||||
|
let row = result.iter().next()
|
||||||
|
.ok_or(format_err!("unable to fetch joined games account={:?}", account))?;
|
||||||
|
|
||||||
|
let count: i64 = row.get(0);
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return Ok(Some(instance::instance_practice(tx, account)?));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
@ -10,20 +10,21 @@ pub enum Effect {
|
|||||||
Banish,
|
Banish,
|
||||||
Block,
|
Block,
|
||||||
Buff,
|
Buff,
|
||||||
Sustain,
|
Counter,
|
||||||
Curse,
|
Curse,
|
||||||
Haste,
|
Haste,
|
||||||
Hybrid,
|
Hybrid,
|
||||||
|
Intercept,
|
||||||
Invert,
|
Invert,
|
||||||
Counter,
|
Pure,
|
||||||
Purge,
|
Purge,
|
||||||
Reflect,
|
Reflect,
|
||||||
Slow,
|
|
||||||
Restrict,
|
Restrict,
|
||||||
Stun,
|
|
||||||
Intercept,
|
|
||||||
Vulnerable,
|
|
||||||
Silence,
|
Silence,
|
||||||
|
Slow,
|
||||||
|
Stun,
|
||||||
|
Sustain,
|
||||||
|
Vulnerable,
|
||||||
Wither, // Reduce green dmg (healing) taken
|
Wither, // Reduce green dmg (healing) taken
|
||||||
|
|
||||||
// electric is the buff that applies
|
// electric is the buff that applies
|
||||||
@ -99,21 +100,25 @@ impl Effect {
|
|||||||
|
|
||||||
pub fn modifications(&self) -> Vec<Stat> {
|
pub fn modifications(&self) -> Vec<Stat> {
|
||||||
match self {
|
match self {
|
||||||
Effect::Vulnerable => vec![Stat::RedDamageTaken],
|
// Bases
|
||||||
Effect::Block => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
Effect::Block => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
||||||
Effect::Buff => vec![Stat::BluePower, Stat::RedPower, Stat::Speed],
|
Effect::Buff => vec![Stat::BluePower, Stat::RedPower, Stat::Speed],
|
||||||
|
|
||||||
Effect::Absorption => vec![Stat::RedPower, Stat::BluePower],
|
|
||||||
|
|
||||||
Effect::Amplify => vec![Stat::GreenPower, Stat::RedPower, Stat::BluePower],
|
|
||||||
Effect::Curse => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
|
||||||
|
|
||||||
Effect::Hybrid => vec![Stat::GreenPower],
|
|
||||||
Effect::Wither => vec![Stat::GreenDamageTaken],
|
|
||||||
|
|
||||||
Effect::Haste => vec![Stat::Speed],
|
|
||||||
Effect::Slow => vec![Stat::Speed],
|
Effect::Slow => vec![Stat::Speed],
|
||||||
|
|
||||||
|
// Power changes
|
||||||
|
Effect::Absorption => vec![Stat::RedPower, Stat::BluePower],
|
||||||
|
Effect::Amplify => vec![Stat::RedPower, Stat::BluePower],
|
||||||
|
Effect::Hybrid => vec![Stat::GreenPower],
|
||||||
|
|
||||||
|
// Damage taken changes
|
||||||
|
Effect::Curse => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
||||||
|
Effect::Pure => vec![Stat::GreenDamageTaken], // increased green taken
|
||||||
|
Effect::Vulnerable => vec![Stat::RedDamageTaken],
|
||||||
|
Effect::Wither => vec![Stat::GreenDamageTaken], // reduced green taken
|
||||||
|
|
||||||
|
// Speed
|
||||||
|
Effect::Haste => vec![Stat::Speed],
|
||||||
|
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,6 +133,7 @@ impl Effect {
|
|||||||
Effect::Haste |
|
Effect::Haste |
|
||||||
Effect::Slow |
|
Effect::Slow |
|
||||||
Effect::Hybrid |
|
Effect::Hybrid |
|
||||||
|
Effect::Pure |
|
||||||
Effect::Wither => value.pct(match meta {
|
Effect::Wither => value.pct(match meta {
|
||||||
Some(EffectMeta::Multiplier(d)) => d,
|
Some(EffectMeta::Multiplier(d)) => d,
|
||||||
_ => 100,
|
_ => 100,
|
||||||
@ -135,7 +141,10 @@ impl Effect {
|
|||||||
|
|
||||||
Effect::Absorption => value + match meta {
|
Effect::Absorption => value + match meta {
|
||||||
Some(EffectMeta::AddedDamage(d)) => d,
|
Some(EffectMeta::AddedDamage(d)) => d,
|
||||||
_ => panic!("absorb meta not damage"),
|
_ => {
|
||||||
|
warn!("absorb meta not damage");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
@ -185,6 +194,7 @@ impl Effect {
|
|||||||
Effect::Decay => Some(Colour::Blue),
|
Effect::Decay => Some(Colour::Blue),
|
||||||
Effect::Regen => Some(Colour::Green),
|
Effect::Regen => Some(Colour::Green),
|
||||||
Effect::Siphon => Some(Colour::Blue),
|
Effect::Siphon => Some(Colour::Blue),
|
||||||
|
Effect::Pure => Some(Colour::Green),
|
||||||
|
|
||||||
Effect::Ko => None,
|
Effect::Ko => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,7 @@ pub enum Event {
|
|||||||
Invite(Id),
|
Invite(Id),
|
||||||
Join(Id, String),
|
Join(Id, String),
|
||||||
Joined(Id),
|
Joined(Id),
|
||||||
|
Leave(Id),
|
||||||
|
|
||||||
Chat(Id, Uuid, String),
|
Chat(Id, Uuid, String),
|
||||||
ChatClear(Id, Uuid),
|
ChatClear(Id, Uuid),
|
||||||
@ -249,6 +250,7 @@ impl Events {
|
|||||||
// or flag the requester as pvp ready
|
// or flag the requester as pvp ready
|
||||||
let requester = self.clients.get_mut(&id).unwrap();
|
let requester = self.clients.get_mut(&id).unwrap();
|
||||||
requester.pvp = true;
|
requester.pvp = true;
|
||||||
|
requester.tx.send(RpcMessage::QueueJoined(()))?;
|
||||||
info!("joined game queue id={:?} account={:?}", requester.id, requester.account);
|
info!("joined game queue id={:?} account={:?}", requester.id, requester.account);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
@ -305,6 +307,18 @@ impl Events {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Event::Leave(id) => {
|
||||||
|
// check whether request is valid
|
||||||
|
let c = self.clients.get_mut(&id)
|
||||||
|
.ok_or(format_err!("connection not found id={:?}", id))?;
|
||||||
|
|
||||||
|
c.pvp = false;
|
||||||
|
c.tx.send(RpcMessage::QueueLeft(()))?;
|
||||||
|
info!("left game queue id={:?} account={:?}", c.id, c.account);
|
||||||
|
return Ok(());
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
Event::Chat(id, instance, msg) => {
|
Event::Chat(id, instance, msg) => {
|
||||||
// set the chat state of this connection
|
// set the chat state of this connection
|
||||||
{
|
{
|
||||||
|
|||||||
@ -635,15 +635,15 @@ impl Game {
|
|||||||
for player in self.players.iter_mut() {
|
for player in self.players.iter_mut() {
|
||||||
if !player.ready {
|
if !player.ready {
|
||||||
player.set_ready(true);
|
player.set_ready(true);
|
||||||
player.add_warning();
|
// player.add_warning();
|
||||||
info!("upkeep: {:} warned", player.name);
|
// info!("upkeep: {:} warned", player.name);
|
||||||
if player.warnings >= 3 {
|
// if player.warnings >= 3 {
|
||||||
player.forfeit();
|
// player.forfeit();
|
||||||
info!("upkeep: {:} forfeited", player.name);
|
// info!("upkeep: {:} forfeited", player.name);
|
||||||
//todo
|
// //todo
|
||||||
// self.resolved.push(forfeit)
|
// // self.resolved.push(forfeit)
|
||||||
// self.log.push(format!("{:} forfeited.", player.name));
|
// // self.log.push(format!("{:} forfeited.", player.name));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1622,6 +1622,6 @@ mod tests {
|
|||||||
game.players[0].set_ready(true);
|
game.players[0].set_ready(true);
|
||||||
game.phase_end = Some(Utc::now().checked_sub_signed(Duration::seconds(500)).unwrap());
|
game.phase_end = Some(Utc::now().checked_sub_signed(Duration::seconds(500)).unwrap());
|
||||||
game = game.upkeep();
|
game = game.upkeep();
|
||||||
assert!(game.players[1].warnings == 1);
|
// assert!(game.players[1].warnings == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,8 @@ pub enum MnmlHttpError {
|
|||||||
AccountNameNotProvided,
|
AccountNameNotProvided,
|
||||||
#[fail(display="account name unavailable")]
|
#[fail(display="account name unavailable")]
|
||||||
AccountNameUnavailable,
|
AccountNameUnavailable,
|
||||||
|
#[fail(display="account name is unacceptable. 20 char max")]
|
||||||
|
AccountNameUnacceptable,
|
||||||
#[fail(display="account not found")]
|
#[fail(display="account not found")]
|
||||||
AccountNotFound,
|
AccountNotFound,
|
||||||
#[fail(display="password does not match")]
|
#[fail(display="password does not match")]
|
||||||
@ -122,6 +124,7 @@ impl From<MnmlHttpError> for IronError {
|
|||||||
|
|
||||||
MnmlHttpError::AccountNameNotProvided |
|
MnmlHttpError::AccountNameNotProvided |
|
||||||
MnmlHttpError::AccountNameUnavailable |
|
MnmlHttpError::AccountNameUnavailable |
|
||||||
|
MnmlHttpError::AccountNameUnacceptable |
|
||||||
MnmlHttpError::AccountNotFound |
|
MnmlHttpError::AccountNotFound |
|
||||||
MnmlHttpError::BadRequest |
|
MnmlHttpError::BadRequest |
|
||||||
MnmlHttpError::PasswordUnacceptable => (m_err.compat(), status::BadRequest),
|
MnmlHttpError::PasswordUnacceptable => (m_err.compat(), status::BadRequest),
|
||||||
|
|||||||
@ -318,12 +318,12 @@ impl Instance {
|
|||||||
self.phase_end = self.time_control.vbox_phase_end();
|
self.phase_end = self.time_control.vbox_phase_end();
|
||||||
|
|
||||||
let bits = match self.rounds.len() > 0 {
|
let bits = match self.rounds.len() > 0 {
|
||||||
true => 12 + 6 * self.rounds.len(),
|
true => 30,
|
||||||
false => 0,
|
false => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.players.iter_mut().for_each(|p| {
|
self.players.iter_mut().for_each(|p| {
|
||||||
p.vbox.balance_add(bits.into());
|
p.vbox.balance_add(bits);
|
||||||
p.set_ready(false);
|
p.set_ready(false);
|
||||||
p.vbox.fill();
|
p.vbox.fill();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -712,7 +712,7 @@ impl Item {
|
|||||||
// Skills <- need to move effect mulltipliers into skills
|
// Skills <- need to move effect mulltipliers into skills
|
||||||
Item::Amplify|
|
Item::Amplify|
|
||||||
Item::AmplifyPlus |
|
Item::AmplifyPlus |
|
||||||
Item::AmplifyPlusPlus => format!("Increase RedPower BluePower GreenPower by {:?}%. Lasts {:?}T.",
|
Item::AmplifyPlusPlus => format!("Increase RedPower BluePower by {:?}%. Lasts {:?}T.",
|
||||||
self.into_skill().unwrap().effect()[0].get_multiplier() - 100,
|
self.into_skill().unwrap().effect()[0].get_multiplier() - 100,
|
||||||
self.into_skill().unwrap().effect()[0].get_duration()),
|
self.into_skill().unwrap().effect()[0].get_duration()),
|
||||||
|
|
||||||
@ -824,15 +824,17 @@ impl Item {
|
|||||||
Item::Purge|
|
Item::Purge|
|
||||||
Item::PurgePlus |
|
Item::PurgePlus |
|
||||||
Item::PurgePlusPlus => format!(
|
Item::PurgePlusPlus => format!(
|
||||||
"Remove buffs from target construct.
|
"Remove all effects from target construct.
|
||||||
Applies purge disabling target green skills for {:?}T.",
|
Applies purge disabling target green skills for {:?}T.",
|
||||||
self.into_skill().unwrap().effect()[0].get_duration()),
|
self.into_skill().unwrap().effect()[0].get_duration()),
|
||||||
|
|
||||||
Item::Purify|
|
Item::Purify|
|
||||||
Item::PurifyPlus |
|
Item::PurifyPlus |
|
||||||
Item::PurifyPlusPlus => format!(
|
Item::PurifyPlusPlus => format!(
|
||||||
"Remove debuffs and heals for {:?}% GreenPower per debuff removed.",
|
"Remove all effects and heals for {:?}% GreenPower per effect removed.
|
||||||
self.into_skill().unwrap().multiplier()),
|
Applies Pure increasing healing taken by {:?}%.",
|
||||||
|
self.into_skill().unwrap().multiplier(),
|
||||||
|
self.into_skill().unwrap().effect()[0].get_multiplier() - 100),
|
||||||
|
|
||||||
Item::Reflect|
|
Item::Reflect|
|
||||||
Item::ReflectPlus |
|
Item::ReflectPlus |
|
||||||
@ -898,11 +900,10 @@ impl Item {
|
|||||||
Item::Bash|
|
Item::Bash|
|
||||||
Item::BashPlus |
|
Item::BashPlus |
|
||||||
Item::BashPlusPlus => format!(
|
Item::BashPlusPlus => format!(
|
||||||
"Bash the target increasing the cooldowns of target skills by 1T.
|
"Bash the target increasing the cooldowns of target skills by 1T. Stuns target for {:?}T.
|
||||||
Deals {:?}% RedPower as red damage and 45% more damage per cooldown increased.
|
Deals {:?}% RedPower as red damage and 45% more damage per cooldown increased.",
|
||||||
Stuns for {:?}T.",
|
self.into_skill().unwrap().effect()[0].get_duration(),
|
||||||
self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier(),
|
self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier()),
|
||||||
self.into_skill().unwrap().effect()[0].get_duration()),
|
|
||||||
|
|
||||||
Item::Strike|
|
Item::Strike|
|
||||||
Item::StrikePlus |
|
Item::StrikePlus |
|
||||||
@ -1318,25 +1319,18 @@ pub fn get_combos() -> Vec<Combo> {
|
|||||||
Combo { components: Item::Intercept.combo(), item: Item::Intercept },
|
Combo { components: Item::Intercept.combo(), item: Item::Intercept },
|
||||||
Combo { components: Item::InterceptPlus.combo(), item: Item::InterceptPlus },
|
Combo { components: Item::InterceptPlus.combo(), item: Item::InterceptPlus },
|
||||||
Combo { components: Item::InterceptPlusPlus.combo(), item: Item::InterceptPlusPlus },
|
Combo { components: Item::InterceptPlusPlus.combo(), item: Item::InterceptPlusPlus },
|
||||||
|
|
||||||
Combo { components: Item::Triage.combo(), item: Item::Triage },
|
Combo { components: Item::Triage.combo(), item: Item::Triage },
|
||||||
Combo { components: Item::TriagePlus.combo(), item: Item::TriagePlus },
|
Combo { components: Item::TriagePlus.combo(), item: Item::TriagePlus },
|
||||||
Combo { components: Item::TriagePlusPlus.combo(), item: Item::TriagePlusPlus },
|
Combo { components: Item::TriagePlusPlus.combo(), item: Item::TriagePlusPlus },
|
||||||
|
|
||||||
Combo { components: Item::Link.combo(), item: Item::Link },
|
|
||||||
Combo { components: Item::LinkPlus.combo(), item: Item::LinkPlus },
|
|
||||||
Combo { components: Item::LinkPlusPlus.combo(), item: Item::LinkPlusPlus },
|
|
||||||
|
|
||||||
Combo { components: Item::Haste.combo(), item: Item::Haste },
|
|
||||||
Combo { components: Item::HastePlus.combo(), item: Item::HastePlus },
|
|
||||||
Combo { components: Item::HastePlusPlus.combo(), item: Item::HastePlusPlus },
|
|
||||||
Combo { components: Item::Absorb.combo(), item: Item::Absorb },
|
Combo { components: Item::Absorb.combo(), item: Item::Absorb },
|
||||||
Combo { components: Item::AbsorbPlus.combo(), item: Item::AbsorbPlus },
|
Combo { components: Item::AbsorbPlus.combo(), item: Item::AbsorbPlus },
|
||||||
Combo { components: Item::AbsorbPlusPlus.combo(), item: Item::AbsorbPlusPlus },
|
Combo { components: Item::AbsorbPlusPlus.combo(), item: Item::AbsorbPlusPlus },
|
||||||
|
Combo { components: Item::Haste.combo(), item: Item::Haste },
|
||||||
|
Combo { components: Item::HastePlus.combo(), item: Item::HastePlus },
|
||||||
|
Combo { components: Item::HastePlusPlus.combo(), item: Item::HastePlusPlus },
|
||||||
Combo { components: Item::Hybrid.combo(), item: Item::Hybrid },
|
Combo { components: Item::Hybrid.combo(), item: Item::Hybrid },
|
||||||
Combo { components: Item::HybridPlus.combo(), item: Item::HybridPlus },
|
Combo { components: Item::HybridPlus.combo(), item: Item::HybridPlus },
|
||||||
Combo { components: Item::HybridPlusPlus.combo(), item: Item::HybridPlusPlus },
|
Combo { components: Item::HybridPlusPlus.combo(), item: Item::HybridPlusPlus },
|
||||||
|
|
||||||
Combo { components: Item::Amplify.combo(), item: Item::Amplify },
|
Combo { components: Item::Amplify.combo(), item: Item::Amplify },
|
||||||
Combo { components: Item::AmplifyPlus.combo(), item: Item::AmplifyPlus },
|
Combo { components: Item::AmplifyPlus.combo(), item: Item::AmplifyPlus },
|
||||||
Combo { components: Item::AmplifyPlusPlus.combo(), item: Item::AmplifyPlusPlus },
|
Combo { components: Item::AmplifyPlusPlus.combo(), item: Item::AmplifyPlusPlus },
|
||||||
@ -1353,15 +1347,15 @@ pub fn get_combos() -> Vec<Combo> {
|
|||||||
Combo { components: Item::SilencePlusPlus.combo(), item: Item::SilencePlusPlus },
|
Combo { components: Item::SilencePlusPlus.combo(), item: Item::SilencePlusPlus },
|
||||||
|
|
||||||
|
|
||||||
|
Combo { components: Item::Invert.combo(), item: Item::Invert },
|
||||||
|
Combo { components: Item::InvertPlus.combo(), item: Item::InvertPlus },
|
||||||
|
Combo { components: Item::InvertPlusPlus.combo(), item: Item::InvertPlusPlus },
|
||||||
Combo { components: Item::Curse.combo(), item: Item::Curse },
|
Combo { components: Item::Curse.combo(), item: Item::Curse },
|
||||||
Combo { components: Item::CursePlus.combo(), item: Item::CursePlus },
|
Combo { components: Item::CursePlus.combo(), item: Item::CursePlus },
|
||||||
Combo { components: Item::CursePlusPlus.combo(), item: Item::CursePlusPlus },
|
Combo { components: Item::CursePlusPlus.combo(), item: Item::CursePlusPlus },
|
||||||
Combo { components: Item::Decay.combo(), item: Item::Decay },
|
Combo { components: Item::Decay.combo(), item: Item::Decay },
|
||||||
Combo { components: Item::DecayPlus.combo(), item: Item::DecayPlus },
|
Combo { components: Item::DecayPlus.combo(), item: Item::DecayPlus },
|
||||||
Combo { components: Item::DecayPlusPlus.combo(), item: Item::DecayPlusPlus },
|
Combo { components: Item::DecayPlusPlus.combo(), item: Item::DecayPlusPlus },
|
||||||
Combo { components: Item::Invert.combo(), item: Item::Invert },
|
|
||||||
Combo { components: Item::InvertPlus.combo(), item: Item::InvertPlus },
|
|
||||||
Combo { components: Item::InvertPlusPlus.combo(), item: Item::InvertPlusPlus },
|
|
||||||
|
|
||||||
Combo { components: Item::Counter.combo(), item: Item::Counter },
|
Combo { components: Item::Counter.combo(), item: Item::Counter },
|
||||||
Combo { components: Item::CounterPlus.combo(), item: Item::CounterPlus },
|
Combo { components: Item::CounterPlus.combo(), item: Item::CounterPlus },
|
||||||
@ -1399,6 +1393,9 @@ pub fn get_combos() -> Vec<Combo> {
|
|||||||
Combo { components: Item::Break.combo(), item: Item::Break },
|
Combo { components: Item::Break.combo(), item: Item::Break },
|
||||||
Combo { components: Item::BreakPlus.combo(), item: Item::BreakPlus },
|
Combo { components: Item::BreakPlus.combo(), item: Item::BreakPlus },
|
||||||
Combo { components: Item::BreakPlusPlus.combo(), item: Item::BreakPlusPlus },
|
Combo { components: Item::BreakPlusPlus.combo(), item: Item::BreakPlusPlus },
|
||||||
|
Combo { components: Item::Link.combo(), item: Item::Link },
|
||||||
|
Combo { components: Item::LinkPlus.combo(), item: Item::LinkPlus },
|
||||||
|
Combo { components: Item::LinkPlusPlus.combo(), item: Item::LinkPlusPlus },
|
||||||
Combo { components: Item::Banish.combo(), item: Item::Banish },
|
Combo { components: Item::Banish.combo(), item: Item::Banish },
|
||||||
Combo { components: Item::BanishPlus.combo(), item: Item::BanishPlus },
|
Combo { components: Item::BanishPlus.combo(), item: Item::BanishPlus },
|
||||||
Combo { components: Item::BanishPlusPlus.combo(), item: Item::BanishPlusPlus },
|
Combo { components: Item::BanishPlusPlus.combo(), item: Item::BanishPlusPlus },
|
||||||
|
|||||||
@ -62,15 +62,18 @@ use std::path::{Path};
|
|||||||
use fern::colors::{Color, ColoredLevelConfig};
|
use fern::colors::{Color, ColoredLevelConfig};
|
||||||
use crossbeam_channel::{unbounded};
|
use crossbeam_channel::{unbounded};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
struct JsonLog {
|
|
||||||
time: String,
|
|
||||||
module: String,
|
|
||||||
level: String,
|
|
||||||
msg: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setup_logger() -> Result<(), fern::InitError> {
|
pub fn setup_logger() -> Result<(), fern::InitError> {
|
||||||
|
let formatter = syslog::Formatter3164 {
|
||||||
|
facility: syslog::Facility::LOG_USER,
|
||||||
|
hostname: None,
|
||||||
|
process: "mnml".to_owned(),
|
||||||
|
pid: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let syslog = fern::Dispatch::new()
|
||||||
|
.level(log::LevelFilter::Info)
|
||||||
|
.chain(syslog::unix(formatter).unwrap());
|
||||||
|
|
||||||
let colors_line = ColoredLevelConfig::new()
|
let colors_line = ColoredLevelConfig::new()
|
||||||
.error(Color::Red)
|
.error(Color::Red)
|
||||||
.warn(Color::Yellow)
|
.warn(Color::Yellow)
|
||||||
@ -90,31 +93,16 @@ pub fn setup_logger() -> Result<(), fern::InitError> {
|
|||||||
message = message,
|
message = message,
|
||||||
));
|
));
|
||||||
})
|
})
|
||||||
|
.chain(fern::log_file("/var/log/mnml/mnml.log")?)
|
||||||
.chain(std::io::stdout());
|
.chain(std::io::stdout());
|
||||||
|
|
||||||
let json = fern::Dispatch::new()
|
|
||||||
.format(|out, message, record| {
|
|
||||||
let json = JsonLog {
|
|
||||||
time: chrono::Local::now().to_rfc3339(),
|
|
||||||
module: record.target().to_string(),
|
|
||||||
level: record.level().to_string(),
|
|
||||||
msg: message.to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
out.finish(format_args!(
|
|
||||||
"{}",
|
|
||||||
serde_json::to_string(&json).unwrap(),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.chain(fern::log_file("/var/log/mnml/mnml.log")?);
|
|
||||||
|
|
||||||
fern::Dispatch::new()
|
fern::Dispatch::new()
|
||||||
.level_for("postgres", log::LevelFilter::Info)
|
.level_for("postgres", log::LevelFilter::Info)
|
||||||
.level_for("ws", log::LevelFilter::Warn)
|
.level_for("ws", log::LevelFilter::Warn)
|
||||||
.level_for("iron", log::LevelFilter::Info)
|
.level_for("iron", log::LevelFilter::Info)
|
||||||
.level(log::LevelFilter::Info)
|
.level(log::LevelFilter::Info)
|
||||||
.chain(term)
|
.chain(term)
|
||||||
.chain(json)
|
.chain(syslog)
|
||||||
.apply()?;
|
.apply()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -44,7 +44,7 @@ const FIRSTS: [&'static str; 53] = [
|
|||||||
"orbiting",
|
"orbiting",
|
||||||
"piscine",
|
"piscine",
|
||||||
"polar",
|
"polar",
|
||||||
"purified",
|
"pure",
|
||||||
"recalcitrant",
|
"recalcitrant",
|
||||||
"rogue",
|
"rogue",
|
||||||
"sealed",
|
"sealed",
|
||||||
|
|||||||
@ -77,11 +77,11 @@ fn handle_notification(n: Notification, pool: &PgPool, events: &Sender<Event>) {
|
|||||||
|
|
||||||
let msg = match n.action {
|
let msg = match n.action {
|
||||||
Action::Delete => {
|
Action::Delete => {
|
||||||
warn!("unimplemented delete notification {:?}", n);
|
// warn!("unimplemented delete notification {:?}", n);
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
Action::Insert => {
|
Action::Insert => {
|
||||||
warn!("unimplemented insert notification {:?}", n);
|
// warn!("unimplemented insert notification {:?}", n);
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
Action::Update => match n.table {
|
Action::Update => match n.table {
|
||||||
@ -92,7 +92,7 @@ fn handle_notification(n: Notification, pool: &PgPool, events: &Sender<Event>) {
|
|||||||
Table::Games =>
|
Table::Games =>
|
||||||
Some(Event::Push(n.id, RpcMessage::GameState(game::game_get(&mut tx, n.id).unwrap()))),
|
Some(Event::Push(n.id, RpcMessage::GameState(game::game_get(&mut tx, n.id).unwrap()))),
|
||||||
_ => {
|
_ => {
|
||||||
warn!("unimplemented update notification {:?}", n);
|
// warn!("unimplemented update notification {:?}", n);
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -63,7 +63,6 @@ pub struct Player {
|
|||||||
pub constructs: Vec<Construct>,
|
pub constructs: Vec<Construct>,
|
||||||
pub bot: bool,
|
pub bot: bool,
|
||||||
pub ready: bool,
|
pub ready: bool,
|
||||||
pub warnings: u8,
|
|
||||||
pub draw_offered: bool,
|
pub draw_offered: bool,
|
||||||
pub score: Score,
|
pub score: Score,
|
||||||
}
|
}
|
||||||
@ -85,7 +84,6 @@ impl Player {
|
|||||||
constructs,
|
constructs,
|
||||||
bot: false,
|
bot: false,
|
||||||
ready: false,
|
ready: false,
|
||||||
warnings: 0,
|
|
||||||
draw_offered: false,
|
draw_offered: false,
|
||||||
score: Score::Zero,
|
score: Score::Zero,
|
||||||
})
|
})
|
||||||
@ -100,7 +98,6 @@ impl Player {
|
|||||||
constructs,
|
constructs,
|
||||||
bot: false,
|
bot: false,
|
||||||
ready: false,
|
ready: false,
|
||||||
warnings: 0,
|
|
||||||
draw_offered: false,
|
draw_offered: false,
|
||||||
score: Score::Zero,
|
score: Score::Zero,
|
||||||
}
|
}
|
||||||
@ -134,11 +131,6 @@ impl Player {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_warning(&mut self) -> &mut Player {
|
|
||||||
self.warnings += 1;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn forfeit(&mut self) -> &mut Player {
|
pub fn forfeit(&mut self) -> &mut Player {
|
||||||
for construct in self.constructs.iter_mut() {
|
for construct in self.constructs.iter_mut() {
|
||||||
construct.force_ko();
|
construct.force_ko();
|
||||||
|
|||||||
@ -63,7 +63,7 @@ pub enum RpcMessage {
|
|||||||
|
|
||||||
QueueRequested(()),
|
QueueRequested(()),
|
||||||
QueueJoined(()),
|
QueueJoined(()),
|
||||||
QueueCancelled(()),
|
QueueLeft(()),
|
||||||
QueueFound(()),
|
QueueFound(()),
|
||||||
|
|
||||||
InviteRequested(()),
|
InviteRequested(()),
|
||||||
@ -105,6 +105,7 @@ pub enum RpcRequest {
|
|||||||
InstanceInvite {},
|
InstanceInvite {},
|
||||||
InstanceJoin { code: String },
|
InstanceJoin { code: String },
|
||||||
InstanceQueue {},
|
InstanceQueue {},
|
||||||
|
InstanceLeave {},
|
||||||
InstancePractice {},
|
InstancePractice {},
|
||||||
InstanceAbandon { instance_id: Uuid },
|
InstanceAbandon { instance_id: Uuid },
|
||||||
InstanceReady { instance_id: Uuid },
|
InstanceReady { instance_id: Uuid },
|
||||||
@ -168,6 +169,10 @@ impl Connection {
|
|||||||
self.events.send(Event::Join(self.id, code))?;
|
self.events.send(Event::Join(self.id, code))?;
|
||||||
Ok(RpcMessage::Joining(()))
|
Ok(RpcMessage::Joining(()))
|
||||||
},
|
},
|
||||||
|
RpcRequest::InstanceLeave {} => {
|
||||||
|
self.events.send(Event::Leave(self.id))?;
|
||||||
|
Ok(RpcMessage::Processing(()))
|
||||||
|
},
|
||||||
|
|
||||||
RpcRequest::InstanceChat { instance_id, index } => {
|
RpcRequest::InstanceChat { instance_id, index } => {
|
||||||
if !account.subscribed {
|
if !account.subscribed {
|
||||||
@ -353,6 +358,10 @@ impl Handler for Connection {
|
|||||||
let wheel = account::chat_wheel(&db, a.id).unwrap();
|
let wheel = account::chat_wheel(&db, a.id).unwrap();
|
||||||
self.send(RpcMessage::ChatWheel(wheel)).unwrap();
|
self.send(RpcMessage::ChatWheel(wheel)).unwrap();
|
||||||
|
|
||||||
|
if let Some(instance) = account::tutorial(&mut tx, &a).unwrap() {
|
||||||
|
self.send(RpcMessage::InstanceState(instance)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// tx should do nothing
|
// tx should do nothing
|
||||||
tx.commit().unwrap();
|
tx.commit().unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -299,9 +299,9 @@ pub fn resolve(skill: Skill, source: &mut Construct, target: &mut Construct, mut
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) -> Resolutions {
|
fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) -> Resolutions {
|
||||||
for Resolution { source, target, event, stages: _ } in resolutions.clone() {
|
for Resolution { source: event_source, target: event_target, event, stages: _ } in resolutions.clone() {
|
||||||
let mut source = game.construct_by_id(source.id).unwrap().clone();
|
let mut source = game.construct_by_id(event_source.id).unwrap().clone();
|
||||||
let mut target = game.construct_by_id(target.id).unwrap().clone();
|
let mut target = game.construct_by_id(event_target.id).unwrap().clone();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Damage { amount, skill, mitigation, colour: c } => {
|
Event::Damage { amount, skill, mitigation, colour: c } => {
|
||||||
@ -352,7 +352,8 @@ fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) ->
|
|||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
|
|
||||||
if target.is_ko() {
|
if target.is_ko() && event_target.green == 0 {
|
||||||
|
// Make sure target ko is from this event
|
||||||
target.effects.clear();
|
target.effects.clear();
|
||||||
resolutions.push(Resolution::new(&source, &target).event(Event::Ko()).stages(EventStages::PostOnly));
|
resolutions.push(Resolution::new(&source, &target).event(Event::Ko()).stages(EventStages::PostOnly));
|
||||||
}
|
}
|
||||||
@ -505,7 +506,7 @@ pub enum Event {
|
|||||||
AoeSkill { skill: Skill },
|
AoeSkill { skill: Skill },
|
||||||
Skill { skill: Skill },
|
Skill { skill: Skill },
|
||||||
Effect { skill: Skill, effect: Effect, duration: u8, construct_effects: Vec<ConstructEffect> },
|
Effect { skill: Skill, effect: Effect, duration: u8, construct_effects: Vec<ConstructEffect> },
|
||||||
Removal { effect: Effect, construct_effects: Vec<ConstructEffect> },
|
Removal { skill: Skill, effect: Option<Effect>, construct_effects: Vec<ConstructEffect> },
|
||||||
TargetKo { skill: Skill },
|
TargetKo { skill: Skill },
|
||||||
// skill not necessary but makes it neater as all events are arrays in js
|
// skill not necessary but makes it neater as all events are arrays in js
|
||||||
Ko (),
|
Ko (),
|
||||||
@ -1022,6 +1023,14 @@ impl Skill {
|
|||||||
meta: Some(EffectMeta::Skill(Skill::TriageTickPlus)), tick: None}],
|
meta: Some(EffectMeta::Skill(Skill::TriageTickPlus)), tick: None}],
|
||||||
Skill::TriagePlusPlus => vec![ConstructEffect {effect: Effect::Triage, duration: 4,
|
Skill::TriagePlusPlus => vec![ConstructEffect {effect: Effect::Triage, duration: 4,
|
||||||
meta: Some(EffectMeta::Skill(Skill::TriageTickPlusPlus)), tick: None}],
|
meta: Some(EffectMeta::Skill(Skill::TriageTickPlusPlus)), tick: None}],
|
||||||
|
|
||||||
|
Skill::Purify => vec![ConstructEffect { effect: Effect::Pure, duration: 2,
|
||||||
|
meta: Some(EffectMeta::Multiplier(150)), tick: None}],
|
||||||
|
Skill::PurifyPlus => vec![ConstructEffect { effect: Effect::Pure, duration: 2,
|
||||||
|
meta: Some(EffectMeta::Multiplier(175)), tick: None}],
|
||||||
|
Skill::PurifyPlusPlus => vec![ConstructEffect { effect: Effect::Pure, duration: 2,
|
||||||
|
meta: Some(EffectMeta::Multiplier(200)), tick: None}],
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
panic!("{:?} no skill effect", self);
|
panic!("{:?} no skill effect", self);
|
||||||
},
|
},
|
||||||
@ -1630,7 +1639,7 @@ fn electrocute(source: &mut Construct, target: &mut Construct, mut results: Reso
|
|||||||
Some(eff) => {
|
Some(eff) => {
|
||||||
let ce = source.effects.remove(eff);
|
let ce = source.effects.remove(eff);
|
||||||
results.push(Resolution::new(source, source)
|
results.push(Resolution::new(source, source)
|
||||||
.event(Event::Removal { effect: ce.effect, construct_effects: source.effects.clone() })
|
.event(Event::Removal { skill, effect: Some(ce.effect), construct_effects: source.effects.clone() })
|
||||||
.stages(EventStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
}
|
}
|
||||||
None => ()
|
None => ()
|
||||||
@ -1701,7 +1710,7 @@ fn absorption(source: &mut Construct, target: &mut Construct, mut results: Resol
|
|||||||
let ce = target.effects.remove(absorb_index);
|
let ce = target.effects.remove(absorb_index);
|
||||||
|
|
||||||
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 { skill, effect: Some(ce.effect), construct_effects: target.effects.clone() })
|
||||||
.stages(EventStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
return results;;
|
return results;;
|
||||||
}
|
}
|
||||||
@ -1816,58 +1825,33 @@ fn silence(source: &mut Construct, target: &mut Construct, mut results: Resoluti
|
|||||||
|
|
||||||
fn purge(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn purge(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
results.push(Resolution::new(source, target).event(Event::Skill { skill }).stages(EventStages::StartEnd));
|
results.push(Resolution::new(source, target).event(Event::Skill { skill }).stages(EventStages::StartEnd));
|
||||||
while let Some(i) = target.effects
|
if target.effects.len() > 0 {
|
||||||
.iter()
|
target.effects.clear();
|
||||||
.position(|ce| {
|
|
||||||
if let Some(c) = ce.effect.colour() {
|
|
||||||
c == Colour::Green
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
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 { skill, effect: None, construct_effects: target.effects.clone() })
|
||||||
.stages(EventStages::PostOnly));
|
.stages(EventStages::PostOnly));
|
||||||
}
|
}
|
||||||
|
|
||||||
let effect = skill.effect()[0];
|
let effect = skill.effect()[0];
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, effect)).stages(EventStages::PostOnly));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, effect)).stages(EventStages::PostOnly));
|
||||||
|
|
||||||
/*let mut turns = 1;
|
|
||||||
for cs in target.skills.iter_mut() {
|
|
||||||
if Effect::Purge.disables_skill(cs.skill) {
|
|
||||||
turns += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if turns > 1 {
|
|
||||||
effect.duration = effect.duration * turns;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn purify(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn purify(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
results.push(Resolution::new(source, target).event(Event::Skill { skill }).stages(EventStages::StartEnd));
|
results.push(Resolution::new(source, target).event(Event::Skill { skill }).stages(EventStages::StartEnd));
|
||||||
let amount = source.green_power().pct(skill.multiplier());
|
if target.effects.len() > 0 {
|
||||||
while let Some(i) = target.effects
|
let amount = source.green_power().pct(skill.multiplier().saturating_mul(target.effects.len() as u64));
|
||||||
.iter()
|
target.effects.clear();
|
||||||
.position(|ce| {
|
|
||||||
if let Some(c) = ce.effect.colour() {
|
|
||||||
[Colour::Red, Colour::Blue].contains(&c)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
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 { skill, effect: None, construct_effects: target.effects.clone() })
|
||||||
.stages(EventStages::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(EventStages::PostOnly)));
|
.for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly)));
|
||||||
}
|
}
|
||||||
|
let effect = skill.effect()[0];
|
||||||
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, effect)).stages(EventStages::PostOnly));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ impl Vbox {
|
|||||||
Vbox {
|
Vbox {
|
||||||
free: vec![vec![], vec![], vec![]],
|
free: vec![vec![], vec![], vec![]],
|
||||||
bound: starting_items,
|
bound: starting_items,
|
||||||
bits: 18,
|
bits: 30,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user