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.
|
||||
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
|
||||
# Added
|
||||
- Step by step tutorial
|
||||
|
||||
13
WORKLOG.md
13
WORKLOG.md
@ -4,16 +4,7 @@
|
||||
*PRODUCTION*
|
||||
|
||||
* can't reset password without knowing password =\
|
||||
|
||||
* 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
|
||||
|
||||
* ws gzip encoding
|
||||
|
||||
* mobile info page
|
||||
|
||||
@ -36,8 +27,6 @@
|
||||
- Strike + SpeedRR -> StrikeSpeed (strike has Y% more speed)
|
||||
- Strike + LifeRR -> StrikeLife (Strike recharges X% of damage as red life)
|
||||
|
||||
* move item from one construct to another
|
||||
|
||||
* ACP
|
||||
* essential
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.7.1",
|
||||
"version": "1.8.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"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;
|
||||
|
||||
div {
|
||||
padding-right: 2em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
button {
|
||||
|
||||
@ -169,3 +169,15 @@ button {
|
||||
color: @green;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rb-text {
|
||||
0% {
|
||||
color: @red;
|
||||
}
|
||||
50% {
|
||||
color: @white;
|
||||
}
|
||||
100% {
|
||||
color: @blue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,6 +96,20 @@ aside {
|
||||
border-color: forestgreen;
|
||||
}
|
||||
}
|
||||
|
||||
// all green
|
||||
// &:enabled {
|
||||
// background: forestgreen;
|
||||
// color: black;
|
||||
// border-color: forestgreen;
|
||||
|
||||
// &:hover {
|
||||
// color: forestgreen;
|
||||
// border-color: forestgreen;
|
||||
// background: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
.team-page-ctrl {
|
||||
|
||||
@ -10,6 +10,10 @@
|
||||
// "opponent"
|
||||
// "target "
|
||||
// "player ";
|
||||
|
||||
.skill-description {
|
||||
font-size: 75%;
|
||||
}
|
||||
}
|
||||
|
||||
.game .team, .faceoff .team {
|
||||
@ -43,8 +47,11 @@
|
||||
|
||||
.game-construct {
|
||||
align-items: flex-start;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
grid-template-rows: 2fr min-content;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-areas:
|
||||
"right"
|
||||
"left";
|
||||
|
||||
.right {
|
||||
height: 100%;
|
||||
@ -79,12 +86,16 @@
|
||||
justify-items: center;
|
||||
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: min-content 1fr;
|
||||
grid-template-rows: 1fr 2fr;
|
||||
grid-template-areas:
|
||||
"left"
|
||||
"right";
|
||||
|
||||
.left {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
|
||||
grid-area: left;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
grid-template-areas:
|
||||
"skills effects";
|
||||
@ -92,6 +103,7 @@
|
||||
|
||||
.right {
|
||||
display: grid;
|
||||
grid-area: right;
|
||||
grid-template-rows: minmax(min-content, 1fr) min-content min-content;
|
||||
grid-template-areas:
|
||||
"avatar"
|
||||
@ -121,6 +133,7 @@
|
||||
}
|
||||
|
||||
.skills {
|
||||
z-index: 2;
|
||||
button {
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
@ -132,6 +145,7 @@
|
||||
}
|
||||
|
||||
.effects {
|
||||
z-index: 2;
|
||||
grid-area: effects;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
@ -261,14 +275,6 @@
|
||||
color: #a52a2a;
|
||||
}
|
||||
|
||||
.red-damage text {
|
||||
fill: #a52a2a;
|
||||
}
|
||||
|
||||
.red-damage .stats {
|
||||
/*border-top: 1px solid #a52a2a;*/
|
||||
}
|
||||
|
||||
.game-construct.blue-damage {
|
||||
color: #3050f8;
|
||||
opacity: 1;
|
||||
@ -278,13 +284,6 @@
|
||||
color: #3050f8;
|
||||
}
|
||||
|
||||
.blue-damage text {
|
||||
fill: #3050f8;
|
||||
}
|
||||
|
||||
.blue-damage .stats {
|
||||
}
|
||||
|
||||
.game-construct.green-damage {
|
||||
color: #1FF01F;
|
||||
opacity: 1;
|
||||
@ -294,31 +293,8 @@
|
||||
color: #1FF01F;
|
||||
}
|
||||
|
||||
.green-damage text {
|
||||
fill: #1FF01F;
|
||||
}
|
||||
|
||||
.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-construct.rb-damage {
|
||||
animation: rb-text 1s cubic-bezier(0.5, 0, 0.5, 1) 0s infinite;
|
||||
}
|
||||
|
||||
.game .img, .faceoff .img {
|
||||
|
||||
@ -9,10 +9,6 @@
|
||||
grid-template-areas:
|
||||
"vbox info"
|
||||
"constructs constructs";
|
||||
|
||||
hr {
|
||||
grid-area: rule;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1920px) {
|
||||
@ -88,65 +84,6 @@
|
||||
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 {
|
||||
0% {
|
||||
color: palegoldenrod;
|
||||
@ -195,6 +132,7 @@
|
||||
grid-area: skills;
|
||||
padding: 0 0.5em;
|
||||
margin-bottom: 0.75em;
|
||||
z-index: 2;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
@ -212,6 +150,7 @@
|
||||
grid-area: specs;
|
||||
padding: 0 0.5em;
|
||||
margin-bottom: 0.75em;
|
||||
z-index: 2;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
|
||||
@ -142,6 +142,19 @@ section {
|
||||
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-repeat: no-repeat;
|
||||
background-position: center;
|
||||
z-index: 0;
|
||||
// pointer-events: none;
|
||||
}
|
||||
|
||||
@ -317,3 +318,28 @@ li {
|
||||
height: 1px;
|
||||
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;
|
||||
padding: 0.25em;
|
||||
|
||||
.menu {
|
||||
.logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.team {
|
||||
height: 20em;
|
||||
}
|
||||
}
|
||||
|
||||
.instance {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: min-content 1fr;
|
||||
|
||||
grid-template-areas:
|
||||
"vbox"
|
||||
"constructs";
|
||||
|
||||
svg {
|
||||
stroke-width: 1.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.game {
|
||||
|
||||
.team, #targeting, .resolving-skill {
|
||||
width: calc(90% - 3em);
|
||||
}
|
||||
|
||||
.game-construct {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: min-content 1fr;
|
||||
|
||||
|
||||
.avatar {
|
||||
grid-area: initial;
|
||||
position: absolute;
|
||||
@ -43,6 +43,51 @@
|
||||
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 {
|
||||
@ -62,10 +107,86 @@
|
||||
}
|
||||
}
|
||||
|
||||
.opponent {
|
||||
.avatar {
|
||||
bottom: 0;
|
||||
aside {
|
||||
button {
|
||||
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;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.vbox-btn {
|
||||
@ -73,6 +69,7 @@
|
||||
button {
|
||||
height: 4em;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
|
||||
// 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 rel="stylesheet" href="assets/styles/normalize.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>
|
||||
<body>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "mnml",
|
||||
"description": "mnml pvp atbs",
|
||||
"short_name": "mnml",
|
||||
"name": "MNML",
|
||||
"description": "abstract strategy",
|
||||
"short_name": "MNML",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./assets/icons/mnml.png",
|
||||
@ -15,7 +15,8 @@
|
||||
}
|
||||
],
|
||||
"start_url": "/index.html",
|
||||
"display": "fullscreen",
|
||||
"display": "standalone",
|
||||
"orientation": "landscape",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#000000"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-client",
|
||||
"version": "1.7.1",
|
||||
"version": "1.8.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -160,7 +160,7 @@ function getText(resolution) {
|
||||
|
||||
if (type === 'Recharge') {
|
||||
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 (blue > 0) return { text: [`+${blue}B`, ''], css: 'blue-damage' };
|
||||
return nullText;
|
||||
|
||||
@ -217,7 +217,10 @@ function Construct(props) {
|
||||
|
||||
|
||||
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
|
||||
key={i}
|
||||
onClick={specClick}
|
||||
|
||||
@ -7,15 +7,26 @@ const Controls = require('./controls');
|
||||
const Footer = require('./footer');
|
||||
|
||||
const addState = connect(
|
||||
state => ({ showNav: state.showNav })
|
||||
({ game, instance }) => ({ game, instance })
|
||||
);
|
||||
|
||||
function Mnml(args) {
|
||||
const {
|
||||
game,
|
||||
instance,
|
||||
} = args;
|
||||
|
||||
const rotateClass = (game || instance) && window.innerWidth < window.innerHeight
|
||||
? 'show'
|
||||
: '';
|
||||
|
||||
return (
|
||||
<div id="mnml">
|
||||
<Main />
|
||||
<Controls />
|
||||
<Footer />
|
||||
<div id="rotate" class={rotateClass} >
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -60,10 +60,10 @@ function Scoreboard(args) {
|
||||
} = args;
|
||||
|
||||
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 === '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 === 'Win') 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 === '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>];
|
||||
return '';
|
||||
};
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ class TargetSvg extends Component {
|
||||
if (tutorialGame) {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ class Vbox extends preact.Component {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// state not yet set in double click handler
|
||||
@ -215,7 +215,11 @@ class Vbox extends preact.Component {
|
||||
const vboxObject = shapes[v] ? shapes[v]() : v;
|
||||
return (
|
||||
<label draggable='true'
|
||||
onDragStart={ev => ev.dataTransfer.setData('text', '')}
|
||||
onDragStart={ev => {
|
||||
onClick(ev);
|
||||
ev.dataTransfer.setData('text', '')
|
||||
}}
|
||||
key={group * 10 + index}
|
||||
onDragEnd={clearVboxSelected}>
|
||||
<button
|
||||
class={classes}
|
||||
@ -275,7 +279,7 @@ class Vbox extends preact.Component {
|
||||
const inventoryHighlight = vboxSelecting || itemUnequip.length;
|
||||
|
||||
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]);
|
||||
@ -293,29 +297,30 @@ class Vbox extends preact.Component {
|
||||
} return false;
|
||||
}) ? 'combo-border' : '';
|
||||
|
||||
function onClick(e) {
|
||||
function onClick(type) {
|
||||
if (vboxSelecting) clearVboxSelected();
|
||||
if (reclaiming) return sendVboxReclaim(i);
|
||||
|
||||
const combinerContainsIndex = combiner.indexOf(i) > -1;
|
||||
// 4 things selected
|
||||
if (combiner.length > 2) {
|
||||
if (combiner.length > 2 && !combinerContainsIndex) {
|
||||
setInfo(vbox.bound[i]);
|
||||
return combinerChange([i]);
|
||||
}
|
||||
// removing
|
||||
const combinerIndex = combiner.indexOf(i);
|
||||
if (combinerIndex > -1) {
|
||||
if (combinerContainsIndex) {
|
||||
if (type === 'click') {
|
||||
return combinerChange(without(combiner, i));
|
||||
}
|
||||
return true;
|
||||
// return combinerChange(without(combiner, i));
|
||||
}
|
||||
|
||||
combiner.push(i);
|
||||
|
||||
if (!comboHighlight) {
|
||||
if (!comboHighlight && !combinerContainsIndex) {
|
||||
setInfo(vbox.bound[i]);
|
||||
return combinerChange([i]);
|
||||
}
|
||||
|
||||
combiner.push(i);
|
||||
return combinerChange(combiner);
|
||||
}
|
||||
|
||||
@ -327,16 +332,17 @@ class Vbox extends preact.Component {
|
||||
|
||||
return (
|
||||
<label
|
||||
key={i}
|
||||
draggable='true'
|
||||
onDragStart={ev => ev.dataTransfer.setData('text', '')}
|
||||
onDragEnd={() => {
|
||||
if (combiner.length === 1) combinerChange([]);
|
||||
onDragStart={ev => {
|
||||
onClick('drag');
|
||||
ev.dataTransfer.setData('text', '');
|
||||
}}>
|
||||
<button
|
||||
class={classes}
|
||||
onMouseOver={e => vboxHover(e, v)}
|
||||
onClick={e => e.stopPropagation()}
|
||||
onMouseDown={onClick}>
|
||||
onMouseDown={() => onClick('click')}>
|
||||
{invObject}
|
||||
</button>
|
||||
</label>
|
||||
|
||||
@ -12,7 +12,7 @@ const { tutorialVbox } = require('./tutorial.utils');
|
||||
|
||||
function registerEvents(store) {
|
||||
function notify(msg) {
|
||||
if (Notification && Notification.permission === 'granted') {
|
||||
if (window.Notification && window.Notification.permission === 'granted') {
|
||||
const n = new Notification('MNML', {
|
||||
body: msg,
|
||||
tag: 'MNML',
|
||||
@ -134,12 +134,12 @@ function registerEvents(store) {
|
||||
}
|
||||
|
||||
function setAccount(account) {
|
||||
if (account) {
|
||||
if (account && process.env.NODE_ENV !== 'development') {
|
||||
LogRocket.init('yh0dy3/mnml');
|
||||
LogRocket.identify(account.id, account);
|
||||
|
||||
if (Notification) {
|
||||
Notification.requestPermission();
|
||||
if (window.Notification) {
|
||||
window.Notification.requestPermission();
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,7 +224,9 @@ function registerEvents(store) {
|
||||
if (v.phase === 'Finished') {
|
||||
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));
|
||||
} else if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) {
|
||||
tutorialVbox(player, store, tutorial);
|
||||
|
||||
@ -318,8 +318,11 @@ function createSocket(events) {
|
||||
return handlers[msgType](params);
|
||||
}
|
||||
|
||||
let attempts = 1;
|
||||
|
||||
// Connection opened
|
||||
function onOpen() {
|
||||
attempts = 0;
|
||||
toast.info({
|
||||
message: 'connected',
|
||||
position: 'topRight',
|
||||
@ -338,12 +341,21 @@ function createSocket(events) {
|
||||
}
|
||||
|
||||
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);
|
||||
toast.warning({
|
||||
message: 'disconnected',
|
||||
position: 'topRight',
|
||||
});
|
||||
return setTimeout(connect, 5000);
|
||||
return setTimeout(connect, attempts * 1000);
|
||||
}
|
||||
|
||||
function connect() {
|
||||
|
||||
@ -199,13 +199,16 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
||||
}
|
||||
|
||||
if (tutorial === 8) {
|
||||
if (window.innerWidth < 1000) {
|
||||
return exit();
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Tutorial</h2>
|
||||
<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 />
|
||||
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>
|
||||
);
|
||||
}
|
||||
@ -213,10 +216,11 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {
|
||||
};
|
||||
|
||||
const classes = tutorial === 8 ? 'focus' : '';
|
||||
const text = tutorial === 8 ? 'Continue' : 'Close Tutorial'
|
||||
const exitTutorial = <button
|
||||
class={classes}
|
||||
onClick={e => e.stopPropagation()}
|
||||
onMouseDown={exit}> Exit Tutorial </button>;
|
||||
onMouseDown={exit}> {text} </button>;
|
||||
|
||||
return (
|
||||
<div class='tutorial'>
|
||||
|
||||
@ -264,7 +264,7 @@ function effectInfo(i) {
|
||||
}
|
||||
|
||||
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 '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}%`;
|
||||
|
||||
@ -15,6 +15,12 @@ map $http_upgrade $connection_upgrade {
|
||||
server {
|
||||
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 / {
|
||||
root /var/lib/mnml/public/current;
|
||||
index index.html;
|
||||
|
||||
@ -15,8 +15,14 @@ map $http_upgrade $connection_upgrade {
|
||||
server {
|
||||
server_name sixtysix.pro;
|
||||
|
||||
auth_basic "who dis";
|
||||
auth_basic_user_file /etc/mnml/htpasswd.users;
|
||||
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;
|
||||
|
||||
# auth_basic "who dis";
|
||||
# auth_basic_user_file /etc/mnml/htpasswd.users;
|
||||
|
||||
location / {
|
||||
root /var/lib/mnml/public/current;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mnml-ops",
|
||||
"version": "1.7.1",
|
||||
"version": "1.8.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mnml"
|
||||
version = "1.7.1"
|
||||
version = "1.8.0"
|
||||
authors = ["ntr <ntr@smokestack.io>"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -220,11 +220,11 @@ impl Construct {
|
||||
account: id,
|
||||
img: Uuid::new_v4(),
|
||||
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_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_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 },
|
||||
// evasion: ConstructStat { base: 0, value: 0, max: 0, stat: Stat::Evasion },
|
||||
skills: vec![],
|
||||
|
||||
@ -105,7 +105,7 @@ impl Effect {
|
||||
|
||||
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::Hybrid => vec![Stat::GreenPower],
|
||||
|
||||
@ -1229,7 +1229,7 @@ mod tests {
|
||||
assert!(game.player_by_id(x_player.id).unwrap().constructs[0].is_stunned() == false);
|
||||
// riposte
|
||||
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]
|
||||
|
||||
@ -302,7 +302,7 @@ pub fn smile(id: Uuid) -> Result<Uuid, Error> {
|
||||
// 100W 25H
|
||||
let mouths = [
|
||||
("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,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
|
||||
|
||||
@ -712,14 +712,14 @@ impl Item {
|
||||
// Skills <- need to move effect mulltipliers into skills
|
||||
Item::Amplify|
|
||||
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_duration()),
|
||||
|
||||
Item::Banish|
|
||||
Item::BanishPlus |
|
||||
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.",
|
||||
self.into_skill().unwrap().effect()[0].get_duration(),
|
||||
self.into_skill().unwrap().multiplier()),
|
||||
@ -773,11 +773,12 @@ impl Item {
|
||||
Item::Absorb|
|
||||
Item::AbsorbPlus |
|
||||
Item::AbsorbPlusPlus => format!(
|
||||
"Gain Absorb for {:?}T. When attacked with Absorb you gain Absorption.
|
||||
Absorption increases RedPower and BluePower based on Damage taken.
|
||||
Absorption lasts {:?}T.",
|
||||
"Gain Absorb for {:?}T. Taking damage replaces Absorb with Absorption.
|
||||
Absorption increases RedPower and BluePower based on damage taken.
|
||||
Absorption lasts {:?}T. Recharges BlueLife based on {:?}% BluePower.",
|
||||
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::HastePlus |
|
||||
|
||||
@ -89,10 +89,15 @@ pub fn resolve(skill: Skill, source: &mut Construct, target: &mut Construct, mut
|
||||
|
||||
if source.affected(Effect::Haste) {
|
||||
match skill {
|
||||
Skill::Attack |
|
||||
Skill::Slay |
|
||||
Skill::SlayPlus |
|
||||
Skill::SlayPlusPlus |
|
||||
Skill::Chaos |
|
||||
Skill::Strike=> {
|
||||
Skill::ChaosPlus |
|
||||
Skill::ChaosPlusPlus |
|
||||
Skill::Strike |
|
||||
Skill::StrikePlus |
|
||||
Skill::StrikePlusPlus => {
|
||||
let amount = source.speed().pct(Skill::HasteStrike.multiplier());
|
||||
target.deal_red_damage(Skill::HasteStrike, amount)
|
||||
.into_iter()
|
||||
@ -105,8 +110,14 @@ pub fn resolve(skill: Skill, source: &mut Construct, target: &mut Construct, mut
|
||||
if source.affected(Effect::Hybrid) {
|
||||
match skill {
|
||||
Skill::Blast|
|
||||
Skill::BlastPlus |
|
||||
Skill::BlastPlusPlus |
|
||||
Skill::Chaos |
|
||||
Skill::Siphon=> {
|
||||
Skill::ChaosPlus |
|
||||
Skill::ChaosPlusPlus |
|
||||
Skill::Siphon |
|
||||
Skill::SiphonPlus |
|
||||
Skill::SiphonPlusPlus => {
|
||||
let amount = source.green_power().pct(Skill::HybridBlast.multiplier());
|
||||
target.deal_blue_damage(Skill::HybridBlast, amount)
|
||||
.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();
|
||||
|
||||
match event {
|
||||
Event::Damage { amount, skill, mitigation: _, colour: c } => {
|
||||
Event::Damage { amount, skill, mitigation, colour: c } => {
|
||||
if target.affected(Effect::Electric) && !skill.is_tick() {
|
||||
let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
|
||||
.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();
|
||||
match meta {
|
||||
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"),
|
||||
};
|
||||
@ -834,6 +845,10 @@ impl Skill {
|
||||
|
||||
Skill::HasteStrike => 60,
|
||||
|
||||
Skill::Absorb=> 95,
|
||||
Skill::AbsorbPlus => 120,
|
||||
Skill::AbsorbPlusPlus => 155,
|
||||
|
||||
Skill::Intercept=> 80,
|
||||
Skill::InterceptPlus => 110,
|
||||
Skill::InterceptPlusPlus => 150,
|
||||
@ -911,11 +926,11 @@ impl Skill {
|
||||
Skill::HastePlusPlus => vec![ConstructEffect {effect: Effect::Haste, duration: 5,
|
||||
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}],
|
||||
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}],
|
||||
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}],
|
||||
|
||||
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}],
|
||||
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::InterceptPlus => vec![ConstructEffect {effect: Effect::Intercept, duration: 3, meta: None, tick: None}],
|
||||
Skill::InterceptPlusPlus => vec![ConstructEffect {effect: Effect::Intercept, duration: 4, 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: 1, 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,
|
||||
meta: Some(EffectMeta::Skill(Skill::TriageTick)), tick: None}],
|
||||
@ -1062,9 +1077,11 @@ impl Skill {
|
||||
Skill::Invert=> Some(2),
|
||||
Skill::InvertPlus => Some(2),
|
||||
Skill::InvertPlusPlus => Some(2),
|
||||
Skill::Decay=> Some(1), // dot
|
||||
Skill::DecayPlus => Some(1),
|
||||
Skill::DecayPlusPlus => Some(1),
|
||||
|
||||
Skill::Decay=> None, // dot
|
||||
Skill::DecayPlus => None,
|
||||
Skill::DecayPlusPlus => None,
|
||||
|
||||
Skill::Siphon|
|
||||
Skill::SiphonPlus |
|
||||
Skill::SiphonPlusPlus => None,
|
||||
@ -1091,7 +1108,7 @@ impl Skill {
|
||||
|
||||
Skill::Banish |
|
||||
Skill::BanishPlus |
|
||||
Skill::BanishPlusPlus => Some(2),
|
||||
Skill::BanishPlusPlus => Some(1),
|
||||
|
||||
Skill::Haste=> Some(1),
|
||||
Skill::HastePlus => Some(1),
|
||||
@ -1121,9 +1138,9 @@ impl Skill {
|
||||
Skill::SustainPlus |
|
||||
Skill::SustainPlusPlus => Some(1),
|
||||
|
||||
Skill::Intercept=> Some(2),
|
||||
Skill::InterceptPlus => Some(2),
|
||||
Skill::InterceptPlusPlus => Some(2),
|
||||
Skill::Intercept=> Some(1),
|
||||
Skill::InterceptPlus => Some(1),
|
||||
Skill::InterceptPlusPlus => Some(1),
|
||||
|
||||
Skill::Electrify |
|
||||
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 {
|
||||
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;;
|
||||
}
|
||||
|
||||
@ -1794,13 +1824,19 @@ fn link(source: &mut Construct, target: &mut Construct, mut results: Resolutions
|
||||
None => 0
|
||||
};
|
||||
|
||||
target.deal_blue_damage(skill, swap)
|
||||
.into_iter()
|
||||
.for_each(|e| results.push(Resolution::new(source, target).event(e)));
|
||||
|
||||
source.deal_green_damage(skill, swap)
|
||||
.into_iter()
|
||||
.for_each(|e| results.push(Resolution::new(source, source).event(e).stages(EventStages::PostOnly)));
|
||||
let link_events = target.deal_blue_damage(skill, swap);
|
||||
for e in link_events {
|
||||
match e {
|
||||
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
|
||||
results.push(Resolution::new(source, target).event(e));
|
||||
let heal = source.deal_green_damage(skill, amount);
|
||||
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)
|
||||
.event(source.add_effect(skill, skill.effect()[0])).stages(EventStages::PostOnly));
|
||||
@ -2076,6 +2112,7 @@ mod tests {
|
||||
x.blue_power.force(256);
|
||||
x.green_power.force(220);
|
||||
x.green_life.force(1024);
|
||||
y.blue_life.force(0);
|
||||
x.green_life.reduce(512);
|
||||
|
||||
let mut results = resolve(Skill::Siphon, &mut x, &mut y, vec![]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user