diff --git a/artwork/itch.io/screenshots/7.png b/artwork/itch.io/screenshots/7.png
index bab1b536..0df86bcc 100644
Binary files a/artwork/itch.io/screenshots/7.png and b/artwork/itch.io/screenshots/7.png differ
diff --git a/artwork/itch.io/screenshots/8.png b/artwork/itch.io/screenshots/8.png
new file mode 100644
index 00000000..1b3bbdc2
Binary files /dev/null and b/artwork/itch.io/screenshots/8.png differ
diff --git a/artwork/thirdparty/kongregate/iframe.html b/artwork/thirdparty/kongregate/iframe.html
new file mode 100644
index 00000000..6b741420
--- /dev/null
+++ b/artwork/thirdparty/kongregate/iframe.html
@@ -0,0 +1,17 @@
+
+
+
+ Iframe test
+
+
+
+
+
diff --git a/artwork/thirdparty/kongregate/index.html b/artwork/thirdparty/kongregate/index.html
index 03a38db1..ce19f275 100644
--- a/artwork/thirdparty/kongregate/index.html
+++ b/artwork/thirdparty/kongregate/index.html
@@ -2,11 +2,11 @@
Redirecting to shapez.io
-
+
Redirecting you to
- shapez.io
+ shapez.io
diff --git a/src/css/ingame_hud/dialogs.scss b/src/css/ingame_hud/dialogs.scss
index d2315063..868dac58 100644
--- a/src/css/ingame_hud/dialogs.scss
+++ b/src/css/ingame_hud/dialogs.scss
@@ -117,6 +117,10 @@
overflow-y: auto;
pointer-events: all;
@include S(width, 350px);
+
+ > strong {
+ font-weight: bold;
+ }
}
> .buttons {
@@ -143,6 +147,32 @@
background-color: $colorRedBright;
color: #fff;
}
+
+ &.timedButton {
+ pointer-events: none;
+ cursor: default;
+ position: relative;
+ overflow: hidden;
+ &::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: unset;
+ z-index: 5;
+ content: " ";
+ display: inline-block;
+ background: rgba(#fff, 0.6);
+ @include InlineAnimation(5s linear) {
+ 0% {
+ width: 100%;
+ }
+ 100% {
+ width: 0%;
+ }
+ }
+ }
+ }
}
}
}
diff --git a/src/css/states/changelog.scss b/src/css/states/changelog.scss
index d4a948bf..69b7864c 100644
--- a/src/css/states/changelog.scss
+++ b/src/css/states/changelog.scss
@@ -19,6 +19,13 @@
.changes {
@include SuperSmallText;
@include S(padding-left, 20px);
+ strong {
+ background: $colorBlueBright;
+ color: #fff;
+ text-transform: uppercase;
+ @include S(padding, 1px, 2px);
+ @include S(margin-right, 3px);
+ }
}
}
}
diff --git a/src/css/states/preload.scss b/src/css/states/preload.scss
index 2c8a302e..075a363f 100644
--- a/src/css/states/preload.scss
+++ b/src/css/states/preload.scss
@@ -7,11 +7,14 @@
}
.changelogDialogEntry {
+ margin-top: 10px;
width: 100%;
flex-direction: column;
text-align: left;
padding: 10px;
box-sizing: border-box;
+ background: #eef1f4;
+
.version {
@include Heading;
}
@@ -25,7 +28,14 @@
.changes {
@include SuperSmallText;
- @include S(padding-left, 20px);
+ @include S(padding-left, 15px);
+ strong {
+ background: $colorBlueBright;
+ color: #fff;
+ text-transform: uppercase;
+ @include S(padding, 1px, 2px);
+ @include S(margin-right, 3px);
+ }
}
}
diff --git a/src/js/application.js b/src/js/application.js
index 58804ee5..27be4b1c 100644
--- a/src/js/application.js
+++ b/src/js/application.js
@@ -146,11 +146,7 @@ export class Application {
}
this.analytics = new GoogleAnalyticsImpl(this);
- if (queryParamOptions.betaMode) {
- this.gameAnalytics = new NoGameAnalytics(this);
- } else {
- this.gameAnalytics = new ShapezGameAnalytics(this);
- }
+ this.gameAnalytics = new ShapezGameAnalytics(this);
}
/**
@@ -232,6 +228,7 @@ export class Application {
* @param {Event} event
*/
handleVisibilityChange(event) {
+ window.focus();
const pageVisible = !document[pageHiddenPropName];
if (pageVisible !== this.pageVisible) {
this.pageVisible = pageVisible;
@@ -271,6 +268,7 @@ export class Application {
onAppRenderableStateChanged(renderable) {
logger.log("Application renderable:", renderable);
+ window.focus();
if (!renderable) {
this.stateMgr.getCurrentState().onAppPause();
} else {
@@ -301,8 +299,7 @@ export class Application {
logSection("BEFORE UNLOAD HANDLER", "#f77");
if (!G_IS_DEV && this.stateMgr.getCurrentState().getHasUnloadConfirmation()) {
- if (G_IS_STANDALONE) {
- } else {
+ if (!G_IS_STANDALONE) {
// Need to show a "Are you sure you want to exit"
event.preventDefault();
event.returnValue = "Are you sure you want to exit?";
@@ -314,6 +311,7 @@ export class Application {
* Boots the application
*/
boot() {
+ console.log("Booting ...");
this.registerStates();
this.registerEventListeners();
@@ -330,6 +328,8 @@ export class Application {
this.ticker.frameEmitted.add(this.onFrameEmitted, this);
this.ticker.bgFrameEmitted.add(this.onBackgroundFrame, this);
this.ticker.start();
+
+ window.focus();
}
/**
diff --git a/src/js/changelog.js b/src/js/changelog.js
index 3b3bb229..f2744136 100644
--- a/src/js/changelog.js
+++ b/src/js/changelog.js
@@ -1,4 +1,19 @@
export const CHANGELOG = [
+ {
+ version: "1.0.4",
+ date: "unreleased",
+ entries: [
+ "Balancing Reduce cost of first painting upgrade, and change 'Shape Processing' to 'Cutting, Rotating & Stacking'",
+ "Tutorial Add dialog after completing level 2 to check out the upgrades tab.",
+ ],
+ },
+ {
+ version: "1.0.3",
+ date: "24.05.2020",
+ entries: [
+ "Balancing Reduced the amount of shapes required for the first 5 levels to make it easier to get into the game.",
+ ],
+ },
{
version: "1.0.2",
date: "23.05.2020",
diff --git a/src/js/core/click_detector.js b/src/js/core/click_detector.js
index a4aece50..557c1f28 100644
--- a/src/js/core/click_detector.js
+++ b/src/js/core/click_detector.js
@@ -155,6 +155,7 @@ export class ClickDetector {
* @param {Event} event
*/
internalPreventClick(event) {
+ window.focus();
event.preventDefault();
}
@@ -301,6 +302,8 @@ export class ClickDetector {
* @param {TouchEvent|MouseEvent} event
*/
internalOnPointerDown(event) {
+ window.focus();
+
if (!this.internalEventPreHandler(event, 1)) {
return false;
}
@@ -369,6 +372,8 @@ export class ClickDetector {
* @param {TouchEvent|MouseEvent} event
*/
internalOnPointerEnd(event) {
+ window.focus();
+
if (!this.internalEventPreHandler(event, 0)) {
return false;
}
diff --git a/src/js/core/config.js b/src/js/core/config.js
index 70f9ee3b..922870d8 100644
--- a/src/js/core/config.js
+++ b/src/js/core/config.js
@@ -101,7 +101,8 @@ export const globalConfig = {
// framePausesBetweenTicks: 40,
// testTranslations: true,
// enableEntityInspector: true,
- testAds: true,
+ // testAds: true,
+ disableMapOverview: true,
/* dev:end */
},
@@ -123,3 +124,8 @@ export const IS_MOBILE = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
// Automatic calculations
globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5;
+
+if (globalConfig.debug.disableMapOverview) {
+ globalConfig.mapChunkOverviewMinZoom = 0;
+ globalConfig.mapChunkPrerenderMinZoom = 0;
+}
diff --git a/src/js/core/input_distributor.js b/src/js/core/input_distributor.js
index 8886947b..e0152774 100644
--- a/src/js/core/input_distributor.js
+++ b/src/js/core/input_distributor.js
@@ -201,7 +201,7 @@ export class InputDistributor {
// TAB
event.keyCode === 9 ||
// F1 - F10
- (event.keyCode >= 112 && event.keyCode < 122 && !G_IS_DEV)
+ (event.keyCode >= 112 && event.keyCode < 122)
) {
event.preventDefault();
}
diff --git a/src/js/core/loader.js b/src/js/core/loader.js
index 5c8e17ec..8888ecbf 100644
--- a/src/js/core/loader.js
+++ b/src/js/core/loader.js
@@ -84,7 +84,7 @@ class LoaderImpl {
return Promise.race([
new Promise((resolve, reject) => {
- setTimeout(reject, G_IS_DEV ? 3000 : 60000);
+ setTimeout(reject, G_IS_DEV ? 500 : 10000);
}),
new Promise(resolve => {
diff --git a/src/js/core/query_parameters.js b/src/js/core/query_parameters.js
index 7bc09b37..b3dab1b3 100644
--- a/src/js/core/query_parameters.js
+++ b/src/js/core/query_parameters.js
@@ -3,13 +3,8 @@ const options = queryString.parse(location.search);
export let queryParamOptions = {
embedProvider: null,
- betaMode: null,
};
if (options.embed) {
queryParamOptions.embedProvider = options.embed;
}
-
-if (!G_IS_RELEASE && options.betamode) {
- queryParamOptions.betaMode = true;
-}
diff --git a/src/js/game/camera.js b/src/js/game/camera.js
index c95970c1..7fb25b32 100644
--- a/src/js/game/camera.js
+++ b/src/js/game/camera.js
@@ -715,10 +715,6 @@ export class Camera extends BasicSerializableObject {
if (G_IS_DEV && globalConfig.debug.disableZoomLimits) {
return;
}
- if (queryParamOptions.betaMode) {
- return;
- }
-
const wrapper = this.root.app.platformWrapper;
assert(Number.isFinite(this.zoomLevel), "Invalid zoom level *before* clamp: " + this.zoomLevel);
diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js
index 6c155165..f1fc15c9 100644
--- a/src/js/game/hub_goals.js
+++ b/src/js/game/hub_goals.js
@@ -145,9 +145,6 @@ export class HubGoals extends BasicSerializableObject {
if (G_IS_DEV && globalConfig.debug.allBuildingsUnlocked) {
return true;
}
- if (queryParamOptions.betaMode) {
- return true;
- }
return !!this.gainedRewards[reward];
}
@@ -233,9 +230,6 @@ export class HubGoals extends BasicSerializableObject {
if (G_IS_DEV && globalConfig.debug.upgradesNoCost) {
return true;
}
- if (queryParamOptions.betaMode) {
- return true;
- }
const tierData = handle.tiers[currentLevel];
@@ -282,8 +276,6 @@ export class HubGoals extends BasicSerializableObject {
if (G_IS_DEV && globalConfig.debug.upgradesNoCost) {
// Dont take resources
- } else if (queryParamOptions.betaMode) {
- // Same
} else {
for (let i = 0; i < tierData.required.length; ++i) {
const requirement = tierData.required[i];
diff --git a/src/js/game/hud/parts/unlock_notification.js b/src/js/game/hud/parts/unlock_notification.js
index 612d900d..570d04d9 100644
--- a/src/js/game/hud/parts/unlock_notification.js
+++ b/src/js/game/hud/parts/unlock_notification.js
@@ -8,6 +8,7 @@ import { enumHubGoalRewards } from "../../tutorial_goals";
import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals_mappings";
+import { InputReceiver } from "../../../core/input_receiver";
export class HUDUnlockNotification extends BaseHUDPart {
initialize() {
@@ -25,6 +26,8 @@ export class HUDUnlockNotification extends BaseHUDPart {
}
createElements(parent) {
+ this.inputReciever = new InputReceiver("unlock-notification");
+
this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", []);
const dialog = makeDiv(this.element, null, ["dialog"]);
@@ -47,6 +50,7 @@ export class HUDUnlockNotification extends BaseHUDPart {
* @param {enumHubGoalRewards} reward
*/
showForLevel(level, reward) {
+ this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
this.elemTitle.innerText = T.ingame.levelCompleteNotification.levelTitle.replace(
"",
("" + level).padStart(2, "0")
@@ -92,6 +96,7 @@ export class HUDUnlockNotification extends BaseHUDPart {
}
cleanup() {
+ this.root.app.inputMgr.makeSureDetached(this.inputReciever);
if (this.buttonShowTimeout) {
clearTimeout(this.buttonShowTimeout);
this.buttonShowTimeout = null;
@@ -101,10 +106,19 @@ export class HUDUnlockNotification extends BaseHUDPart {
requestClose() {
this.root.app.adProvider.showVideoAd().then(() => {
this.close();
+ if (this.root.hubGoals.level === 3) {
+ const { showUpgrades } = this.root.hud.parts.dialogs.showInfo(
+ T.dialogs.upgradesIntroduction.title,
+ T.dialogs.upgradesIntroduction.desc,
+ ["showUpgrades:good:timeout"]
+ );
+ showUpgrades.add(() => this.root.hud.parts.shop.show());
+ }
});
}
close() {
+ this.root.app.inputMgr.makeSureDetached(this.inputReciever);
if (this.buttonShowTimeout) {
clearTimeout(this.buttonShowTimeout);
this.buttonShowTimeout = null;
diff --git a/src/js/game/tutorial_goals.js b/src/js/game/tutorial_goals.js
index 83aca89c..b2f5b0ef 100644
--- a/src/js/game/tutorial_goals.js
+++ b/src/js/game/tutorial_goals.js
@@ -30,20 +30,23 @@ export const enumHubGoalRewards = {
};
export const tutorialGoals = [
+ // 1
// Circle
{
shape: "CuCuCuCu", // belts t1
- required: 60,
+ required: 35,
reward: enumHubGoalRewards.reward_cutter_and_trash,
},
+ // 2
// Cutter
{
shape: "----CuCu", //
- required: 80,
+ required: 50,
reward: enumHubGoalRewards.no_reward,
},
+ // 3
// Rectangle
{
shape: "RuRuRuRu", // miners t1
@@ -51,12 +54,14 @@ export const tutorialGoals = [
reward: enumHubGoalRewards.reward_splitter,
},
+ // 4
{
shape: "RuRu----", // processors t2
- required: 350,
+ required: 150,
reward: enumHubGoalRewards.reward_rotater,
},
+ // 5
// Rotater
{
shape: "Cu----Cu", // belts t2
@@ -64,25 +69,29 @@ export const tutorialGoals = [
reward: enumHubGoalRewards.reward_tunnel,
},
+ // 6
{
shape: "Cu------", // miners t2
- required: 1000,
+ required: 700,
reward: enumHubGoalRewards.reward_painter,
},
+ // 7
// Painter
{
shape: "CrCrCrCr", // unused
- required: 1500,
+ required: 1300,
reward: enumHubGoalRewards.reward_rotater_ccw,
},
+ // 8
{
shape: "RbRb----", // painter t2
required: 2500,
reward: enumHubGoalRewards.reward_mixer,
},
+ // 9
// Mixing (purple)
{
shape: "CpCpCpCp", // belts t3
@@ -90,6 +99,7 @@ export const tutorialGoals = [
reward: enumHubGoalRewards.reward_splitter_compact,
},
+ // 10
// Star shape + cyan
{
shape: "ScScScSc", // miners t3
@@ -97,6 +107,7 @@ export const tutorialGoals = [
reward: enumHubGoalRewards.reward_stacker,
},
+ // 11
// Stacker
{
shape: "CgScScCg", // processors t3
@@ -104,36 +115,42 @@ export const tutorialGoals = [
reward: enumHubGoalRewards.reward_miner_chainable,
},
+ // 12
{
shape: "RpRpRpRp:CwCwCwCw", // painting t3
required: 7000,
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
},
+ // 13
{
shape: "SrSrSrSr:CyCyCyCy", // unused
required: 7850,
reward: enumHubGoalRewards.reward_storage,
},
+ // 14
{
shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants)
required: 8000,
reward: enumHubGoalRewards.reward_cutter_quad,
},
+ // 15
{
shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants)
required: 9000,
reward: enumHubGoalRewards.reward_painter_double,
},
+ // 16
{
shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", // processors t4 (two varinats)
required: 10000,
reward: enumHubGoalRewards.reward_painter_quad,
},
+ // 17
{
shape: finalGameShape,
required: 50000,
diff --git a/src/js/game/upgrades.js b/src/js/game/upgrades.js
index 4260f7f9..8864c5e2 100644
--- a/src/js/game/upgrades.js
+++ b/src/js/game/upgrades.js
@@ -97,7 +97,7 @@ export const UPGRADES = {
painting: {
tiers: [
{
- required: [{ shape: "WrWrWrWr", amount: 2000 }],
+ required: [{ shape: "WrWrWrWr", amount: 500 }],
improvement: 1,
},
{
diff --git a/src/js/globals.d.ts b/src/js/globals.d.ts
index 7e84d86a..977e8ff3 100644
--- a/src/js/globals.d.ts
+++ b/src/js/globals.d.ts
@@ -107,8 +107,6 @@ declare interface Window {
assert(condition: boolean, failureMessage: string);
coreThreadLoadedCb();
-
- gameanalytics: typeof import("./game_analytics");
}
declare interface Navigator {
diff --git a/src/js/platform/browser/game_analytics.js b/src/js/platform/browser/game_analytics.js
index 2efc458f..be1a8940 100644
--- a/src/js/platform/browser/game_analytics.js
+++ b/src/js/platform/browser/game_analytics.js
@@ -137,7 +137,8 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
ingameTime: root.time.now(),
category,
value,
- gameDump: this.generateGameDump(root),
+ version: G_BUILD_VERSION,
+ gameDump: this.generateGameDump(root, category === "sync"),
});
}
@@ -152,14 +153,15 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
/**
* Generates a game dump
* @param {GameRoot} root
+ * @param {boolean=} metaOnly
*/
- generateGameDump(root) {
+ generateGameDump(root, metaOnly = false) {
let staticEntities = [];
const entities = root.entityMgr.getAllWithComponent(StaticMapEntityComponent);
// Limit the entities
- if (entities.length < 5000) {
+ if (!metaOnly && entities.length < 500) {
for (let i = 0; i < entities.length; ++i) {
const entity = entities[i];
const staticComp = entity.components.StaticMapEntity;
diff --git a/src/js/platform/browser/sound.js b/src/js/platform/browser/sound.js
index 32985bb5..508dcf8c 100644
--- a/src/js/platform/browser/sound.js
+++ b/src/js/platform/browser/sound.js
@@ -23,7 +23,7 @@ class SoundSpritesContainer {
}
return (this.loadingPromise = Promise.race([
new Promise((resolve, reject) => {
- setTimeout(reject, G_IS_DEV ? 5000 : 60000);
+ setTimeout(reject, G_IS_DEV ? 500 : 5000);
}),
new Promise(resolve => {
this.howl = new Howl({
@@ -100,7 +100,7 @@ class MusicInstance extends MusicInstanceInterface {
load() {
return Promise.race([
new Promise((resolve, reject) => {
- setTimeout(reject, G_IS_DEV ? 5000 : 60000);
+ setTimeout(reject, G_IS_DEV ? 500 : 5000);
}),
new Promise((resolve, reject) => {
this.howl = new Howl({
diff --git a/src/js/platform/browser/storage_indexed_db.js b/src/js/platform/browser/storage_indexed_db.js
index 3d29c246..0c1dbe4f 100644
--- a/src/js/platform/browser/storage_indexed_db.js
+++ b/src/js/platform/browser/storage_indexed_db.js
@@ -34,10 +34,12 @@ export class StorageImplBrowserIndexedDB extends StorageInterface {
reject("Indexed DB access error");
};
+ // @ts-ignore
request.onsuccess = event => resolve(event.target.result);
request.onupgradeneeded = /** @type {IDBVersionChangeEvent} */ event => {
/** @type {IDBDatabase} */
+ // @ts-ignore
const database = event.target.result;
const objectStore = database.createObjectStore("files", {
diff --git a/src/js/platform/browser/wrapper.js b/src/js/platform/browser/wrapper.js
index 32c0e5f3..fa3f80b3 100644
--- a/src/js/platform/browser/wrapper.js
+++ b/src/js/platform/browser/wrapper.js
@@ -1,5 +1,5 @@
import { Math_min } from "../../core/builtins";
-import { globalConfig, IS_MOBILE } from "../../core/config";
+import { globalConfig, IS_MOBILE, IS_DEBUG, IS_DEMO } from "../../core/config";
import { createLogger } from "../../core/logging";
import { queryParamOptions } from "../../core/query_parameters";
import { clamp } from "../../core/utils";
@@ -19,6 +19,8 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
iframed: false,
externalLinks: true,
iogLink: true,
+ unlimitedSavegames: IS_DEMO ? false : true,
+ showDemoBadge: IS_DEMO,
};
if (!G_IS_STANDALONE && queryParamOptions.embedProvider) {
@@ -35,6 +37,8 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
case "iogames.space": {
this.embedProvider.id = "iogames.space";
this.embedProvider.iogLink = true;
+ this.embedProvider.unlimitedSavegames = true;
+ this.embedProvider.showDemoBadge = false;
break;
}
@@ -71,6 +75,14 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
return super.initialize().then(() => this.initializeAdProvider());
}
+ getHasUnlimitedSavegames() {
+ return this.embedProvider.unlimitedSavegames;
+ }
+
+ getShowDemoBadges() {
+ return this.embedProvider.showDemoBadge;
+ }
+
onSentryLoaded() {
logger.log("Initializing sentry");
window.Sentry.init({
diff --git a/src/js/platform/wrapper.js b/src/js/platform/wrapper.js
index a7b5c807..5754a8a2 100644
--- a/src/js/platform/wrapper.js
+++ b/src/js/platform/wrapper.js
@@ -29,6 +29,17 @@ export class PlatformWrapperInterface {
return false;
}
+ /**
+ * Whether the user has unlimited savegames
+ */
+ getHasUnlimitedSavegames() {
+ return true;
+ }
+
+ getShowDemoBadges() {
+ return false;
+ }
+
/**
* Returns the strength of touch pans with the mouse
*/
diff --git a/src/js/savegame/savegame_interface.js b/src/js/savegame/savegame_interface.js
index aeec062f..8671471d 100644
--- a/src/js/savegame/savegame_interface.js
+++ b/src/js/savegame/savegame_interface.js
@@ -26,7 +26,6 @@ export class BaseSavegameInterface {
*/
getSchemaUncached() {
throw new Error("Implement get schema");
- return {};
}
getValidator() {
diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js
index 1c9d5010..9dd18909 100644
--- a/src/js/states/main_menu.js
+++ b/src/js/states/main_menu.js
@@ -54,7 +54,11 @@ export class MainMenuState extends GameState {
- ${IS_DEMO ? `
` : ""}
+ ${
+ IS_DEMO && this.app.platformWrapper.getShowDemoBadges()
+ ? `
`
+ : ""
+ }
@@ -93,7 +97,7 @@ export class MainMenuState extends GameState {
G_IS_BROWSER &&
this.app.platformWrapper instanceof PlatformWrapperImplBrowser &&
this.app.platformWrapper.embedProvider.iogLink
- ? `More .io games`
+ ? `.io games`
: ""
}
@@ -104,7 +108,11 @@ export class MainMenuState extends GameState {
}
requestImportSavegame() {
- if (IS_DEMO && this.app.savegameMgr.getSavegamesMetaData().length > 0) {
+ if (
+ IS_DEMO &&
+ this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
+ !this.app.platformWrapper.getHasUnlimitedSavegames()
+ ) {
this.app.analytics.trackUiClick("importgame_slot_limit_show");
this.dialogs.showWarning(T.dialogs.oneSavegameLimit.title, T.dialogs.oneSavegameLimit.desc);
return;
@@ -122,6 +130,7 @@ export class MainMenuState extends GameState {
const closeLoader = this.dialogs.showLoadingDialog();
const reader = new FileReader();
reader.addEventListener("load", event => {
+ // @ts-ignore
const contents = event.target.result;
let realContent;
@@ -372,7 +381,11 @@ export class MainMenuState extends GameState {
}
onPlayButtonClicked() {
- if (IS_DEMO && this.app.savegameMgr.getSavegamesMetaData().length > 0) {
+ if (
+ IS_DEMO &&
+ this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
+ !this.app.platformWrapper.getHasUnlimitedSavegames()
+ ) {
this.app.analytics.trackUiClick("startgame_slot_limit_show");
this.dialogs.showWarning(T.dialogs.oneSavegameLimit.title, T.dialogs.oneSavegameLimit.desc);
return;
diff --git a/src/js/states/preload.js b/src/js/states/preload.js
index c12972e0..43c84eb0 100644
--- a/src/js/states/preload.js
+++ b/src/js/states/preload.js
@@ -186,7 +186,8 @@ export class PreloadState extends GameState {
return G_BUILD_VERSION;
})
.then(version => {
- this.app.storage.writeFileAsync("lastversion.bin", version);
+ logger.log("Last version:", version, "App version:", G_BUILD_VERSION);
+ this.app.storage.writeFileAsync("lastversion.bin", G_BUILD_VERSION);
return version;
})
.then(version => {
diff --git a/translations/base-en.yaml b/translations/base-en.yaml
index d3fe6aca..2e5cfd4c 100644
--- a/translations/base-en.yaml
+++ b/translations/base-en.yaml
@@ -89,6 +89,7 @@ dialogs:
getStandalone: Get Standalone
deleteGame: I know what I do
viewUpdate: View Update
+ showUpgrades: Show Upgrades
importSavegameError:
title: Import Error
@@ -165,6 +166,12 @@ dialogs:
desc: >-
Whenever you need help or are stuck, check out the 'Show hint' button in the lower left and I'll give my best to help you!
+ upgradesIntroduction:
+ title: Unlock Upgrades
+ desc: >-
+ All shapes you produce can be used to unlock upgrades - Don't destroy your old factories!
+ The upgrades tab can be found on the top right corner of the screen.
+
ingame:
# This is shown in the top left corner and displays useful keybindings in
# every situation
@@ -277,7 +284,7 @@ shopUpgrades:
name: Extraction
description: Speed +%
processors:
- name: Shape Processing
+ name: Cutting, Rotating & Stacking
description: Speed +%
painting:
name: Mixing & Painting
diff --git a/version b/version
index e6d5cb83..a6a3a43c 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.0.2
\ No newline at end of file
+1.0.4
\ No newline at end of file