Merge tag '1.8.0' into develop
1.8.0
This commit is contained in:
commit
d1b9882231
47
CHANGELOG.md
47
CHANGELOG.md
@ -2,6 +2,53 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [1.8.0] - 2019-10-31
|
||||||
|
# Added
|
||||||
|
- Drag and drop for vbox interactions can be used instead of single click / double click
|
||||||
|
|
||||||
|
- Base white items and be directly equipped from vbox rather than going through the inventory
|
||||||
|
- Useful if you want to equip an item without further combining with colours
|
||||||
|
|
||||||
|
- You can swap skills and specs between constructs without using the inventory
|
||||||
|
|
||||||
|
# Changed
|
||||||
|
|
||||||
|
- Construct life changed
|
||||||
|
- You now start with 800 green life (down from 950)
|
||||||
|
- You now start with 125 red life and blue life (up from 0)
|
||||||
|
|
||||||
|
- Game phase layout
|
||||||
|
- Enemy team effects appear under your construct instead of next to it
|
||||||
|
- Game phase constructs line up symmetrically now
|
||||||
|
|
||||||
|
- Mobile
|
||||||
|
- Tutorial is disabled for mobile view
|
||||||
|
- Landscape is now default view
|
||||||
|
- Vbox phase everything is now in one view
|
||||||
|
- Game constructs and animations are much larger in mobile view
|
||||||
|
|
||||||
|
- Amplify
|
||||||
|
Now increases green power
|
||||||
|
|
||||||
|
- Absorb
|
||||||
|
- Reduced duration and cooldown from 2T -> 1T (Absorption duration unchanged)
|
||||||
|
- Absorption damage is now based on all damage taken (previously only green damage taken)
|
||||||
|
- Now recharges blue life based on 95 / 120 / 155 blue power
|
||||||
|
|
||||||
|
- Banish
|
||||||
|
Reduced cooldown to 1T
|
||||||
|
|
||||||
|
- Decay
|
||||||
|
Removed cooldown
|
||||||
|
|
||||||
|
- Haste / Hybrid
|
||||||
|
Fixed issue when hybridblast and hastestrike wouldn't trigger from upgraded + skills
|
||||||
|
|
||||||
|
- Intercept
|
||||||
|
- Reduced duration to 1T down from 2T
|
||||||
|
- Reduced cooldown to 1T down from 2T
|
||||||
|
|
||||||
|
|
||||||
## [1.7.0] - 2019-10-31
|
## [1.7.0] - 2019-10-31
|
||||||
# Added
|
# Added
|
||||||
- Step by step tutorial
|
- Step by step tutorial
|
||||||
|
|||||||
13
WORKLOG.md
13
WORKLOG.md
@ -4,16 +4,7 @@
|
|||||||
*PRODUCTION*
|
*PRODUCTION*
|
||||||
|
|
||||||
* can't reset password without knowing password =\
|
* can't reset password without knowing password =\
|
||||||
|
* ws gzip encoding
|
||||||
* mobile
|
|
||||||
- force to landscape view and try make everything fit
|
|
||||||
OR
|
|
||||||
- 2 pages vbox / equip
|
|
||||||
- vbox page as current with equip button at bottom
|
|
||||||
- equip page with inventory and all 3 construct avatars
|
|
||||||
- click one of the avatars to expand out skill / spec slots
|
|
||||||
- show the info pane at the bottom or as an overlay
|
|
||||||
|
|
||||||
|
|
||||||
* mobile info page
|
* mobile info page
|
||||||
|
|
||||||
@ -36,8 +27,6 @@
|
|||||||
- Strike + SpeedRR -> StrikeSpeed (strike has Y% more speed)
|
- Strike + SpeedRR -> StrikeSpeed (strike has Y% more speed)
|
||||||
- Strike + LifeRR -> StrikeLife (Strike recharges X% of damage as red life)
|
- Strike + LifeRR -> StrikeLife (Strike recharges X% of damage as red life)
|
||||||
|
|
||||||
* move item from one construct to another
|
|
||||||
|
|
||||||
* ACP
|
* ACP
|
||||||
* essential
|
* essential
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.7.1",
|
"version": "1.8.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 9.6 KiB |
2593
client/assets/rotate.svg
Normal file
2593
client/assets/rotate.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 96 KiB |
@ -4,7 +4,7 @@
|
|||||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
padding-right: 2em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
|||||||
@ -169,3 +169,15 @@ button {
|
|||||||
color: @green;
|
color: @green;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes rb-text {
|
||||||
|
0% {
|
||||||
|
color: @red;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
color: @white;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
color: @blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -96,6 +96,20 @@ aside {
|
|||||||
border-color: forestgreen;
|
border-color: forestgreen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all green
|
||||||
|
// &:enabled {
|
||||||
|
// background: forestgreen;
|
||||||
|
// color: black;
|
||||||
|
// border-color: forestgreen;
|
||||||
|
|
||||||
|
// &:hover {
|
||||||
|
// color: forestgreen;
|
||||||
|
// border-color: forestgreen;
|
||||||
|
// background: 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-page-ctrl {
|
.team-page-ctrl {
|
||||||
|
|||||||
@ -10,6 +10,10 @@
|
|||||||
// "opponent"
|
// "opponent"
|
||||||
// "target "
|
// "target "
|
||||||
// "player ";
|
// "player ";
|
||||||
|
|
||||||
|
.skill-description {
|
||||||
|
font-size: 75%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.game .team, .faceoff .team {
|
.game .team, .faceoff .team {
|
||||||
@ -43,8 +47,11 @@
|
|||||||
|
|
||||||
.game-construct {
|
.game-construct {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
grid-template-columns: 1fr 2fr;
|
grid-template-rows: 2fr min-content;
|
||||||
grid-template-rows: 1fr;
|
grid-template-rows: 1fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"right"
|
||||||
|
"left";
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -79,12 +86,16 @@
|
|||||||
justify-items: center;
|
justify-items: center;
|
||||||
|
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: min-content 1fr;
|
grid-template-rows: 1fr 2fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"left"
|
||||||
|
"right";
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
||||||
|
grid-area: left;
|
||||||
grid-template-columns: 1fr 2fr;
|
grid-template-columns: 1fr 2fr;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"skills effects";
|
"skills effects";
|
||||||
@ -92,6 +103,7 @@
|
|||||||
|
|
||||||
.right {
|
.right {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
grid-area: right;
|
||||||
grid-template-rows: minmax(min-content, 1fr) min-content min-content;
|
grid-template-rows: minmax(min-content, 1fr) min-content min-content;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"avatar"
|
"avatar"
|
||||||
@ -121,6 +133,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.skills {
|
.skills {
|
||||||
|
z-index: 2;
|
||||||
button {
|
button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
@ -132,6 +145,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.effects {
|
.effects {
|
||||||
|
z-index: 2;
|
||||||
grid-area: effects;
|
grid-area: effects;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -261,14 +275,6 @@
|
|||||||
color: #a52a2a;
|
color: #a52a2a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.red-damage text {
|
|
||||||
fill: #a52a2a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.red-damage .stats {
|
|
||||||
/*border-top: 1px solid #a52a2a;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-construct.blue-damage {
|
.game-construct.blue-damage {
|
||||||
color: #3050f8;
|
color: #3050f8;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@ -278,13 +284,6 @@
|
|||||||
color: #3050f8;
|
color: #3050f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.blue-damage text {
|
|
||||||
fill: #3050f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blue-damage .stats {
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-construct.green-damage {
|
.game-construct.green-damage {
|
||||||
color: #1FF01F;
|
color: #1FF01F;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@ -294,31 +293,8 @@
|
|||||||
color: #1FF01F;
|
color: #1FF01F;
|
||||||
}
|
}
|
||||||
|
|
||||||
.green-damage text {
|
.game-construct.rb-damage {
|
||||||
fill: #1FF01F;
|
animation: rb-text 1s cubic-bezier(0.5, 0, 0.5, 1) 0s infinite;
|
||||||
}
|
|
||||||
|
|
||||||
.green-damage .stats {
|
|
||||||
/*border-top: 1px solid #1FF01F;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-construct.purple-damage {
|
|
||||||
/* filter: drop-shadow(0 0 0.2em purple);
|
|
||||||
*/ color: purple;
|
|
||||||
border-color: purple;
|
|
||||||
}
|
|
||||||
|
|
||||||
.purple-damage button {
|
|
||||||
border: 1px solid purple;
|
|
||||||
color: purple;
|
|
||||||
}
|
|
||||||
|
|
||||||
.purple-damage text {
|
|
||||||
fill: purple;
|
|
||||||
}
|
|
||||||
|
|
||||||
.purple-damage .stats {
|
|
||||||
border-top: 1px solid purple;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.game .img, .faceoff .img {
|
.game .img, .faceoff .img {
|
||||||
|
|||||||
@ -9,10 +9,6 @@
|
|||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"vbox info"
|
"vbox info"
|
||||||
"constructs constructs";
|
"constructs constructs";
|
||||||
|
|
||||||
hr {
|
|
||||||
grid-area: rule;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1920px) {
|
@media (max-width: 1920px) {
|
||||||
@ -88,65 +84,6 @@
|
|||||||
border-right-width: 0;
|
border-right-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* VBOX */
|
|
||||||
.vbox {
|
|
||||||
align-content: space-between;
|
|
||||||
grid-area: vbox;
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: min-content min-content min-content;
|
|
||||||
grid-template-columns: 1fr min-content 1fr;
|
|
||||||
grid-template-areas:
|
|
||||||
"vbox varrow inventory"
|
|
||||||
"vbox varrow combiner";
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-inventory {
|
|
||||||
grid-area: inventory;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-combiner {
|
|
||||||
grid-area: combiner;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-arrow, .vbox-arrow-mobile {
|
|
||||||
display: flex;
|
|
||||||
justify-content:center;
|
|
||||||
align-content:center;
|
|
||||||
flex-direction:column;
|
|
||||||
|
|
||||||
margin: 1em 0.25em 0 0.25em;
|
|
||||||
grid-area: varrow;
|
|
||||||
font-size: 2em;
|
|
||||||
color: @gray-hint;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-combiner button {
|
|
||||||
flex: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.vbox-hdr {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-hdr h3 {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vbox-hdr .bits {
|
|
||||||
font-size: 2em;
|
|
||||||
line-height: 1em;
|
|
||||||
animation: bits 1s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.arrow {
|
|
||||||
grid-area: arrow;
|
|
||||||
color: @gray-hint;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes action {
|
@keyframes action {
|
||||||
0% {
|
0% {
|
||||||
color: palegoldenrod;
|
color: palegoldenrod;
|
||||||
@ -195,6 +132,7 @@
|
|||||||
grid-area: skills;
|
grid-area: skills;
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
margin-bottom: 0.75em;
|
margin-bottom: 0.75em;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
@ -212,6 +150,7 @@
|
|||||||
grid-area: specs;
|
grid-area: specs;
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
margin-bottom: 0.75em;
|
margin-bottom: 0.75em;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
|||||||
@ -142,6 +142,19 @@ section {
|
|||||||
border-color: forestgreen;
|
border-color: forestgreen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // all green
|
||||||
|
// button.ready:enabled {
|
||||||
|
// background: forestgreen;
|
||||||
|
// color: black;
|
||||||
|
// border-color: forestgreen;
|
||||||
|
|
||||||
|
// &:hover {
|
||||||
|
// color: forestgreen;
|
||||||
|
// border-color: forestgreen;
|
||||||
|
// background: 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -309,6 +309,7 @@ li {
|
|||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
z-index: 0;
|
||||||
// pointer-events: none;
|
// pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,3 +318,28 @@ li {
|
|||||||
height: 1px;
|
height: 1px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#rotate {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
z-index: 1000;
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-image: url("./../rotate.svg");
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,29 +7,29 @@
|
|||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
|
|
||||||
.menu {
|
|
||||||
.logo {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.team {
|
|
||||||
height: 20em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.instance {
|
.instance {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: min-content 1fr;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
"vbox"
|
||||||
|
"constructs";
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
stroke-width: 1.25em;
|
stroke-width: 1.25em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.game {
|
.game {
|
||||||
|
|
||||||
.team, #targeting, .resolving-skill {
|
.team, #targeting, .resolving-skill {
|
||||||
width: calc(90% - 3em);
|
width: calc(90% - 3em);
|
||||||
}
|
}
|
||||||
|
|
||||||
.game-construct {
|
.game-construct {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: min-content 1fr;
|
||||||
|
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
grid-area: initial;
|
grid-area: initial;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -43,6 +43,51 @@
|
|||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.skills {
|
||||||
|
button[disabled] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.effects {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player {
|
||||||
|
.game-construct {
|
||||||
|
grid-template-areas:
|
||||||
|
"left"
|
||||||
|
"right";
|
||||||
|
|
||||||
|
.left {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: 1fr min-content;
|
||||||
|
grid-template-areas:
|
||||||
|
"skills"
|
||||||
|
"effects";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opponent {
|
||||||
|
.game-construct {
|
||||||
|
grid-template-rows: 2fr min-content;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"right"
|
||||||
|
"left";
|
||||||
|
|
||||||
|
.left {
|
||||||
|
grid-template-columns: min-content 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.instance-construct {
|
.instance-construct {
|
||||||
@ -62,10 +107,86 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.opponent {
|
aside {
|
||||||
.avatar {
|
button {
|
||||||
bottom: 0;
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// portrait menu
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
#mnml {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"main"
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
.list {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|
||||||
|
&.play {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.account {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
div {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-ctrl {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.options {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
|
||||||
|
button:not(:last-child) {
|
||||||
|
border: 2px solid #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.logo {
|
||||||
|
grid-column-end: span 2;
|
||||||
|
border: none;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.team {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
.construct {
|
||||||
|
height: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.news {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
.list {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -22,10 +22,6 @@
|
|||||||
grid-gap: 0.5em 1em;
|
grid-gap: 0.5em 1em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
|
||||||
button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vbox-btn {
|
.vbox-btn {
|
||||||
@ -73,6 +69,7 @@
|
|||||||
button {
|
button {
|
||||||
height: 4em;
|
height: 4em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
// text-transform: none;
|
// text-transform: none;
|
||||||
|
|
||||||
@ -108,3 +105,62 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* VBOX */
|
||||||
|
.vbox {
|
||||||
|
align-content: space-between;
|
||||||
|
grid-area: vbox;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: min-content min-content min-content;
|
||||||
|
grid-template-columns: 1fr min-content 1fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"vbox varrow inventory"
|
||||||
|
"vbox varrow combiner";
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-inventory {
|
||||||
|
grid-area: inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-combiner {
|
||||||
|
grid-area: combiner;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-arrow, .vbox-arrow-mobile {
|
||||||
|
display: flex;
|
||||||
|
justify-content:center;
|
||||||
|
align-content:center;
|
||||||
|
flex-direction:column;
|
||||||
|
|
||||||
|
margin: 1em 0.25em 0 0.25em;
|
||||||
|
grid-area: varrow;
|
||||||
|
font-size: 2em;
|
||||||
|
color: @gray-hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-combiner button {
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.vbox-hdr {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-hdr h3 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vbox-hdr .bits {
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: 1em;
|
||||||
|
animation: bits 1s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
grid-area: arrow;
|
||||||
|
color: @gray-hint;
|
||||||
|
}
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
<link href="https://fonts.googleapis.com/css?family=Jura" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Jura" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="assets/styles/normalize.css">
|
<link rel="stylesheet" href="assets/styles/normalize.css">
|
||||||
<link rel="stylesheet" href="assets/styles/skeleton.css">
|
<link rel="stylesheet" href="assets/styles/skeleton.css">
|
||||||
|
<link rel="icon" sizes="512x512" href="assets/icons/mnml.png">
|
||||||
|
<link rel="apple-touch-icon" href="assets/icons/mnml.png">
|
||||||
</head>
|
</head>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml",
|
"name": "MNML",
|
||||||
"description": "mnml pvp atbs",
|
"description": "abstract strategy",
|
||||||
"short_name": "mnml",
|
"short_name": "MNML",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "./assets/icons/mnml.png",
|
"src": "./assets/icons/mnml.png",
|
||||||
@ -15,7 +15,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": "/index.html",
|
"start_url": "/index.html",
|
||||||
"display": "fullscreen",
|
"display": "standalone",
|
||||||
|
"orientation": "landscape",
|
||||||
"theme_color": "#000000",
|
"theme_color": "#000000",
|
||||||
"background_color": "#000000"
|
"background_color": "#000000"
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.7.1",
|
"version": "1.8.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -160,7 +160,7 @@ function getText(resolution) {
|
|||||||
|
|
||||||
if (type === 'Recharge') {
|
if (type === 'Recharge') {
|
||||||
const { red, blue } = event;
|
const { red, blue } = event;
|
||||||
if (red > 0 && blue > 0) return { text: [`+${red}R +${blue}B`, ''], css: 'purple-damage' };
|
if (red > 0 && blue > 0) return { text: [`+${red}R +${blue}B`, ''], css: 'rb-damage' };
|
||||||
if (red > 0) return { text: [`+${red}R`, ''], css: 'red-damage' };
|
if (red > 0) return { text: [`+${red}R`, ''], css: 'red-damage' };
|
||||||
if (blue > 0) return { text: [`+${blue}B`, ''], css: 'blue-damage' };
|
if (blue > 0) return { text: [`+${blue}B`, ''], css: 'blue-damage' };
|
||||||
return nullText;
|
return nullText;
|
||||||
|
|||||||
@ -217,7 +217,10 @@ function Construct(props) {
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label onDragStart={specClick} key={i} draggable="true" onDragEnd={() => setItemUnequip([])}>
|
<label onDragStart={ev => {
|
||||||
|
ev.dataTransfer.setData('text', '');
|
||||||
|
specClick(ev);
|
||||||
|
}} key={i} draggable="true" onDragEnd={() => setItemUnequip([])}>
|
||||||
<button
|
<button
|
||||||
key={i}
|
key={i}
|
||||||
onClick={specClick}
|
onClick={specClick}
|
||||||
|
|||||||
@ -7,15 +7,26 @@ const Controls = require('./controls');
|
|||||||
const Footer = require('./footer');
|
const Footer = require('./footer');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
state => ({ showNav: state.showNav })
|
({ game, instance }) => ({ game, instance })
|
||||||
);
|
);
|
||||||
|
|
||||||
function Mnml(args) {
|
function Mnml(args) {
|
||||||
|
const {
|
||||||
|
game,
|
||||||
|
instance,
|
||||||
|
} = args;
|
||||||
|
|
||||||
|
const rotateClass = (game || instance) && window.innerWidth < window.innerHeight
|
||||||
|
? 'show'
|
||||||
|
: '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="mnml">
|
<div id="mnml">
|
||||||
<Main />
|
<Main />
|
||||||
<Controls />
|
<Controls />
|
||||||
<Footer />
|
<Footer />
|
||||||
|
<div id="rotate" class={rotateClass} >
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,10 +60,10 @@ function Scoreboard(args) {
|
|||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
const scoreText = () => {
|
const scoreText = () => {
|
||||||
if (player.score === 'Zero' || player.score === 'Lose') return [<span i={0}>▫</span>, <span i={1}>▫</span>, <span i={2}>▫</span>];
|
if (player.score === 'Zero' || player.score === 'Lose') return [<span i={0}>▫</span>, <span i={1}>▫</span>, <span i={2}>▫</span>];
|
||||||
if (player.score === 'One') return [<span i={0}>■</span>, <span i={1}>▫</span>, <span i={2}>▫</span>];
|
if (player.score === 'One') return [<span i={0}>■</span>, <span i={1}>▫</span>, <span i={2}>▫</span>];
|
||||||
if (player.score === 'Two') return [<span i={0}>■</span>, <span i={1}>■</span>, <span i={2}>▫</span>];
|
if (player.score === 'Two') return [<span i={0}>■</span>, <span i={1}>■</span>, <span i={2}>▫</span>];
|
||||||
if (player.score === 'Win') return [<span i={0}>■</span>, <span i={1}>■</span>, <span i={2}>■</span>];
|
if (player.score === 'Win') return [<span i={0}>■</span>, <span i={1}>■</span>, <span i={2}>■</span>];
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,7 @@ class TargetSvg extends Component {
|
|||||||
if (tutorialGame) {
|
if (tutorialGame) {
|
||||||
return (
|
return (
|
||||||
<div class="resolving-skill">
|
<div class="resolving-skill">
|
||||||
<h2> Select your skills, click on targets and then hit <b>ready</b>.</h2>
|
<h2> Select your skills, click on targets and then hit <b>READY</b>.</h2>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -177,7 +177,7 @@ class Vbox extends preact.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function availableBtn(v, group, index) {
|
function availableBtn(v, group, index) {
|
||||||
if (!v) return <button disabled class='empty' > </button>;
|
if (!v) return <button disabled class='empty' key={(group * 10) + index} > </button>;
|
||||||
const selected = vboxSelected[0] === group && vboxSelected[1] === index;
|
const selected = vboxSelected[0] === group && vboxSelected[1] === index;
|
||||||
|
|
||||||
// state not yet set in double click handler
|
// state not yet set in double click handler
|
||||||
@ -215,7 +215,11 @@ class Vbox extends preact.Component {
|
|||||||
const vboxObject = shapes[v] ? shapes[v]() : v;
|
const vboxObject = shapes[v] ? shapes[v]() : v;
|
||||||
return (
|
return (
|
||||||
<label draggable='true'
|
<label draggable='true'
|
||||||
onDragStart={ev => ev.dataTransfer.setData('text', '')}
|
onDragStart={ev => {
|
||||||
|
onClick(ev);
|
||||||
|
ev.dataTransfer.setData('text', '')
|
||||||
|
}}
|
||||||
|
key={group * 10 + index}
|
||||||
onDragEnd={clearVboxSelected}>
|
onDragEnd={clearVboxSelected}>
|
||||||
<button
|
<button
|
||||||
class={classes}
|
class={classes}
|
||||||
@ -275,7 +279,7 @@ class Vbox extends preact.Component {
|
|||||||
const inventoryHighlight = vboxSelecting || itemUnequip.length;
|
const inventoryHighlight = vboxSelecting || itemUnequip.length;
|
||||||
|
|
||||||
if (!v && v !== 0) {
|
if (!v && v !== 0) {
|
||||||
return <button disabled={!inventoryHighlight} class={inventoryHighlight ? 'receiving' : 'empty'} > </button>;
|
return <button key={i} disabled={!inventoryHighlight} class={inventoryHighlight ? 'receiving' : 'empty'} > </button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const combinerItems = combiner.map(j => vbox.bound[j]);
|
const combinerItems = combiner.map(j => vbox.bound[j]);
|
||||||
@ -293,29 +297,30 @@ class Vbox extends preact.Component {
|
|||||||
} return false;
|
} return false;
|
||||||
}) ? 'combo-border' : '';
|
}) ? 'combo-border' : '';
|
||||||
|
|
||||||
function onClick(e) {
|
function onClick(type) {
|
||||||
if (vboxSelecting) clearVboxSelected();
|
if (vboxSelecting) clearVboxSelected();
|
||||||
if (reclaiming) return sendVboxReclaim(i);
|
if (reclaiming) return sendVboxReclaim(i);
|
||||||
|
|
||||||
|
const combinerContainsIndex = combiner.indexOf(i) > -1;
|
||||||
// 4 things selected
|
// 4 things selected
|
||||||
if (combiner.length > 2) {
|
if (combiner.length > 2 && !combinerContainsIndex) {
|
||||||
setInfo(vbox.bound[i]);
|
setInfo(vbox.bound[i]);
|
||||||
return combinerChange([i]);
|
return combinerChange([i]);
|
||||||
}
|
}
|
||||||
// removing
|
// removing
|
||||||
const combinerIndex = combiner.indexOf(i);
|
if (combinerContainsIndex) {
|
||||||
if (combinerIndex > -1) {
|
if (type === 'click') {
|
||||||
|
return combinerChange(without(combiner, i));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
// return combinerChange(without(combiner, i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
combiner.push(i);
|
if (!comboHighlight && !combinerContainsIndex) {
|
||||||
|
|
||||||
if (!comboHighlight) {
|
|
||||||
setInfo(vbox.bound[i]);
|
setInfo(vbox.bound[i]);
|
||||||
return combinerChange([i]);
|
return combinerChange([i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
combiner.push(i);
|
||||||
return combinerChange(combiner);
|
return combinerChange(combiner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,16 +332,17 @@ class Vbox extends preact.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
|
key={i}
|
||||||
draggable='true'
|
draggable='true'
|
||||||
onDragStart={ev => ev.dataTransfer.setData('text', '')}
|
onDragStart={ev => {
|
||||||
onDragEnd={() => {
|
onClick('drag');
|
||||||
if (combiner.length === 1) combinerChange([]);
|
ev.dataTransfer.setData('text', '');
|
||||||
}}>
|
}}>
|
||||||
<button
|
<button
|
||||||
class={classes}
|
class={classes}
|
||||||
onMouseOver={e => vboxHover(e, v)}
|
onMouseOver={e => vboxHover(e, v)}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
onMouseDown={onClick}>
|
onMouseDown={() => onClick('click')}>
|
||||||
{invObject}
|
{invObject}
|
||||||
</button>
|
</button>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@ -12,7 +12,7 @@ const { tutorialVbox } = require('./tutorial.utils');
|
|||||||
|
|
||||||
function registerEvents(store) {
|
function registerEvents(store) {
|
||||||
function notify(msg) {
|
function notify(msg) {
|
||||||
if (Notification && Notification.permission === 'granted') {
|
if (window.Notification && window.Notification.permission === 'granted') {
|
||||||
const n = new Notification('MNML', {
|
const n = new Notification('MNML', {
|
||||||
body: msg,
|
body: msg,
|
||||||
tag: 'MNML',
|
tag: 'MNML',
|
||||||
@ -134,12 +134,12 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setAccount(account) {
|
function setAccount(account) {
|
||||||
if (account) {
|
if (account && process.env.NODE_ENV !== 'development') {
|
||||||
LogRocket.init('yh0dy3/mnml');
|
LogRocket.init('yh0dy3/mnml');
|
||||||
LogRocket.identify(account.id, account);
|
LogRocket.identify(account.id, account);
|
||||||
|
|
||||||
if (Notification) {
|
if (window.Notification) {
|
||||||
Notification.requestPermission();
|
window.Notification.requestPermission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +224,9 @@ function registerEvents(store) {
|
|||||||
if (v.phase === 'Finished') {
|
if (v.phase === 'Finished') {
|
||||||
ws.sendAccountInstances();
|
ws.sendAccountInstances();
|
||||||
}
|
}
|
||||||
if (localStorage.getItem('tutorial-complete')) {
|
|
||||||
|
// instance.mobile.less hides info at @media 1000
|
||||||
|
if (localStorage.getItem('tutorial-complete') || window.innerWidth <= 1100) {
|
||||||
store.dispatch(actions.setTutorial(null));
|
store.dispatch(actions.setTutorial(null));
|
||||||
} else if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) {
|
} else if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) {
|
||||||
tutorialVbox(player, store, tutorial);
|
tutorialVbox(player, store, tutorial);
|
||||||
|
|||||||
@ -318,8 +318,11 @@ 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',
|
||||||
@ -338,12 +341,21 @@ 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, 5000);
|
return setTimeout(connect, attempts * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function connect() {
|
function connect() {
|
||||||
|
|||||||
@ -199,13 +199,16 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tutorial === 8) {
|
if (tutorial === 8) {
|
||||||
|
if (window.innerWidth < 1000) {
|
||||||
|
return exit();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<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 />
|
||||||
Reclaim can be used to refund the cost of items in your inventory. </p>
|
Reclaim can be used to refund the cost of items in your inventory. </p>
|
||||||
<p>Click the <b>EXIT TUTORIAL</b> button to replace this section with more information.</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -213,10 +216,11 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const classes = tutorial === 8 ? 'focus' : '';
|
const classes = tutorial === 8 ? 'focus' : '';
|
||||||
|
const text = tutorial === 8 ? 'Continue' : 'Close Tutorial'
|
||||||
const exitTutorial = <button
|
const exitTutorial = <button
|
||||||
class={classes}
|
class={classes}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
onMouseDown={exit}> Exit Tutorial </button>;
|
onMouseDown={exit}> {text} </button>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='tutorial'>
|
<div class='tutorial'>
|
||||||
|
|||||||
@ -264,7 +264,7 @@ function effectInfo(i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (i.effect) {
|
switch (i.effect) {
|
||||||
case 'Amplify': return `Increases construct RedPower and BluePower by ${i.meta[1] - 100}%`;
|
case 'Amplify': return `Increases construct RedPower BluePower GreenPower 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}%`;
|
||||||
|
|||||||
@ -15,6 +15,12 @@ map $http_upgrade $connection_upgrade {
|
|||||||
server {
|
server {
|
||||||
server_name mnml.gg;
|
server_name mnml.gg;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
root /var/lib/mnml/public/current;
|
root /var/lib/mnml/public/current;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|||||||
@ -15,8 +15,14 @@ map $http_upgrade $connection_upgrade {
|
|||||||
server {
|
server {
|
||||||
server_name sixtysix.pro;
|
server_name sixtysix.pro;
|
||||||
|
|
||||||
auth_basic "who dis";
|
gzip on;
|
||||||
auth_basic_user_file /etc/mnml/htpasswd.users;
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
|
||||||
|
|
||||||
|
# auth_basic "who dis";
|
||||||
|
# auth_basic_user_file /etc/mnml/htpasswd.users;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
root /var/lib/mnml/public/current;
|
root /var/lib/mnml/public/current;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-ops",
|
"name": "mnml-ops",
|
||||||
"version": "1.7.1",
|
"version": "1.8.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mnml"
|
name = "mnml"
|
||||||
version = "1.7.1"
|
version = "1.8.0"
|
||||||
authors = ["ntr <ntr@smokestack.io>"]
|
authors = ["ntr <ntr@smokestack.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -220,11 +220,11 @@ impl Construct {
|
|||||||
account: id,
|
account: id,
|
||||||
img: Uuid::new_v4(),
|
img: Uuid::new_v4(),
|
||||||
red_power: ConstructStat { base: 320, value: 320, max: 320, stat: Stat::RedPower },
|
red_power: ConstructStat { base: 320, value: 320, max: 320, stat: Stat::RedPower },
|
||||||
red_life: ConstructStat { base: 0, value: 0, max: 0, stat: Stat::RedLife },
|
red_life: ConstructStat { base: 125, value: 125, max: 125, stat: Stat::RedLife },
|
||||||
blue_power: ConstructStat { base: 320, value: 320, max: 320, stat: Stat::BluePower },
|
blue_power: ConstructStat { base: 320, value: 320, max: 320, stat: Stat::BluePower },
|
||||||
blue_life: ConstructStat { base: 0, value: 0, max: 0, stat: Stat::BlueLife },
|
blue_life: ConstructStat { base: 125, value: 125, max: 125, stat: Stat::BlueLife },
|
||||||
green_power: ConstructStat { base: 300, value: 300, max: 300, stat: Stat::GreenPower },
|
green_power: ConstructStat { base: 300, value: 300, max: 300, stat: Stat::GreenPower },
|
||||||
green_life: ConstructStat { base: 950, value: 950, max: 950, stat: Stat::GreenLife },
|
green_life: ConstructStat { base: 800, value: 800, max: 800, stat: Stat::GreenLife },
|
||||||
speed: ConstructStat { base: 100, value: 100, max: 100, stat: Stat::Speed },
|
speed: ConstructStat { base: 100, value: 100, max: 100, stat: Stat::Speed },
|
||||||
// evasion: ConstructStat { base: 0, value: 0, max: 0, stat: Stat::Evasion },
|
// evasion: ConstructStat { base: 0, value: 0, max: 0, stat: Stat::Evasion },
|
||||||
skills: vec![],
|
skills: vec![],
|
||||||
|
|||||||
@ -105,7 +105,7 @@ impl Effect {
|
|||||||
|
|
||||||
Effect::Absorption => vec![Stat::RedPower, Stat::BluePower],
|
Effect::Absorption => vec![Stat::RedPower, Stat::BluePower],
|
||||||
|
|
||||||
Effect::Amplify => vec![Stat::RedPower, Stat::BluePower],
|
Effect::Amplify => vec![Stat::GreenPower, Stat::RedPower, Stat::BluePower],
|
||||||
Effect::Curse => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
Effect::Curse => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
||||||
|
|
||||||
Effect::Hybrid => vec![Stat::GreenPower],
|
Effect::Hybrid => vec![Stat::GreenPower],
|
||||||
|
|||||||
@ -1229,7 +1229,7 @@ mod tests {
|
|||||||
assert!(game.player_by_id(x_player.id).unwrap().constructs[0].is_stunned() == false);
|
assert!(game.player_by_id(x_player.id).unwrap().constructs[0].is_stunned() == false);
|
||||||
// riposte
|
// riposte
|
||||||
assert_eq!(game.player_by_id(y_player.id).unwrap().constructs[0].green_life(), (
|
assert_eq!(game.player_by_id(y_player.id).unwrap().constructs[0].green_life(), (
|
||||||
y_construct.green_life() - x_construct.red_power().pct(Skill::CounterAttack.multiplier())));
|
y_construct.green_life() + y_construct.red_life() - x_construct.red_power().pct(Skill::CounterAttack.multiplier())));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -302,7 +302,7 @@ pub fn smile(id: Uuid) -> Result<Uuid, Error> {
|
|||||||
// 100W 25H
|
// 100W 25H
|
||||||
let mouths = [
|
let mouths = [
|
||||||
("M50,100 L150,100", 1), // _
|
("M50,100 L150,100", 1), // _
|
||||||
("M50,75 L150,75 L150,100 L50,100 L50,75", 1), // box
|
("M50,75 L150,75 L125,100 L75,100 L50,75", 1), // D
|
||||||
("M50,75 L75,100 L100,75 L125,100 L150,75", 1), // w
|
("M50,75 L75,100 L100,75 L125,100 L150,75", 1), // w
|
||||||
("M50,75 L75,75 L75,87.5 M75,75 L125,75 L125,87.5 M125,75 L150,75", 1), // vamp
|
("M50,75 L75,75 L75,87.5 M75,75 L125,75 L125,87.5 M125,75 L150,75", 1), // vamp
|
||||||
("M50,75 L150,75 M50,75 L50,87.5 M75,75 L75,87.5 M100,75 L100,87.5 M125,75 L125,87.5 M150,75 L150,87.5", 1), // mm
|
("M50,75 L150,75 M50,75 L50,87.5 M75,75 L75,87.5 M100,75 L100,87.5 M125,75 L125,87.5 M150,75 L150,87.5", 1), // mm
|
||||||
|
|||||||
@ -712,14 +712,14 @@ 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 and BluePower by {:?}%. Lasts {:?}T.",
|
Item::AmplifyPlusPlus => format!("Increase RedPower BluePower GreenPower 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()),
|
||||||
|
|
||||||
Item::Banish|
|
Item::Banish|
|
||||||
Item::BanishPlus |
|
Item::BanishPlus |
|
||||||
Item::BanishPlusPlus => format!("Banish target for {:?}T.
|
Item::BanishPlusPlus => format!("Banish target for {:?}T.
|
||||||
Deal blue damage and red damage equal to {:?}% target red and blue life.
|
Deal {:?}% target RedLife and BlueLife as red and blue damage respectively.
|
||||||
Banished constructs are immune to all skills and effects.",
|
Banished constructs are immune to all skills and effects.",
|
||||||
self.into_skill().unwrap().effect()[0].get_duration(),
|
self.into_skill().unwrap().effect()[0].get_duration(),
|
||||||
self.into_skill().unwrap().multiplier()),
|
self.into_skill().unwrap().multiplier()),
|
||||||
@ -773,11 +773,12 @@ impl Item {
|
|||||||
Item::Absorb|
|
Item::Absorb|
|
||||||
Item::AbsorbPlus |
|
Item::AbsorbPlus |
|
||||||
Item::AbsorbPlusPlus => format!(
|
Item::AbsorbPlusPlus => format!(
|
||||||
"Gain Absorb for {:?}T. When attacked with Absorb you gain Absorption.
|
"Gain Absorb for {:?}T. Taking damage replaces Absorb with Absorption.
|
||||||
Absorption increases RedPower and BluePower based on Damage taken.
|
Absorption increases RedPower and BluePower based on damage taken.
|
||||||
Absorption lasts {:?}T.",
|
Absorption lasts {:?}T. Recharges BlueLife based on {:?}% BluePower.",
|
||||||
self.into_skill().unwrap().effect()[0].get_duration(),
|
self.into_skill().unwrap().effect()[0].get_duration(),
|
||||||
self.into_skill().unwrap().effect()[0].get_skill().unwrap().effect()[0].get_duration()),
|
self.into_skill().unwrap().effect()[0].get_skill().unwrap().effect()[0].get_duration(),
|
||||||
|
self.into_skill().unwrap().multiplier()),
|
||||||
|
|
||||||
Item::Haste|
|
Item::Haste|
|
||||||
Item::HastePlus |
|
Item::HastePlus |
|
||||||
|
|||||||
@ -89,10 +89,15 @@ pub fn resolve(skill: Skill, source: &mut Construct, target: &mut Construct, mut
|
|||||||
|
|
||||||
if source.affected(Effect::Haste) {
|
if source.affected(Effect::Haste) {
|
||||||
match skill {
|
match skill {
|
||||||
Skill::Attack |
|
Skill::Slay |
|
||||||
Skill::Slay|
|
Skill::SlayPlus |
|
||||||
Skill::Chaos|
|
Skill::SlayPlusPlus |
|
||||||
Skill::Strike=> {
|
Skill::Chaos |
|
||||||
|
Skill::ChaosPlus |
|
||||||
|
Skill::ChaosPlusPlus |
|
||||||
|
Skill::Strike |
|
||||||
|
Skill::StrikePlus |
|
||||||
|
Skill::StrikePlusPlus => {
|
||||||
let amount = source.speed().pct(Skill::HasteStrike.multiplier());
|
let amount = source.speed().pct(Skill::HasteStrike.multiplier());
|
||||||
target.deal_red_damage(Skill::HasteStrike, amount)
|
target.deal_red_damage(Skill::HasteStrike, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -105,8 +110,14 @@ pub fn resolve(skill: Skill, source: &mut Construct, target: &mut Construct, mut
|
|||||||
if source.affected(Effect::Hybrid) {
|
if source.affected(Effect::Hybrid) {
|
||||||
match skill {
|
match skill {
|
||||||
Skill::Blast|
|
Skill::Blast|
|
||||||
Skill::Chaos|
|
Skill::BlastPlus |
|
||||||
Skill::Siphon=> {
|
Skill::BlastPlusPlus |
|
||||||
|
Skill::Chaos |
|
||||||
|
Skill::ChaosPlus |
|
||||||
|
Skill::ChaosPlusPlus |
|
||||||
|
Skill::Siphon |
|
||||||
|
Skill::SiphonPlus |
|
||||||
|
Skill::SiphonPlusPlus => {
|
||||||
let amount = source.green_power().pct(Skill::HybridBlast.multiplier());
|
let amount = source.green_power().pct(Skill::HybridBlast.multiplier());
|
||||||
target.deal_blue_damage(Skill::HybridBlast, amount)
|
target.deal_blue_damage(Skill::HybridBlast, amount)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -293,7 +304,7 @@ fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) ->
|
|||||||
let mut target = game.construct_by_id(target.id).unwrap().clone();
|
let mut target = game.construct_by_id(target.id).unwrap().clone();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Damage { amount, skill, mitigation: _, colour: c } => {
|
Event::Damage { amount, skill, mitigation, colour: c } => {
|
||||||
if target.affected(Effect::Electric) && !skill.is_tick() {
|
if target.affected(Effect::Electric) && !skill.is_tick() {
|
||||||
let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
|
let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
|
||||||
.find(|e| e.effect == Effect::Electric).unwrap().clone();
|
.find(|e| e.effect == Effect::Electric).unwrap().clone();
|
||||||
@ -320,7 +331,7 @@ fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) ->
|
|||||||
.find(|e| e.effect == Effect::Absorb).unwrap().clone();
|
.find(|e| e.effect == Effect::Absorb).unwrap().clone();
|
||||||
match meta {
|
match meta {
|
||||||
Some(EffectMeta::Skill(s)) => {
|
Some(EffectMeta::Skill(s)) => {
|
||||||
resolutions = absorption(&mut source, &mut target, resolutions, skill, amount, s);
|
resolutions = absorption(&mut source, &mut target, resolutions, skill, amount + mitigation, s);
|
||||||
},
|
},
|
||||||
_ => panic!("no absorb skill"),
|
_ => panic!("no absorb skill"),
|
||||||
};
|
};
|
||||||
@ -834,6 +845,10 @@ impl Skill {
|
|||||||
|
|
||||||
Skill::HasteStrike => 60,
|
Skill::HasteStrike => 60,
|
||||||
|
|
||||||
|
Skill::Absorb=> 95,
|
||||||
|
Skill::AbsorbPlus => 120,
|
||||||
|
Skill::AbsorbPlusPlus => 155,
|
||||||
|
|
||||||
Skill::Intercept=> 80,
|
Skill::Intercept=> 80,
|
||||||
Skill::InterceptPlus => 110,
|
Skill::InterceptPlus => 110,
|
||||||
Skill::InterceptPlusPlus => 150,
|
Skill::InterceptPlusPlus => 150,
|
||||||
@ -911,11 +926,11 @@ impl Skill {
|
|||||||
Skill::HastePlusPlus => vec![ConstructEffect {effect: Effect::Haste, duration: 5,
|
Skill::HastePlusPlus => vec![ConstructEffect {effect: Effect::Haste, duration: 5,
|
||||||
meta: Some(EffectMeta::Multiplier(225)), tick: None }],
|
meta: Some(EffectMeta::Multiplier(225)), tick: None }],
|
||||||
|
|
||||||
Skill::Absorb => vec![ConstructEffect {effect: Effect::Absorb, duration: 2,
|
Skill::Absorb => vec![ConstructEffect {effect: Effect::Absorb, duration: 1,
|
||||||
meta: Some(EffectMeta::Skill(Skill::Absorption)), tick: None}],
|
meta: Some(EffectMeta::Skill(Skill::Absorption)), tick: None}],
|
||||||
Skill::AbsorbPlus => vec![ConstructEffect {effect: Effect::Absorb, duration: 3,
|
Skill::AbsorbPlus => vec![ConstructEffect {effect: Effect::Absorb, duration: 1,
|
||||||
meta: Some(EffectMeta::Skill(Skill::AbsorptionPlus)), tick: None}],
|
meta: Some(EffectMeta::Skill(Skill::AbsorptionPlus)), tick: None}],
|
||||||
Skill::AbsorbPlusPlus => vec![ConstructEffect {effect: Effect::Absorb, duration: 4,
|
Skill::AbsorbPlusPlus => vec![ConstructEffect {effect: Effect::Absorb, duration: 1,
|
||||||
meta: Some(EffectMeta::Skill(Skill::AbsorptionPlusPlus)), tick: None}],
|
meta: Some(EffectMeta::Skill(Skill::AbsorptionPlusPlus)), tick: None}],
|
||||||
|
|
||||||
Skill::Absorption => vec![ConstructEffect {effect: Effect::Absorption, duration: 3, meta: None, tick: None}],
|
Skill::Absorption => vec![ConstructEffect {effect: Effect::Absorption, duration: 3, meta: None, tick: None}],
|
||||||
@ -993,9 +1008,9 @@ impl Skill {
|
|||||||
meta: Some(EffectMeta::Skill(Skill::BashPlusPlus)), tick: None}],
|
meta: Some(EffectMeta::Skill(Skill::BashPlusPlus)), tick: None}],
|
||||||
Skill::Stun => vec![ConstructEffect {effect: Effect::Stun, duration: 2, meta: None, tick: None}],
|
Skill::Stun => vec![ConstructEffect {effect: Effect::Stun, duration: 2, meta: None, tick: None}],
|
||||||
|
|
||||||
Skill::Intercept => vec![ConstructEffect {effect: Effect::Intercept, duration: 2, meta: None, tick: None}],
|
Skill::Intercept => vec![ConstructEffect {effect: Effect::Intercept, duration: 1, meta: None, tick: None}],
|
||||||
Skill::InterceptPlus => vec![ConstructEffect {effect: Effect::Intercept, duration: 3, meta: None, tick: None}],
|
Skill::InterceptPlus => vec![ConstructEffect {effect: Effect::Intercept, duration: 1, meta: None, tick: None}],
|
||||||
Skill::InterceptPlusPlus => vec![ConstructEffect {effect: Effect::Intercept, duration: 4, meta: None, tick: None}],
|
Skill::InterceptPlusPlus => vec![ConstructEffect {effect: Effect::Intercept, duration: 1, meta: None, tick: None}],
|
||||||
|
|
||||||
Skill::Triage => vec![ConstructEffect {effect: Effect::Triage, duration: 2,
|
Skill::Triage => vec![ConstructEffect {effect: Effect::Triage, duration: 2,
|
||||||
meta: Some(EffectMeta::Skill(Skill::TriageTick)), tick: None}],
|
meta: Some(EffectMeta::Skill(Skill::TriageTick)), tick: None}],
|
||||||
@ -1062,9 +1077,11 @@ impl Skill {
|
|||||||
Skill::Invert=> Some(2),
|
Skill::Invert=> Some(2),
|
||||||
Skill::InvertPlus => Some(2),
|
Skill::InvertPlus => Some(2),
|
||||||
Skill::InvertPlusPlus => Some(2),
|
Skill::InvertPlusPlus => Some(2),
|
||||||
Skill::Decay=> Some(1), // dot
|
|
||||||
Skill::DecayPlus => Some(1),
|
Skill::Decay=> None, // dot
|
||||||
Skill::DecayPlusPlus => Some(1),
|
Skill::DecayPlus => None,
|
||||||
|
Skill::DecayPlusPlus => None,
|
||||||
|
|
||||||
Skill::Siphon|
|
Skill::Siphon|
|
||||||
Skill::SiphonPlus |
|
Skill::SiphonPlus |
|
||||||
Skill::SiphonPlusPlus => None,
|
Skill::SiphonPlusPlus => None,
|
||||||
@ -1091,7 +1108,7 @@ impl Skill {
|
|||||||
|
|
||||||
Skill::Banish |
|
Skill::Banish |
|
||||||
Skill::BanishPlus |
|
Skill::BanishPlus |
|
||||||
Skill::BanishPlusPlus => Some(2),
|
Skill::BanishPlusPlus => Some(1),
|
||||||
|
|
||||||
Skill::Haste=> Some(1),
|
Skill::Haste=> Some(1),
|
||||||
Skill::HastePlus => Some(1),
|
Skill::HastePlus => Some(1),
|
||||||
@ -1121,9 +1138,9 @@ impl Skill {
|
|||||||
Skill::SustainPlus |
|
Skill::SustainPlus |
|
||||||
Skill::SustainPlusPlus => Some(1),
|
Skill::SustainPlusPlus => Some(1),
|
||||||
|
|
||||||
Skill::Intercept=> Some(2),
|
Skill::Intercept=> Some(1),
|
||||||
Skill::InterceptPlus => Some(2),
|
Skill::InterceptPlus => Some(1),
|
||||||
Skill::InterceptPlusPlus => Some(2),
|
Skill::InterceptPlusPlus => Some(1),
|
||||||
|
|
||||||
Skill::Electrify |
|
Skill::Electrify |
|
||||||
Skill::ElectrifyPlus |
|
Skill::ElectrifyPlus |
|
||||||
@ -1675,6 +1692,19 @@ fn ruin(source: &mut Construct, target: &mut Construct, mut results: Resolutions
|
|||||||
|
|
||||||
fn absorb(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
fn absorb(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
|
||||||
results.push(Resolution::new(source, target).event(target.add_effect(skill, skill.effect()[0])));
|
results.push(Resolution::new(source, target).event(target.add_effect(skill, skill.effect()[0])));
|
||||||
|
let blue_amount = source.blue_power().pct(skill.multiplier());
|
||||||
|
let e = target.recharge(skill, 0, blue_amount);
|
||||||
|
let stages = match e {
|
||||||
|
Event::Recharge { red, blue, skill: _ } => {
|
||||||
|
if red > 0 || blue > 0 { EventStages::PostOnly }
|
||||||
|
else { EventStages::NoStages }
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!("no recharge event found {:?}", e);
|
||||||
|
EventStages::NoStages
|
||||||
|
}
|
||||||
|
};
|
||||||
|
results.push(Resolution::new(source, target).event(e).stages(stages));
|
||||||
return results;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1794,13 +1824,19 @@ fn link(source: &mut Construct, target: &mut Construct, mut results: Resolutions
|
|||||||
None => 0
|
None => 0
|
||||||
};
|
};
|
||||||
|
|
||||||
target.deal_blue_damage(skill, swap)
|
let link_events = target.deal_blue_damage(skill, swap);
|
||||||
.into_iter()
|
for e in link_events {
|
||||||
.for_each(|e| results.push(Resolution::new(source, target).event(e)));
|
match e {
|
||||||
|
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
|
||||||
source.deal_green_damage(skill, swap)
|
results.push(Resolution::new(source, target).event(e));
|
||||||
.into_iter()
|
let heal = source.deal_green_damage(skill, amount);
|
||||||
.for_each(|e| results.push(Resolution::new(source, source).event(e).stages(EventStages::PostOnly)));
|
for h in heal {
|
||||||
|
results.push(Resolution::new(source, source).event(h).stages(EventStages::PostOnly));
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_ => results.push(Resolution::new(source, target).event(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
results.push(Resolution::new(source, source)
|
results.push(Resolution::new(source, source)
|
||||||
.event(source.add_effect(skill, skill.effect()[0])).stages(EventStages::PostOnly));
|
.event(source.add_effect(skill, skill.effect()[0])).stages(EventStages::PostOnly));
|
||||||
@ -2076,6 +2112,7 @@ mod tests {
|
|||||||
x.blue_power.force(256);
|
x.blue_power.force(256);
|
||||||
x.green_power.force(220);
|
x.green_power.force(220);
|
||||||
x.green_life.force(1024);
|
x.green_life.force(1024);
|
||||||
|
y.blue_life.force(0);
|
||||||
x.green_life.reduce(512);
|
x.green_life.reduce(512);
|
||||||
|
|
||||||
let mut results = resolve(Skill::Siphon, &mut x, &mut y, vec![]);
|
let mut results = resolve(Skill::Siphon, &mut x, &mut y, vec![]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user