v1.5.5 - Rework tutorial and polishing
This commit is contained in:
parent
482a4990ba
commit
8c5e593ceb
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Binary file not shown.
|
@ -55,6 +55,35 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
@include S(height, 40px);
|
@include S(height, 40px);
|
||||||
|
|
||||||
|
@at-root html[data-tutorial-step="1_1_extractor"] &[data-id="miner"]:not(.selected),
|
||||||
|
html[data-tutorial-step="1_2_conveyor"] &[data-id="belt"]:not(.selected),
|
||||||
|
html[data-tutorial-step="2_1_place_cutter"] &[data-id="cutter"]:not(.selected),
|
||||||
|
html[data-tutorial-step="2_2_place_trash"] &[data-id="trash"]:not(.selected) {
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
|
||||||
|
& {
|
||||||
|
/* load-async */
|
||||||
|
background: uiResource("icons/tutorial_arrow.png") center center / contain no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include S(width, 25px);
|
||||||
|
@include S(height, 25px);
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 100%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
@include InlineAnimation(1s ease-in-out infinite) {
|
||||||
|
50% {
|
||||||
|
transform: translateX(-50%) translateY(20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
box-shadow: 0 0 D(10px) D(5px) rgba(74, 237, 134, 0.5) !important;
|
||||||
|
background: rgba(74, 237, 134, 0.5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
color: $accentColorDark;
|
color: $accentColorDark;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -32,12 +32,6 @@
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
transition: opacity 0.1s ease-out;
|
transition: opacity 0.1s ease-out;
|
||||||
&.hovered {
|
|
||||||
opacity: 10%;
|
|
||||||
.helperGif {
|
|
||||||
opacity: 0%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
|
@ -126,6 +126,7 @@
|
||||||
@include S(height, 40px);
|
@include S(height, 40px);
|
||||||
background: #171a23 center center / contain no-repeat;
|
background: #171a23 center center / contain no-repeat;
|
||||||
|
|
||||||
|
box-shadow: 0 D(3px) D(10px) rgba(96, 163, 136, 0.5);
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
|
||||||
|
@ -135,6 +136,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.94 !important;
|
||||||
|
}
|
||||||
|
|
||||||
> .discount {
|
> .discount {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@include S(top, -7px);
|
@include S(top, -7px);
|
||||||
|
|
|
@ -102,30 +102,6 @@ button,
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
/* Define a style which is only applied in horizontal mode */
|
|
||||||
@mixin HorizontalStyle {
|
|
||||||
@include AppendGlobal(".h") {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
/* Define a style which is only applied in vertical mode */
|
|
||||||
@mixin VerticalStyle {
|
|
||||||
@include AppendGlobal(".v") {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
/* Define a style which is only while the hardware keyboard is open */
|
|
||||||
@mixin AndroidHwKeyboardOpen {
|
|
||||||
@include AppendGlobal(".kb") {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
/* Automatically transforms the game state if a hardware keyboard is open */
|
/* Automatically transforms the game state if a hardware keyboard is open */
|
||||||
@mixin TransformToMatchKeyboard {
|
@mixin TransformToMatchKeyboard {
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
display: none;
|
display: none;
|
||||||
transform: translate(50%, 50%);
|
transform: translate(50%, 50%);
|
||||||
filter: blur(D(7px));
|
filter: blur(D(15px));
|
||||||
|
|
||||||
$opacity: 0.4;
|
$opacity: 0.4;
|
||||||
&.loaded {
|
&.loaded {
|
||||||
|
@ -81,34 +81,41 @@
|
||||||
|
|
||||||
.mainWrapper {
|
.mainWrapper {
|
||||||
@include S(padding, 0, 10px);
|
@include S(padding, 0, 10px);
|
||||||
|
@include S(margin-top, 15px);
|
||||||
align-items: start;
|
align-items: start;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
|
|
||||||
@include S(grid-column-gap, 10px);
|
@include S(grid-column-gap, 10px);
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
||||||
|
grid-template-rows: D(31px) 1fr D(93px);
|
||||||
|
|
||||||
&[data-columns="1"] {
|
&[data-columns="1"] {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
&[data-columns="2"] {
|
&[data-columns="2"] {
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: D(290px) 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.standaloneBanner {
|
.standaloneBanner {
|
||||||
background: rgba(12, 168, 93, 0.957);
|
background: transparent;
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
// box-shadow: 0 D(5px) D(15px) rgba(#000, 0.2);
|
||||||
|
@include S(width, 380px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@include S(padding, 15px);
|
@include S(padding, 0, 15px);
|
||||||
box-shadow: 0 D(5px) D(15px) rgba(#000, 0.2);
|
// backdrop-filter: blur(10px);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
font-weight: 700 !important;
|
font-weight: 700 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onlinePlayerCount {
|
.onlinePlayerCount {
|
||||||
color: #fff;
|
color: #333;
|
||||||
@include S(margin-top, 15px);
|
@include S(margin-top, 15px);
|
||||||
@include SuperSmallText;
|
@include SuperSmallText;
|
||||||
@include S(height, 15px);
|
@include S(height, 15px);
|
||||||
|
@ -118,15 +125,14 @@
|
||||||
h3 {
|
h3 {
|
||||||
@include Heading;
|
@include Heading;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@include S(margin-bottom, 20px);
|
@include S(margin-bottom, 10px);
|
||||||
display: none;
|
text-align: center;
|
||||||
text-transform: uppercase;
|
color: #44484f;
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@include Text;
|
@include Text;
|
||||||
color: #fff;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
@ -139,7 +145,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.playtimeDisclaimer {
|
.playtimeDisclaimer {
|
||||||
color: #fff;
|
color: #333;
|
||||||
@include S(margin-top, 15px);
|
@include S(margin-top, 15px);
|
||||||
@include SuperSmallText;
|
@include SuperSmallText;
|
||||||
}
|
}
|
||||||
|
@ -162,6 +168,7 @@
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
|
||||||
|
box-shadow: 0 D(3px) D(10px) rgba(96, 163, 136, 0.5);
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
|
@ -190,6 +197,151 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.points {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
width: 100%;
|
||||||
|
@include S(grid-gap, 5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.point {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: #{D(27px)} auto;
|
||||||
|
grid-template-rows: D(11px) D(10px);
|
||||||
|
background: #fff #{D(10px)} center / #{D(17px)} no-repeat;
|
||||||
|
@include S(grid-row-gap, 3px);
|
||||||
|
align-items: center;
|
||||||
|
@include S(padding, 6px);
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
|
||||||
|
box-shadow: 0 D(5px) D(10px) rgba(#000, 0.2);
|
||||||
|
|
||||||
|
> strong {
|
||||||
|
grid-column: 2 / 3;
|
||||||
|
grid-row: 1 / 2;
|
||||||
|
@include PlainText;
|
||||||
|
@include S(font-size, 12px);
|
||||||
|
line-height: 0.8em;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
align-self: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
> p {
|
||||||
|
grid-column: 2 / 3;
|
||||||
|
grid-row: 2 / 3;
|
||||||
|
@include SuperSmallText;
|
||||||
|
white-space: nowrap;
|
||||||
|
@include BreakText;
|
||||||
|
@include S(font-size, 8px);
|
||||||
|
line-height: 1em;
|
||||||
|
align-self: start;
|
||||||
|
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.levels {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_new_levels.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #f13555;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.upgrades {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_upgrades.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #8a00ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.buildings {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_buildings.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #3fce8b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wires {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_wires.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #ef2fdb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.markers {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_markers.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #4294ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mods {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_mods.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #8a00ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.savegames {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_savegames.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #ff9500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.darkmode {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_dark_mode.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #292c32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.support {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_support.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #e72d2d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.achievements {
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/advantage_achievements.png");
|
||||||
|
}
|
||||||
|
> strong {
|
||||||
|
color: #ffac0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,8 +355,8 @@
|
||||||
@include S(padding-top, 20px);
|
@include S(padding-top, 20px);
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@include S(width, 710px / 2.2);
|
@include S(width, 710px / 2.5);
|
||||||
@include S(height, 180 / 2.2px);
|
@include S(height, 180px / 2.5);
|
||||||
}
|
}
|
||||||
position: relative;
|
position: relative;
|
||||||
@include S(left, -8px);
|
@include S(left, -8px);
|
||||||
|
@ -243,11 +395,12 @@
|
||||||
.sideContainer {
|
.sideContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@include S(width, 300px);
|
width: 100%;
|
||||||
|
grid-row: 1 / 4;
|
||||||
|
grid-column: 2 / 3;
|
||||||
|
|
||||||
.standaloneBanner {
|
.standaloneBanner {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@include S(margin-bottom, 10px);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +411,6 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: $colorBlueBright;
|
background: $colorBlueBright;
|
||||||
grid-row: 1 / 2;
|
grid-row: 1 / 2;
|
||||||
grid-column: 2 / 3;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
@include S(padding, 20px);
|
@include S(padding, 20px);
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
@ -324,7 +476,6 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
grid-row: 1 / 2;
|
grid-row: 1 / 2;
|
||||||
grid-column: 2 / 3;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
@ -418,18 +569,24 @@
|
||||||
.mainContainer {
|
.mainContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
grid-row: 1 / 2;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: #fafafa;
|
background: rgba(#fff, 0.9);
|
||||||
@include S(padding, 20px);
|
@include S(padding, 15px);
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
// border: #{D(2px)} solid rgba(0, 10, 20, 0.1);
|
|
||||||
|
|
||||||
box-shadow: 0 D(5px) D(15px) rgba(#000, 0.2);
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
box-shadow: 0 D(5px) D(15px) rgba(#000, 0.2);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
grid-row: 1 / 4;
|
||||||
|
grid-column: 1 / 2;
|
||||||
|
|
||||||
|
// &[data-savegames="0"] {
|
||||||
|
// grid-row: 2 / 3;
|
||||||
|
// }
|
||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
|
@ -483,6 +640,16 @@
|
||||||
|
|
||||||
.outer {
|
.outer {
|
||||||
@include S(margin-top, 15px);
|
@include S(margin-top, 15px);
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-auto-columns: 1fr;
|
||||||
|
|
||||||
|
@include S(grid-gap, 5px);
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> button {
|
||||||
|
@include S(padding, 3px, 6px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.importButton {
|
.importButton {
|
||||||
|
@ -491,14 +658,10 @@
|
||||||
|
|
||||||
.newGameButton {
|
.newGameButton {
|
||||||
@include IncreasedClickArea(0px);
|
@include IncreasedClickArea(0px);
|
||||||
@include S(margin-left, 10px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.modsButton {
|
.modsButton {
|
||||||
@include IncreasedClickArea(0px);
|
@include IncreasedClickArea(0px);
|
||||||
@include S(margin-left, 10px);
|
|
||||||
|
|
||||||
// @include S(width, 20px);
|
|
||||||
|
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-size: D(15px);
|
background-size: D(15px);
|
||||||
|
@ -509,9 +672,11 @@
|
||||||
.savegames {
|
.savegames {
|
||||||
@include S(max-height, 105px);
|
@include S(max-height, 105px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@include S(width, 250px);
|
@include S(min-width, 230px);
|
||||||
|
width: 100%;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
@include S(padding-right, 5px);
|
@include S(padding-right, 5px);
|
||||||
|
margin-right: D(-5px);
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: row;
|
grid-auto-flow: row;
|
||||||
@include S(grid-gap, 5px);
|
@include S(grid-gap, 5px);
|
||||||
|
@ -586,6 +751,7 @@
|
||||||
@include S(height, 15px);
|
@include S(height, 15px);
|
||||||
background-size: 80%;
|
background-size: 80%;
|
||||||
align-self: start;
|
align-self: start;
|
||||||
|
border-radius: 0;
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -608,6 +774,7 @@
|
||||||
@include S(height, 15px);
|
@include S(height, 15px);
|
||||||
align-self: end;
|
align-self: end;
|
||||||
background-size: 80%;
|
background-size: 80%;
|
||||||
|
border-radius: 0;
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -628,7 +795,7 @@
|
||||||
@include S(height, 10px);
|
@include S(height, 10px);
|
||||||
align-self: center;
|
align-self: center;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
|
border-radius: 0;
|
||||||
background-size: 90%;
|
background-size: 90%;
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
@include S(margin-left, 4px);
|
@include S(margin-left, 4px);
|
||||||
|
@ -725,7 +892,7 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
&:hover img {
|
&:hover img {
|
||||||
opacity: 0.8;
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -736,7 +903,7 @@
|
||||||
@include S(width, 82px);
|
@include S(width, 82px);
|
||||||
@include S(height, 25px);
|
@include S(height, 25px);
|
||||||
filter: invert(100%);
|
filter: invert(100%);
|
||||||
opacity: 0.6;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -744,7 +911,7 @@
|
||||||
@include S(padding, 15px);
|
@include S(padding, 15px);
|
||||||
|
|
||||||
$linkBg: rgba(#fdfdff, 0.5);
|
$linkBg: rgba(#fdfdff, 0.5);
|
||||||
$linkBgHover: darken($linkBg, 5);
|
$linkBgHover: rgba(#fff, 0.7);
|
||||||
$linkColor: #55586a;
|
$linkColor: #55586a;
|
||||||
|
|
||||||
> .boxLink {
|
> .boxLink {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#state_MobileWarningState {
|
#state_MobileWarningState {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #333438 !important;
|
background: #555b75 !important;
|
||||||
@include S(padding, 20px);
|
@include S(padding, 20px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: #aaacaf;
|
color: rgba(#fff, 0.5);
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 13px;
|
margin-bottom: 13px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
@ -28,12 +28,11 @@
|
||||||
|
|
||||||
.standaloneLink {
|
.standaloneLink {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 80px;
|
height: 48px;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
& {
|
& {
|
||||||
background: uiResource("steam_link_btn/0.png") center center / contain no-repeat;
|
background: #000 uiResource("steam_link_btn/0.png") center center / contain no-repeat;
|
||||||
}
|
}
|
||||||
overflow: hidden;
|
|
||||||
display: block;
|
display: block;
|
||||||
text-indent: -999em;
|
text-indent: -999em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -41,7 +40,9 @@
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
transition: all 0.12s ease-in;
|
transition: all 0.12s ease-in;
|
||||||
transition-property: opacity, transform;
|
transition-property: opacity, transform;
|
||||||
transform: skewX(-0.5deg);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: skewX(-1deg) scale(1.02);
|
transform: skewX(-1deg) scale(1.02);
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
transition: all 0.12s ease-in;
|
transition: all 0.12s ease-in;
|
||||||
transition-property: opacity, transform;
|
transition-property: opacity, transform;
|
||||||
|
|
||||||
|
box-shadow: 0 D(3px) D(10px) rgba(96, 163, 136, 0.5);
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
@ -178,34 +178,3 @@ $mainFontScale: 1;
|
||||||
@function trim($string) {
|
@function trim($string) {
|
||||||
@return str-slice($string, _first-index($string, "left"), _first-index($string, "right"));
|
@return str-slice($string, _first-index($string, "left"), _first-index($string, "right"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin AppendGlobal($prefix) {
|
|
||||||
$strSelector: quote(&);
|
|
||||||
$selectors: str-split($strSelector, ",");
|
|
||||||
|
|
||||||
$builtSelector: null;
|
|
||||||
|
|
||||||
@if (& == null) {
|
|
||||||
$builtSelector: "html" + $prefix;
|
|
||||||
} @else {
|
|
||||||
$builtSelector: ();
|
|
||||||
// @debug ($strSelector, "->>>", $selectors);
|
|
||||||
@each $srcSelector in $selectors {
|
|
||||||
$srcSelector: trim($srcSelector);
|
|
||||||
// @debug ("___", $srcSelector);
|
|
||||||
$selector: "html" + $prefix + " " + $srcSelector;
|
|
||||||
@if str-index($srcSelector, "html.") {
|
|
||||||
$selector: "html" +
|
|
||||||
$prefix +
|
|
||||||
"." +
|
|
||||||
str-slice($srcSelector, str-index($srcSelector, "html.") + 5);
|
|
||||||
}
|
|
||||||
// @debug ("_______", $selector);
|
|
||||||
$builtSelector: append($builtSelector, $selector, comma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@at-root #{$builtSelector} {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
export const CHANGELOG = [
|
export const CHANGELOG = [
|
||||||
|
{
|
||||||
|
version: "1.5.5",
|
||||||
|
date: "20.06.2022",
|
||||||
|
entries: [
|
||||||
|
"Reworked the tutorial to be simpler and more interactive",
|
||||||
|
"General polishing",
|
||||||
|
"Updated translations",
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
version: "1.5.3",
|
version: "1.5.3",
|
||||||
date: "05.06.2022",
|
date: "05.06.2022",
|
||||||
|
|
|
@ -183,7 +183,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||||
* Recomputes cache variables once the path was changed
|
* Recomputes cache variables once the path was changed
|
||||||
*/
|
*/
|
||||||
onPathChanged() {
|
onPathChanged() {
|
||||||
this.boundAcceptor = this.computeAcceptingEntityAndSlot();
|
this.boundAcceptor = this.computeAcceptingEntityAndSlot().acceptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How many items past the first item are compressed
|
* How many items past the first item are compressed
|
||||||
|
@ -201,7 +201,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||||
/**
|
/**
|
||||||
* Finds the entity which accepts our items
|
* Finds the entity which accepts our items
|
||||||
* @param {boolean=} debug_Silent Whether debug output should be silent
|
* @param {boolean=} debug_Silent Whether debug output should be silent
|
||||||
* @return { (BaseItem, number?) => boolean }
|
* @return { { acceptor?: (BaseItem, number?) => boolean, entity?: Entity } }
|
||||||
*/
|
*/
|
||||||
computeAcceptingEntityAndSlot(debug_Silent = false) {
|
computeAcceptingEntityAndSlot(debug_Silent = false) {
|
||||||
DEBUG && !debug_Silent && logger.log("Recomputing acceptor target");
|
DEBUG && !debug_Silent && logger.log("Recomputing acceptor target");
|
||||||
|
@ -224,7 +224,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!targetEntity) {
|
if (!targetEntity) {
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const noSimplifiedBelts = !this.root.app.settings.getAllSettings().simplifiedBelts;
|
const noSimplifiedBelts = !this.root.app.settings.getAllSettings().simplifiedBelts;
|
||||||
|
@ -247,10 +247,13 @@ export class BeltPath extends BasicSerializableObject {
|
||||||
targetStaticComp.rotation
|
targetStaticComp.rotation
|
||||||
);
|
);
|
||||||
if (ejectSlotWsDirection === beltAcceptingDirection) {
|
if (ejectSlotWsDirection === beltAcceptingDirection) {
|
||||||
return item => {
|
return {
|
||||||
const path = targetBeltComp.assignedPath;
|
entity: targetEntity,
|
||||||
assert(path, "belt has no path");
|
acceptor: item => {
|
||||||
return path.tryAcceptItem(item);
|
const path = targetBeltComp.assignedPath;
|
||||||
|
assert(path, "belt has no path");
|
||||||
|
return path.tryAcceptItem(item);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,7 +262,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||||
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
|
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
|
||||||
if (!targetAcceptorComp) {
|
if (!targetAcceptorComp) {
|
||||||
// Entity doesn't accept items
|
// Entity doesn't accept items
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection);
|
const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection);
|
||||||
|
@ -270,38 +273,41 @@ export class BeltPath extends BasicSerializableObject {
|
||||||
|
|
||||||
if (!matchingSlot) {
|
if (!matchingSlot) {
|
||||||
// No matching slot found
|
// No matching slot found
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const matchingSlotIndex = matchingSlot.index;
|
const matchingSlotIndex = matchingSlot.index;
|
||||||
const passOver = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex);
|
const passOver = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex);
|
||||||
if (!passOver) {
|
if (!passOver) {
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const matchingDirection = enumInvertedDirections[ejectingDirection];
|
const matchingDirection = enumInvertedDirections[ejectingDirection];
|
||||||
const filter = matchingSlot.slot.filter;
|
const filter = matchingSlot.slot.filter;
|
||||||
|
|
||||||
return function (item, remainingProgress = 0.0) {
|
return {
|
||||||
// Check if the acceptor has a filter
|
entity: targetEntity,
|
||||||
if (filter && item._type !== filter) {
|
acceptor: function (item, remainingProgress = 0.0) {
|
||||||
return false;
|
// Check if the acceptor has a filter
|
||||||
}
|
if (filter && item._type !== filter) {
|
||||||
|
return false;
|
||||||
// Try to pass over
|
|
||||||
if (passOver(item, matchingSlotIndex)) {
|
|
||||||
// Trigger animation on the acceptor comp
|
|
||||||
if (noSimplifiedBelts) {
|
|
||||||
targetAcceptorComp.onItemAccepted(
|
|
||||||
matchingSlotIndex,
|
|
||||||
matchingDirection,
|
|
||||||
item,
|
|
||||||
remainingProgress
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
// Try to pass over
|
||||||
return false;
|
if (passOver(item, matchingSlotIndex)) {
|
||||||
|
// Trigger animation on the acceptor comp
|
||||||
|
if (noSimplifiedBelts) {
|
||||||
|
targetAcceptorComp.onItemAccepted(
|
||||||
|
matchingSlotIndex,
|
||||||
|
matchingDirection,
|
||||||
|
item,
|
||||||
|
remainingProgress
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,7 +500,7 @@ export class BeltPath extends BasicSerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check acceptor
|
// Check acceptor
|
||||||
const acceptor = this.computeAcceptingEntityAndSlot(true);
|
const acceptor = this.computeAcceptingEntityAndSlot(true).acceptor;
|
||||||
if (!!acceptor !== !!this.boundAcceptor) {
|
if (!!acceptor !== !!this.boundAcceptor) {
|
||||||
return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.boundAcceptor);
|
return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.boundAcceptor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ export class Camera extends BasicSerializableObject {
|
||||||
* Finds a good initial zoom level
|
* Finds a good initial zoom level
|
||||||
*/
|
*/
|
||||||
findInitialZoom() {
|
findInitialZoom() {
|
||||||
const desiredWorldSpaceWidth = 15 * globalConfig.tileSize;
|
const desiredWorldSpaceWidth = 18 * globalConfig.tileSize;
|
||||||
const zoomLevelX = this.root.gameWidth / desiredWorldSpaceWidth;
|
const zoomLevelX = this.root.gameWidth / desiredWorldSpaceWidth;
|
||||||
const zoomLevelY = this.root.gameHeight / desiredWorldSpaceWidth;
|
const zoomLevelY = this.root.gameHeight / desiredWorldSpaceWidth;
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ export class GameCore {
|
||||||
});
|
});
|
||||||
this.root.map.placeStaticEntity(hub);
|
this.root.map.placeStaticEntity(hub);
|
||||||
this.root.entityMgr.registerEntity(hub);
|
this.root.entityMgr.registerEntity(hub);
|
||||||
|
this.root.camera.center = new Vector(-5, 2).multiplyScalar(globalConfig.tileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -287,6 +287,7 @@ export class HubGoals extends BasicSerializableObject {
|
||||||
* @param {string} upgradeId
|
* @param {string} upgradeId
|
||||||
*/
|
*/
|
||||||
canUnlockUpgrade(upgradeId) {
|
canUnlockUpgrade(upgradeId) {
|
||||||
|
return true;
|
||||||
const tiers = this.root.gameMode.getUpgrades()[upgradeId];
|
const tiers = this.root.gameMode.getUpgrades()[upgradeId];
|
||||||
const currentLevel = this.getUpgradeLevel(upgradeId);
|
const currentLevel = this.getUpgradeLevel(upgradeId);
|
||||||
|
|
||||||
|
|
|
@ -198,6 +198,7 @@ export class GameHUD {
|
||||||
"changesDebugger",
|
"changesDebugger",
|
||||||
"minerHighlight",
|
"minerHighlight",
|
||||||
"shapeTooltip",
|
"shapeTooltip",
|
||||||
|
"interactiveTutorial",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i = 0; i < partsOrder.length; ++i) {
|
for (let i = 0; i < partsOrder.length; ++i) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { makeDiv } from "../../../core/utils";
|
import { clamp, makeDiv, smoothPulse } from "../../../core/utils";
|
||||||
import { GameRoot } from "../../root";
|
import { GameRoot } from "../../root";
|
||||||
import { MinerComponent } from "../../components/miner";
|
import { MinerComponent } from "../../components/miner";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
|
@ -10,6 +10,15 @@ import { enumItemProcessorTypes, ItemProcessorComponent } from "../../components
|
||||||
import { ShapeItem } from "../../items/shape_item";
|
import { ShapeItem } from "../../items/shape_item";
|
||||||
import { WireComponent } from "../../components/wire";
|
import { WireComponent } from "../../components/wire";
|
||||||
import { LeverComponent } from "../../components/lever";
|
import { LeverComponent } from "../../components/lever";
|
||||||
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
|
import { globalConfig } from "../../../core/config";
|
||||||
|
import { Vector } from "../../../core/vector";
|
||||||
|
import { MetaMinerBuilding } from "../../buildings/miner";
|
||||||
|
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||||
|
import { MetaBeltBuilding } from "../../buildings/belt";
|
||||||
|
import { BeltComponent } from "../../components/belt";
|
||||||
|
import { MetaTrashBuilding } from "../../buildings/trash";
|
||||||
|
import { SOUNDS } from "../../../platform/sound";
|
||||||
|
|
||||||
// @todo: Make dictionary
|
// @todo: Make dictionary
|
||||||
const tutorialsByLevel = [
|
const tutorialsByLevel = [
|
||||||
|
@ -24,12 +33,30 @@ const tutorialsByLevel = [
|
||||||
// 1.2. connect to hub
|
// 1.2. connect to hub
|
||||||
{
|
{
|
||||||
id: "1_2_conveyor",
|
id: "1_2_conveyor",
|
||||||
condition: /** @param {GameRoot} root */ root => root.hubGoals.getCurrentGoalDelivered() === 0,
|
condition: /** @param {GameRoot} root */ root => {
|
||||||
|
const paths = root.systemMgr.systems.belt.beltPaths;
|
||||||
|
const miners = root.entityMgr.getAllWithComponent(MinerComponent);
|
||||||
|
for (let i = 0; i < paths.length; i++) {
|
||||||
|
const path = paths[i];
|
||||||
|
const acceptingEntity = path.computeAcceptingEntityAndSlot().entity;
|
||||||
|
if (!acceptingEntity || !acceptingEntity.components.Hub) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Find a miner which delivers to this belt path
|
||||||
|
for (let k = 0; k < miners.length; ++k) {
|
||||||
|
const miner = miners[k];
|
||||||
|
if (miner.components.ItemEjector.slots[0].cachedBeltPath === path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// 1.3 wait for completion
|
// 1.3 wait for completion
|
||||||
{
|
{
|
||||||
id: "1_3_expand",
|
id: "1_3_expand",
|
||||||
condition: () => true,
|
condition: /** @param {GameRoot} root */ root => true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// Level 2
|
// Level 2
|
||||||
|
@ -55,11 +82,7 @@ const tutorialsByLevel = [
|
||||||
// 2.3 place more cutters
|
// 2.3 place more cutters
|
||||||
{
|
{
|
||||||
id: "2_3_more_cutters",
|
id: "2_3_more_cutters",
|
||||||
condition: /** @param {GameRoot} root */ root =>
|
condition: /** @param {GameRoot} root */ root => true,
|
||||||
root.entityMgr
|
|
||||||
.getAllWithComponent(ItemProcessorComponent)
|
|
||||||
.filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.cutter).length <
|
|
||||||
3,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -158,7 +181,7 @@ export class HUDInteractiveTutorial extends BaseHUDPart {
|
||||||
|
|
||||||
onHintChanged(hintId) {
|
onHintChanged(hintId) {
|
||||||
this.elementDescription.innerHTML = T.ingame.interactiveTutorial.hints[hintId];
|
this.elementDescription.innerHTML = T.ingame.interactiveTutorial.hints[hintId];
|
||||||
|
document.documentElement.setAttribute("data-tutorial-step", hintId);
|
||||||
const folder = G_WEGAME_VERSION
|
const folder = G_WEGAME_VERSION
|
||||||
? "interactive_tutorial.cn.noinline"
|
? "interactive_tutorial.cn.noinline"
|
||||||
: "interactive_tutorial.noinline";
|
: "interactive_tutorial.noinline";
|
||||||
|
@ -167,6 +190,9 @@ export class HUDInteractiveTutorial extends BaseHUDPart {
|
||||||
"url('" + cachebust("res/ui/" + folder + "/" + hintId + ".gif") + "')";
|
"url('" + cachebust("res/ui/" + folder + "/" + hintId + ".gif") + "')";
|
||||||
this.element.classList.toggle("animEven");
|
this.element.classList.toggle("animEven");
|
||||||
this.element.classList.toggle("animOdd");
|
this.element.classList.toggle("animOdd");
|
||||||
|
if (hintId) {
|
||||||
|
this.root.app.sound.playUiSound(SOUNDS.tutorialStep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
|
@ -187,4 +213,226 @@ export class HUDInteractiveTutorial extends BaseHUDPart {
|
||||||
this.currentHintId.set(targetHintId);
|
this.currentHintId.set(targetHintId);
|
||||||
this.domAttach.update(!!targetHintId);
|
this.domAttach.update(!!targetHintId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
*/
|
||||||
|
draw(parameters) {
|
||||||
|
const animation = smoothPulse(this.root.time.now());
|
||||||
|
const currentBuilding = this.root.hud.parts.buildingPlacer.currentMetaBuilding.get();
|
||||||
|
|
||||||
|
if (["1_1_extractor"].includes(this.currentHintId.get())) {
|
||||||
|
if (
|
||||||
|
currentBuilding &&
|
||||||
|
currentBuilding.getId() === gMetaBuildingRegistry.findByClass(MetaMinerBuilding).getId()
|
||||||
|
) {
|
||||||
|
// Find closest circle patch to hub
|
||||||
|
|
||||||
|
let closest = null;
|
||||||
|
let closestDistance = 1e10;
|
||||||
|
|
||||||
|
for (let i = 0; i > -globalConfig.mapChunkSize; --i) {
|
||||||
|
for (let j = 0; j < globalConfig.mapChunkSize; ++j) {
|
||||||
|
const resourceItem = this.root.map.getLowerLayerContentXY(i, j);
|
||||||
|
if (
|
||||||
|
resourceItem instanceof ShapeItem &&
|
||||||
|
resourceItem.definition.getHash() === "CuCuCuCu"
|
||||||
|
) {
|
||||||
|
let distance = Math.hypot(i, j);
|
||||||
|
if (!closest || distance < closestDistance) {
|
||||||
|
const tile = new Vector(i, j);
|
||||||
|
if (!this.root.map.getTileContent(tile, "regular")) {
|
||||||
|
closest = tile;
|
||||||
|
closestDistance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest) {
|
||||||
|
parameters.context.fillStyle = "rgba(74, 237, 134, " + (0.5 - animation * 0.2) + ")";
|
||||||
|
parameters.context.strokeStyle = "rgb(74, 237, 134)";
|
||||||
|
parameters.context.lineWidth = 2;
|
||||||
|
parameters.context.beginRoundedRect(
|
||||||
|
closest.x * globalConfig.tileSize - 2 * animation,
|
||||||
|
closest.y * globalConfig.tileSize - 2 * animation,
|
||||||
|
globalConfig.tileSize + 4 * animation,
|
||||||
|
globalConfig.tileSize + 4 * animation,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
parameters.context.fill();
|
||||||
|
parameters.context.stroke();
|
||||||
|
parameters.context.globalAlpha = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentHintId.get() === "1_2_conveyor") {
|
||||||
|
if (
|
||||||
|
currentBuilding &&
|
||||||
|
currentBuilding.getId() === gMetaBuildingRegistry.findByClass(MetaBeltBuilding).getId()
|
||||||
|
) {
|
||||||
|
// Find closest miner
|
||||||
|
const miners = this.root.entityMgr.getAllWithComponent(MinerComponent);
|
||||||
|
|
||||||
|
let closest = null;
|
||||||
|
let closestDistance = 1e10;
|
||||||
|
|
||||||
|
for (let i = 0; i < miners.length; i++) {
|
||||||
|
const miner = miners[i];
|
||||||
|
const distance = miner.components.StaticMapEntity.origin.lengthSquare();
|
||||||
|
|
||||||
|
if (![0, 90].includes(miner.components.StaticMapEntity.rotation)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!closest || distance < closestDistance) {
|
||||||
|
closest = miner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest) {
|
||||||
|
// draw line from miner to hub -> But respect orientation
|
||||||
|
|
||||||
|
const staticComp = closest.components.StaticMapEntity;
|
||||||
|
|
||||||
|
const offset = staticComp.rotation === 0 ? new Vector(0.5, 0) : new Vector(1, 0.5);
|
||||||
|
|
||||||
|
const anchor =
|
||||||
|
staticComp.rotation === 0
|
||||||
|
? new Vector(staticComp.origin.x + 0.5, 0.5)
|
||||||
|
: new Vector(-0.5, staticComp.origin.y + 0.5);
|
||||||
|
|
||||||
|
const target = staticComp.rotation === 0 ? new Vector(-2.1, 0.5) : new Vector(-0.5, 2.1);
|
||||||
|
|
||||||
|
parameters.context.globalAlpha = 0.1 + animation * 0.1;
|
||||||
|
parameters.context.strokeStyle = "rgb(74, 237, 134)";
|
||||||
|
parameters.context.lineWidth = globalConfig.tileSize / 2;
|
||||||
|
parameters.context.beginPath();
|
||||||
|
parameters.context.moveTo(
|
||||||
|
(staticComp.origin.x + offset.x) * globalConfig.tileSize,
|
||||||
|
(staticComp.origin.y + offset.y) * globalConfig.tileSize
|
||||||
|
);
|
||||||
|
parameters.context.lineTo(
|
||||||
|
anchor.x * globalConfig.tileSize,
|
||||||
|
anchor.y * globalConfig.tileSize
|
||||||
|
);
|
||||||
|
parameters.context.lineTo(
|
||||||
|
target.x * globalConfig.tileSize,
|
||||||
|
target.y * globalConfig.tileSize
|
||||||
|
);
|
||||||
|
parameters.context.stroke();
|
||||||
|
parameters.context.globalAlpha = 1;
|
||||||
|
|
||||||
|
const arrowSprite = this.root.hud.parts.buildingPlacer.lockIndicatorSprites.regular;
|
||||||
|
|
||||||
|
let arrows = [];
|
||||||
|
|
||||||
|
let pos = staticComp.origin.add(offset);
|
||||||
|
let delta = anchor.sub(pos).normalize();
|
||||||
|
let maxIter = 999;
|
||||||
|
|
||||||
|
while (pos.distanceSquare(anchor) > 1 && maxIter-- > 0) {
|
||||||
|
pos = pos.add(delta);
|
||||||
|
arrows.push({
|
||||||
|
pos: pos.sub(offset),
|
||||||
|
rotation: staticComp.rotation,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = anchor.copy();
|
||||||
|
delta = target.sub(pos).normalize();
|
||||||
|
const localDelta =
|
||||||
|
staticComp.rotation === 0 ? new Vector(-1.5, -0.5) : new Vector(-0.5, 0.5);
|
||||||
|
while (pos.distanceSquare(target) > 1 && maxIter-- > 0) {
|
||||||
|
pos = pos.add(delta);
|
||||||
|
arrows.push({
|
||||||
|
pos: pos.add(localDelta),
|
||||||
|
rotation: 90 - staticComp.rotation,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < arrows.length; i++) {
|
||||||
|
const { pos, rotation } = arrows[i];
|
||||||
|
const worldPos = pos.toWorldSpaceCenterOfTile();
|
||||||
|
const angle = Math.radians(rotation);
|
||||||
|
|
||||||
|
parameters.context.translate(worldPos.x, worldPos.y);
|
||||||
|
parameters.context.rotate(angle);
|
||||||
|
parameters.context.drawImage(
|
||||||
|
arrowSprite,
|
||||||
|
-6,
|
||||||
|
-globalConfig.halfTileSize -
|
||||||
|
clamp((this.root.time.realtimeNow() * 1.5) % 1.0, 0, 1) *
|
||||||
|
1 *
|
||||||
|
globalConfig.tileSize +
|
||||||
|
globalConfig.halfTileSize -
|
||||||
|
6,
|
||||||
|
12,
|
||||||
|
12
|
||||||
|
);
|
||||||
|
parameters.context.rotate(-angle);
|
||||||
|
parameters.context.translate(-worldPos.x, -worldPos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
parameters.context.fillStyle = "rgb(30, 40, 60)";
|
||||||
|
parameters.context.font = "15px GameFont";
|
||||||
|
|
||||||
|
if (staticComp.rotation === 0) {
|
||||||
|
const pos = staticComp.origin.toWorldSpace().subScalars(2, 10);
|
||||||
|
parameters.context.translate(pos.x, pos.y);
|
||||||
|
parameters.context.rotate(-Math.radians(90));
|
||||||
|
parameters.context.fillText(
|
||||||
|
T.ingame.interactiveTutorial.hints["1_2_hold_and_drag"],
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
parameters.context.rotate(Math.radians(90));
|
||||||
|
parameters.context.translate(-pos.x, -pos.y);
|
||||||
|
} else {
|
||||||
|
const pos = staticComp.origin.toWorldSpace().addScalars(40, 50);
|
||||||
|
parameters.context.fillText(
|
||||||
|
T.ingame.interactiveTutorial.hints["1_2_hold_and_drag"],
|
||||||
|
pos.x,
|
||||||
|
pos.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentHintId.get() === "2_2_place_trash") {
|
||||||
|
// Find cutters
|
||||||
|
if (
|
||||||
|
currentBuilding &&
|
||||||
|
currentBuilding.getId() === gMetaBuildingRegistry.findByClass(MetaTrashBuilding).getId()
|
||||||
|
) {
|
||||||
|
const entities = this.root.entityMgr.getAllWithComponent(ItemProcessorComponent);
|
||||||
|
for (let i = 0; i < entities.length; i++) {
|
||||||
|
const entity = entities[i];
|
||||||
|
if (entity.components.ItemProcessor.type !== enumItemProcessorTypes.cutter) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const slot = entity.components.StaticMapEntity.localTileToWorld(
|
||||||
|
new Vector(1, -1)
|
||||||
|
).toWorldSpace();
|
||||||
|
parameters.context.fillStyle = "rgba(74, 237, 134, " + (0.5 - animation * 0.2) + ")";
|
||||||
|
parameters.context.strokeStyle = "rgb(74, 237, 134)";
|
||||||
|
parameters.context.lineWidth = 2;
|
||||||
|
parameters.context.beginRoundedRect(
|
||||||
|
slot.x - 2 * animation,
|
||||||
|
slot.y - 2 * animation,
|
||||||
|
globalConfig.tileSize + 4 * animation,
|
||||||
|
globalConfig.tileSize + 4 * animation,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
parameters.context.fill();
|
||||||
|
parameters.context.stroke();
|
||||||
|
parameters.context.globalAlpha = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { T } from "../../../translations";
|
import { T } from "../../../translations";
|
||||||
|
|
||||||
const tutorialVideos = [2, 3, 4, 5, 6, 7, 9, 10, 11];
|
const tutorialVideos = [3, 4, 5, 6, 7, 9, 10, 11];
|
||||||
|
|
||||||
export class HUDPartTutorialHints extends BaseHUDPart {
|
export class HUDPartTutorialHints extends BaseHUDPart {
|
||||||
createElements(parent) {
|
createElements(parent) {
|
||||||
|
|
|
@ -110,13 +110,6 @@ export class InGameState extends GameState {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
getThemeMusic() {
|
|
||||||
if (this.creationPayload.gameModeId && this.creationPayload.gameModeId.includes("puzzle")) {
|
|
||||||
return MUSIC.puzzle;
|
|
||||||
}
|
|
||||||
return MUSIC.theme;
|
|
||||||
}
|
|
||||||
|
|
||||||
onAppPause() {
|
onAppPause() {
|
||||||
// if (this.stage === stages.s10_gameRunning) {
|
// if (this.stage === stages.s10_gameRunning) {
|
||||||
// logger.log("Saving because app got paused");
|
// logger.log("Saving because app got paused");
|
||||||
|
@ -241,6 +234,15 @@ export class InGameState extends GameState {
|
||||||
|
|
||||||
this.app.backgroundResourceLoader.getIngamePromise().then(
|
this.app.backgroundResourceLoader.getIngamePromise().then(
|
||||||
() => {
|
() => {
|
||||||
|
if (
|
||||||
|
this.creationPayload.gameModeId &&
|
||||||
|
this.creationPayload.gameModeId.includes("puzzle")
|
||||||
|
) {
|
||||||
|
this.app.sound.playThemeMusic(MUSIC.puzzle);
|
||||||
|
} else {
|
||||||
|
this.app.sound.playThemeMusic(MUSIC.theme);
|
||||||
|
}
|
||||||
|
|
||||||
this.loadingOverlay.loadingIndicator.innerText = "";
|
this.loadingOverlay.loadingIndicator.innerText = "";
|
||||||
this.app.backgroundResourceLoader.resourceStateChangedSignal.removeAll();
|
this.app.backgroundResourceLoader.resourceStateChangedSignal.removeAll();
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,6 @@ export class MainMenuState extends GameState {
|
||||||
getInnerHTML() {
|
getInnerHTML() {
|
||||||
const showLanguageIcon = !G_CHINA_VERSION && !G_WEGAME_VERSION;
|
const showLanguageIcon = !G_CHINA_VERSION && !G_WEGAME_VERSION;
|
||||||
const showExitAppButton = G_IS_STANDALONE;
|
const showExitAppButton = G_IS_STANDALONE;
|
||||||
// const showBrowserWarning = !G_IS_STANDALONE && !isSupportedBrowser();
|
|
||||||
const showBrowserWarning = false;
|
|
||||||
const showPuzzleDLC = !G_WEGAME_VERSION && G_IS_STANDALONE && !G_IS_STEAM_DEMO;
|
const showPuzzleDLC = !G_WEGAME_VERSION && G_IS_STANDALONE && !G_IS_STEAM_DEMO;
|
||||||
const showWegameFooter = G_WEGAME_VERSION;
|
const showWegameFooter = G_WEGAME_VERSION;
|
||||||
const hasMods = MODS.anyModsActive();
|
const hasMods = MODS.anyModsActive();
|
||||||
|
@ -73,8 +71,23 @@ export class MainMenuState extends GameState {
|
||||||
/** @type { PlatformWrapperImplElectron}*/ (this.app.platformWrapper).dlcs.puzzle);
|
/** @type { PlatformWrapperImplElectron}*/ (this.app.platformWrapper).dlcs.puzzle);
|
||||||
|
|
||||||
const bannerHtml = `
|
const bannerHtml = `
|
||||||
<h3>${T.demoBanners.title}</h3>
|
<h3>${T.demoBanners.titleV2}</h3>
|
||||||
<p>${T.demoBanners.intro}</p>
|
|
||||||
|
|
||||||
|
<div class="points">
|
||||||
|
${Object.entries(T.ingame.standaloneAdvantages.points)
|
||||||
|
.map(
|
||||||
|
([key, trans]) => `
|
||||||
|
<div class="point ${key}">
|
||||||
|
<strong>${trans.title}</strong>
|
||||||
|
<p>${trans.desc}</p>
|
||||||
|
</div>`
|
||||||
|
)
|
||||||
|
.join("")}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
${
|
${
|
||||||
G_IS_STEAM_DEMO
|
G_IS_STEAM_DEMO
|
||||||
? `<span class="playtimeDisclaimer">${T.demoBanners.playtimeDisclaimer}</span>`
|
? `<span class="playtimeDisclaimer">${T.demoBanners.playtimeDisclaimer}</span>`
|
||||||
|
@ -110,21 +123,21 @@ export class MainMenuState extends GameState {
|
||||||
|
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<img src="${cachebust("res/" + getLogoSprite())}" alt="shapez.io Logo"
|
<img src="${cachebust("res/" + getLogoSprite())}" alt="shapez.io Logo"
|
||||||
width="${Math.round((710 / 2.2) * this.app.getEffectiveUiScale())}"
|
width="${Math.round((710 / 2.5) * this.app.getEffectiveUiScale())}"
|
||||||
height="${Math.round((180 / 2.2) * this.app.getEffectiveUiScale())}"
|
height="${Math.round((180 / 2.5) * this.app.getEffectiveUiScale())}"
|
||||||
>
|
>
|
||||||
${/*showUpdateLabel ? `<span class="updateLabel">MODS UPDATE!</span>` : ""*/ ""}
|
${/*showUpdateLabel ? `<span class="updateLabel">MODS UPDATE!</span>` : ""*/ ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mainWrapper" data-columns="${showDemoAdvertisement || showPuzzleDLC ? 2 : 1}">
|
<div class="mainWrapper" data-columns="${showDemoAdvertisement || showPuzzleDLC ? 2 : 1}">
|
||||||
|
<div class="mainContainer">
|
||||||
|
<div class="buttons"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="sideContainer">
|
<div class="sideContainer">
|
||||||
${showDemoAdvertisement ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
${showDemoAdvertisement ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mainContainer">
|
|
||||||
${showBrowserWarning ? `<div class="browserWarning">${T.mainMenu.browserWarning}</div>` : ""}
|
|
||||||
<div class="buttons"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${
|
${
|
||||||
showPuzzleDLC && ownsPuzzleDLC && !hasMods
|
showPuzzleDLC && ownsPuzzleDLC && !hasMods
|
||||||
|
@ -425,6 +438,10 @@ export class MainMenuState extends GameState {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.htmlElement
|
||||||
|
.querySelector(".mainContainer")
|
||||||
|
.setAttribute("data-savegames", String(this.savedGames.length));
|
||||||
|
|
||||||
// Mods
|
// Mods
|
||||||
this.trackClicks(
|
this.trackClicks(
|
||||||
makeButton(outerDiv, ["modsButton", "styledButton"], T.mods.title),
|
makeButton(outerDiv, ["modsButton", "styledButton"], T.mods.title),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { cachebust } from "../core/cachebust";
|
import { cachebust } from "../core/cachebust";
|
||||||
import { GameState } from "../core/game_state";
|
import { GameState } from "../core/game_state";
|
||||||
import { getLogoSprite } from "../core/utils";
|
|
||||||
|
|
||||||
export class MobileWarningState extends GameState {
|
export class MobileWarningState extends GameState {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -10,14 +9,10 @@ export class MobileWarningState extends GameState {
|
||||||
getInnerHTML() {
|
getInnerHTML() {
|
||||||
return `
|
return `
|
||||||
|
|
||||||
<img class="logo" src="${cachebust("res/" + getLogoSprite())}" alt="shapez.io Logo">
|
<img class="logo" src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
||||||
|
|
||||||
<p>
|
<p>I'm sorry, but shapez.io is not available on mobile devices yet!</p>
|
||||||
I'm sorry, but shapez.io is not available on mobile devices yet!
|
<p>If you have a desktop device, you can get shapez on Steam:</p>
|
||||||
There is also no estimate when this will change, but feel to make a contribution! It's
|
|
||||||
<a href="https://github.com/tobspr/shapez.io" target="_blank">open source</a>!</p>
|
|
||||||
|
|
||||||
<p>If you want to play on your computer, you can also get the game on Steam:</p>
|
|
||||||
|
|
||||||
|
|
||||||
<a href="https://get.shapez.io/shapez_mobile" class="standaloneLink" target="_blank">Play on Steam!</a>
|
<a href="https://get.shapez.io/shapez_mobile" class="standaloneLink" target="_blank">Play on Steam!</a>
|
||||||
|
|
|
@ -57,6 +57,8 @@ global:
|
||||||
loadingResources: Lade zusätzliche Ressourcen (<percentage> %)
|
loadingResources: Lade zusätzliche Ressourcen (<percentage> %)
|
||||||
demoBanners:
|
demoBanners:
|
||||||
title: Demoversion
|
title: Demoversion
|
||||||
|
titleV2: >-
|
||||||
|
Spiele jetzt die Vollversion für:
|
||||||
intro: |-
|
intro: |-
|
||||||
Kaufe die Vollversion <strong>jetzt</strong> für:<ul>
|
Kaufe die Vollversion <strong>jetzt</strong> für:<ul>
|
||||||
<li>Alle 26 Level + unendlich Freeplay</li>
|
<li>Alle 26 Level + unendlich Freeplay</li>
|
||||||
|
@ -77,7 +79,7 @@ mainMenu:
|
||||||
newGame: Neues Spiel
|
newGame: Neues Spiel
|
||||||
changelog: Änderungshistorie
|
changelog: Änderungshistorie
|
||||||
subreddit: Reddit
|
subreddit: Reddit
|
||||||
importSavegame: Importieren
|
importSavegame: Import
|
||||||
openSourceHint: Dieses Spiel ist quelloffen!
|
openSourceHint: Dieses Spiel ist quelloffen!
|
||||||
discordLink: Offizieller Discord Server
|
discordLink: Offizieller Discord Server
|
||||||
helpTranslate: Hilf beim Übersetzen!
|
helpTranslate: Hilf beim Übersetzen!
|
||||||
|
@ -497,6 +499,7 @@ ingame:
|
||||||
Signal</strong> ausgibt und den Färber aktiviert.<br><br> PS: Du
|
Signal</strong> ausgibt und den Färber aktiviert.<br><br> PS: Du
|
||||||
musst nicht alle Eingänge verbinden! Probiere es auch mal mit
|
musst nicht alle Eingänge verbinden! Probiere es auch mal mit
|
||||||
zwei."
|
zwei."
|
||||||
|
1_2_hold_and_drag: Drücke und ziehe
|
||||||
connectedMiners:
|
connectedMiners:
|
||||||
one_miner: Ein Extraktor
|
one_miner: Ein Extraktor
|
||||||
n_miners: <amount> Extraktoren
|
n_miners: <amount> Extraktoren
|
||||||
|
|
|
@ -97,6 +97,9 @@ global:
|
||||||
demoBanners:
|
demoBanners:
|
||||||
# This is the "advertisement" shown in the main menu and other various places
|
# This is the "advertisement" shown in the main menu and other various places
|
||||||
title: Demo
|
title: Demo
|
||||||
|
titleV2: >-
|
||||||
|
Play the full version now for:
|
||||||
|
|
||||||
intro: >-
|
intro: >-
|
||||||
Get the full game <strong>now</strong> to unlock:<ul>
|
Get the full game <strong>now</strong> to unlock:<ul>
|
||||||
<li>All 26 levels + infinite Freeplay</li>
|
<li>All 26 levels + infinite Freeplay</li>
|
||||||
|
@ -641,6 +644,8 @@ ingame:
|
||||||
Press the switch to make it <strong>emit a truthy signal</strong> and thus activate the painter.<br><br>
|
Press the switch to make it <strong>emit a truthy signal</strong> and thus activate the painter.<br><br>
|
||||||
PS: You don't have to connect all inputs! Try wiring only two.
|
PS: You don't have to connect all inputs! Try wiring only two.
|
||||||
|
|
||||||
|
1_2_hold_and_drag: Hold and drag
|
||||||
|
|
||||||
# Connected miners
|
# Connected miners
|
||||||
connectedMiners:
|
connectedMiners:
|
||||||
one_miner: 1 Extractor
|
one_miner: 1 Extractor
|
||||||
|
@ -655,7 +660,7 @@ ingame:
|
||||||
|
|
||||||
standaloneAdvantages:
|
standaloneAdvantages:
|
||||||
titleV2: >-
|
titleV2: >-
|
||||||
Get the full version now on Steam to unlock:
|
Play the full version now on Steam to unlock:
|
||||||
titleExpiredV2: Demo completed!
|
titleExpiredV2: Demo completed!
|
||||||
titleEnjoyingDemo: Enjoying the demo?
|
titleEnjoyingDemo: Enjoying the demo?
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue