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 { @@ -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