diff --git a/artwork/steam/announcement-cover.png b/artwork/steam/announcement-cover.png new file mode 100644 index 00000000..60af9100 Binary files /dev/null and b/artwork/steam/announcement-cover.png differ diff --git a/artwork/steam/announcement.png b/artwork/steam/announcement.png index 9a6b79f5..1aacc62e 100644 Binary files a/artwork/steam/announcement.png and b/artwork/steam/announcement.png differ diff --git a/artwork/steam/announcement.psd b/artwork/steam/announcement.psd index 6f0b201c..30dce1e6 100644 --- a/artwork/steam/announcement.psd +++ b/artwork/steam/announcement.psd @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c91adcd4e00006ffa4aed4db19d1530bf8c58935b1624d1640fc8e9465a2824 -size 176993 +oid sha256:ebde52e75e54d2f4add0cf498c85f059082a0745212a23c4de7328a7d78b00a5 +size 238170 diff --git a/artwork/steam/devlog.png b/artwork/steam/devlog.png new file mode 100644 index 00000000..8e5c29e6 Binary files /dev/null and b/artwork/steam/devlog.png differ diff --git a/artwork/steam/devlog.psd b/artwork/steam/devlog.psd new file mode 100644 index 00000000..0c06ba5d --- /dev/null +++ b/artwork/steam/devlog.psd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:746c6cf3f0284798a78c08f77d7e9d0c28b02323081fda42b5fa876a7ade29a0 +size 205925 diff --git a/artwork/wires/prefab.png b/artwork/wires/prefab.png new file mode 100644 index 00000000..99df19b8 Binary files /dev/null and b/artwork/wires/prefab.png differ diff --git a/artwork/wires/prefab.psd b/artwork/wires/prefab.psd new file mode 100644 index 00000000..71c38097 --- /dev/null +++ b/artwork/wires/prefab.psd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:498dea7314b8720c40dcd8bdd64b1b4a7a35259b2ffe7e896fc3db22878d6414 +size 1954036 diff --git a/gulp/sounds.js b/gulp/sounds.js index 1b18278d..0e8dee12 100644 --- a/gulp/sounds.js +++ b/gulp/sounds.js @@ -29,7 +29,7 @@ function gulptasksSounds($, gulp, buildFolder) { .audioChannels(1) .audioFrequency(22050) .audioCodec("libmp3lame") - .audioFilters(["volume=0.3"]); + .audioFilters(["volume=0.15"]); }), { name: "music", diff --git a/res/ui/languages/zh-CN.svg b/res/ui/languages/zh-CN.svg new file mode 100644 index 00000000..f89219a0 --- /dev/null +++ b/res/ui/languages/zh-CN.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res_raw/sounds/music/theme.mp3 b/res_raw/sounds/music/theme.mp3 deleted file mode 100644 index 66b78e55..00000000 --- a/res_raw/sounds/music/theme.mp3 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f61e851402fbc92d6909912fb203c63258fedbdea83e81f7ececb5091f4bee03 -size 3732550 diff --git a/res_raw/sounds/music/theme.wav b/res_raw/sounds/music/theme.wav new file mode 100644 index 00000000..a2014603 --- /dev/null +++ b/res_raw/sounds/music/theme.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c334a9f100fce4647b4803d2a8270b30e26d53622b3717bdb81b3ea07f84aed +size 150286082 diff --git a/src/css/common.scss b/src/css/common.scss index 22b39cb9..6a87012e 100644 --- a/src/css/common.scss +++ b/src/css/common.scss @@ -38,6 +38,10 @@ html { right: 0; background: #dee1ea; + + @include DarkThemeOverride { + background: $darkModeGameBackground; + } } body { @@ -413,6 +417,10 @@ canvas { display: inline-block; vertical-align: middle; } + + @include DarkThemeOverride { + color: #fff; + } } .prefab_LoadingTextWithAnimDelayed { diff --git a/src/css/icons.scss b/src/css/icons.scss index c66b87ae..2128fde3 100644 --- a/src/css/icons.scss +++ b/src/css/icons.scss @@ -27,7 +27,7 @@ $icons: notification_saved, notification_success, notification_upgrade; } } -$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, nb, mt-MT, ar, nl, vi, th, +$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi, th, hu, pl, ja, kor, no, pt-PT; @each $language in $languages { diff --git a/src/css/ingame_hud/building_placer.scss b/src/css/ingame_hud/building_placer.scss index 99c4d654..e63868ab 100644 --- a/src/css/ingame_hud/building_placer.scss +++ b/src/css/ingame_hud/building_placer.scss @@ -75,6 +75,15 @@ @include StyleBelowWidth(700px) { display: none !important; } + + &.compact { + width: unset !important; + grid-template-columns: 1fr; + .buildingImage, + .description > .text { + display: none; + } + } } #ingame_HUD_PlacerVariants { @@ -86,6 +95,10 @@ flex-direction: column; align-items: flex-end; + &.compact { + @include S(top, 150px); + } + .explanation { text-transform: uppercase; grid-row: 1 / 2; diff --git a/src/css/ingame_hud/dialogs.scss b/src/css/ingame_hud/dialogs.scss index 366ab8ce..d72265e7 100644 --- a/src/css/ingame_hud/dialogs.scss +++ b/src/css/ingame_hud/dialogs.scss @@ -21,15 +21,32 @@ } } + $darkModeDialogBg: darken($darkModeGameBackground, 10); + @include DarkThemeOverride { - background: rgba(#33363d, 0.9); + background: rgba($darkModeDialogBg, 0.9); @include InlineAnimation(0.12s ease-in-out) { 0% { background-color: transparent; opacity: 0.5; } 100% { - background-color: rgba(#33363d, 0.9); + background-color: rgba($darkModeDialogBg, 0.9); + } + } + + > .dialogInner.optionChooserDialog .optionParent { + .option { + background: #3d3f42; + + &:hover { + background-color: #424348; + } + + &.active { + background: $colorBlueBright; + color: #fff; + } } } } diff --git a/src/css/ingame_hud/keybindings_overlay.scss b/src/css/ingame_hud/keybindings_overlay.scss index 6d0f99c8..38b560d8 100644 --- a/src/css/ingame_hud/keybindings_overlay.scss +++ b/src/css/ingame_hud/keybindings_overlay.scss @@ -14,6 +14,10 @@ } > .binding { + &:not(.visible) { + display: none !important; + } + display: inline-grid; @include PlainText; align-items: center; @@ -57,50 +61,6 @@ @include S(margin-left, 5px); } } - - &:not(.placementActive) .binding.placementOnly, - &.mapOverviewActive .binding.placementOnly { - display: none; - } - - &.placementActive:not(.mapOverviewActive) .noPlacementOnly { - display: none; - } - - &:not(.mapOverviewActive) .binding.overviewOnly { - display: none; - } - - &.mapOverviewActive .noOverviewOnly { - display: none; - } - - &:not(.hasDirectionLock) .binding.directionLock { - display: none; - } - - &.hasDirectionLock .noDirectionLock { - display: none; - } - - .binding.placementOnly, - &:not(.placementActive) .binding.noPlacementOnly { - transform-origin: 0% 50%; - @include InlineAnimation(0.3s ease-in-out) { - 0% { - color: $colorRedBright; - transform: scale(1.2); - } - } - } - - .keybinding.builtinKey { - transition: all 0.1s ease-in-out; - transition-property: background-color, color, border-color; - background: $colorRedBright; - border-color: $colorRedBright; - color: #fff; - } } body.uiHidden #ingame_HUD_KeybindingOverlay .binding:not(.hudToggle) { diff --git a/src/css/ingame_hud/mass_selector.scss b/src/css/ingame_hud/mass_selector.scss deleted file mode 100644 index ddd2d40a..00000000 --- a/src/css/ingame_hud/mass_selector.scss +++ /dev/null @@ -1,22 +0,0 @@ -#ingame_HUD_MassSelector { - position: absolute; - @include S(top, 50px); - left: 50%; - transform: translateX(-50%); - background: $ingameHudBg; - @include S(padding, 6px, 10px); - @include SuperSmallText; - color: #fff; - // color: #f77; - - .keybinding { - vertical-align: middle; - @include S(margin, 0, 1px); - position: relative; - top: unset; - left: unset; - right: unset; - bottom: unset; - @include S(margin-top, -2px); - } -} diff --git a/src/css/ingame_hud/waypoints.scss b/src/css/ingame_hud/waypoints.scss index ab8fed39..fecb2c66 100644 --- a/src/css/ingame_hud/waypoints.scss +++ b/src/css/ingame_hud/waypoints.scss @@ -29,7 +29,7 @@ #ingame_HUD_Waypoints { position: absolute; @include S(right, 10px); - @include S(top, 60px); + @include S(top, 45px); display: flex; flex-direction: column; @include DarkThemeInvert(); diff --git a/src/css/main.scss b/src/css/main.scss index 10bf384e..178f398b 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -37,7 +37,6 @@ @import "ingame_hud/shop"; @import "ingame_hud/game_menu"; @import "ingame_hud/dialogs"; -@import "ingame_hud/mass_selector"; @import "ingame_hud/vignette_overlay"; @import "ingame_hud/statistics"; @import "ingame_hud/pinned_shapes"; @@ -67,7 +66,6 @@ ingame_HUD_PinnedShapes, ingame_HUD_GameMenu, ingame_HUD_KeybindingOverlay, ingame_HUD_Notifications, -ingame_HUD_MassSelector, ingame_HUD_DebugInfo, ingame_HUD_EntityDebugger, ingame_HUD_InteractiveTutorial, @@ -101,7 +99,6 @@ body.uiHidden { #ingame_HUD_buildings_toolbar, #ingame_HUD_PlacementHints, #ingame_HUD_GameMenu, - #ingame_HUD_MassSelector, #ingame_HUD_PinnedShapes, #ingame_HUD_Notifications, #ingame_HUD_TutorialHints, @@ -115,6 +112,6 @@ body.modalDialogActive, body.externalAdOpen, body.ingameDialogOpen { > *:not(.ingameDialog):not(.modalDialogParent):not(.loadingDialog):not(.gameLoadingOverlay):not(#ingame_HUD_ModalDialogs):not(.noBlur) { - filter: blur(5px) !important; + // filter: blur(5px) !important; } } diff --git a/src/css/mixins.scss b/src/css/mixins.scss index dc5eeb86..ee0a9752 100644 --- a/src/css/mixins.scss +++ b/src/css/mixins.scss @@ -350,7 +350,7 @@ button, } @mixin DarkThemeOverride { - @at-root body[data-theme="dark"] &, + @at-root html[data-theme="dark"] &, &[data-theme="dark"] { @content; } diff --git a/src/css/states/ingame.scss b/src/css/states/ingame.scss index 8b0a614c..3f220a5d 100644 --- a/src/css/states/ingame.scss +++ b/src/css/states/ingame.scss @@ -28,4 +28,10 @@ right: 0; bottom: 0; } + + @include DarkThemeOverride { + .gameLoadingOverlay { + background: $darkModeGameBackground; + } + } } diff --git a/src/css/states/keybindings.scss b/src/css/states/keybindings.scss index f5ee3170..cf211403 100644 --- a/src/css/states/keybindings.scss +++ b/src/css/states/keybindings.scss @@ -51,4 +51,21 @@ } } } + + @include DarkThemeOverride { + .content { + .hint { + background: #3b3d40; + } + + .category .entry { + color: #c0c4c8; + border-bottom-color: #888; + + button { + filter: invert(1); + } + } + } + } } diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss index a10390b8..fa9d430c 100644 --- a/src/css/states/main_menu.scss +++ b/src/css/states/main_menu.scss @@ -401,4 +401,44 @@ } } } + + @include DarkThemeOverride { + background: $darkModeGameBackground center center / cover !important; + + .topButtons { + filter: invert(1); + + .languageChoose { + filter: invert(1); + } + } + + .mainContainer { + background: darken($darkModeGameBackground, 10); + + .savegames .savegame { + background: darken($darkModeGameBackground, 15); + color: white; + } + } + + .footer { + > a { + background: darken($darkModeGameBackground, 10); + color: #eee; + } + + .author { + color: #bdbdbd; + + > a { + color: white; + } + } + + .thirdpartyLogo.githubLogo { + filter: invert(1); + } + } + } } diff --git a/src/css/states/settings.scss b/src/css/states/settings.scss index e52152c3..f06c9b31 100644 --- a/src/css/states/settings.scss +++ b/src/css/states/settings.scss @@ -88,4 +88,26 @@ } } } + + @include DarkThemeOverride { + .content { + .setting { + background: darken($darkModeGameBackground, 10); + + .value.enum { + // dirty but works + filter: invert(0.85); + color: #222; + } + + .value.checkbox { + background-color: #74767b; + + &.checked { + background-color: $colorBlueBright; + } + } + } + } + } } diff --git a/src/css/textual_game_state.scss b/src/css/textual_game_state.scss index 897c379a..a8d7a31f 100644 --- a/src/css/textual_game_state.scss +++ b/src/css/textual_game_state.scss @@ -61,4 +61,21 @@ } } } + + @include DarkThemeOverride { + .headerBar { + h1 { + color: #e2e0db; + } + + .backButton { + filter: invert(1); + } + } + + > .container > .content { + background: darken($darkModeGameBackground, 3); + color: #eee; + } + } } diff --git a/src/css/variables.scss b/src/css/variables.scss index 5f056a00..c1c69371 100644 --- a/src/css/variables.scss +++ b/src/css/variables.scss @@ -38,6 +38,8 @@ $ingameHudBg: rgba(#333438, 0.9); $text3dColor: #f4ffff; +$darkModeGameBackground: #5c606c; + // Dialog properties $modalDialogBg: rgba(160, 165, 180, 0.8); $dialogBgColor: lighten($mainBgColor, 10); diff --git a/src/js/changelog.js b/src/js/changelog.js index 280ea50e..fa41760b 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -1,8 +1,26 @@ export const CHANGELOG = [ { version: "1.1.16", - date: "unreleased", - entries: ["Fix belt planner not placing the last belt"], + date: "21.06.2020", + entries: [ + "You can now pickup buildings below your cursor with 'Q'!", + "The game soundtrack has been extended! There are now 4 songs with over 13 minutes of playtime from Peppsen!", + "Refactor keybindings overlay to show more appropriate keybindings", + "Show keybindings for area-select in the upper left instead", + "Automatically deselect area when selecting a new building", + "Raise markers limit from 14 characters to 71 (by Joker-vD)", + "Optimize performance by caching extractor items (by Phlosioneer)", + "Added setting to enable compact building infos, which only show ratios and hide the image / description", + "Apply dark theme to menu as well (by dengr1065)", + "Fix belt planner not placing the last belt", + "Fix buildings getting deleted when right clicking while placing a blueprint", + "Fix for exporting screenshots for huge bases (It was showing an empty file) (by xSparfuchs)", + "Fix buttons not responding when using right click directly after left click (by davidburhans)", + "Fix hub marker being hidden by building info panel", + "Disable dialog background blur since it can cause performance issues", + "Added simplified chinese translations", + "Update translations (Thanks to all translators!)", + ], }, { version: "1.1.15", diff --git a/src/js/core/click_detector.js b/src/js/core/click_detector.js index f4197721..508e9375 100644 --- a/src/js/core/click_detector.js +++ b/src/js/core/click_detector.js @@ -325,6 +325,7 @@ export class ClickDetector { // Ignore right clicks this.rightClick.dispatch(position, event); this.cancelled = true; + this.clickDownPosition = null; return; } } diff --git a/src/js/game/canvas_click_interceptor.js b/src/js/game/canvas_click_interceptor.js deleted file mode 100644 index 675c1387..00000000 --- a/src/js/game/canvas_click_interceptor.js +++ /dev/null @@ -1,70 +0,0 @@ -import { STOP_PROPAGATION } from "../core/signal"; -import { GameRoot } from "./root"; -import { ClickDetector } from "../core/click_detector"; -import { createLogger } from "../core/logging"; - -const logger = createLogger("canvas_click_interceptor"); - -export class CanvasClickInterceptor { - /** - * @param {GameRoot} root - */ - constructor(root) { - this.root = root; - - this.root.signals.postLoadHook.add(this.initialize, this); - this.root.signals.aboutToDestruct.add(this.cleanup, this); - - /** @type {Array} */ - this.interceptors = []; - } - - initialize() { - this.clickDetector = new ClickDetector(this.root.canvas, { - applyCssClass: null, - captureTouchmove: false, - targetOnly: true, - preventDefault: true, - maxDistance: 13, - clickSound: null, - }); - this.clickDetector.click.add(this.onCanvasClick, this); - this.clickDetector.rightClick.add(this.onCanvasRightClick, this); - - if (this.root.hud.parts.buildingPlacer) { - this.interceptors.push(this.root.hud.parts.buildingPlacer); - } - - logger.log("Registered", this.interceptors.length, "interceptors"); - } - - cleanup() { - if (this.clickDetector) { - this.clickDetector.cleanup(); - } - this.interceptors = []; - } - - onCanvasClick(position, event, cancelAction = false) { - if (!this.root.gameInitialized) { - logger.warn("Skipping click outside of game initiaization!"); - return; - } - - if (this.root.hud.hasBlockingOverlayOpen()) { - return; - } - - for (let i = 0; i < this.interceptors.length; ++i) { - const interceptor = this.interceptors[i]; - if (interceptor.onCanvasClick(position, cancelAction) === STOP_PROPAGATION) { - // log(this, "Interceptor", interceptor.constructor.name, "catched click"); - break; - } - } - } - - onCanvasRightClick(position, event) { - this.onCanvasClick(position, event, true); - } -} diff --git a/src/js/game/components/miner.js b/src/js/game/components/miner.js index 57de7e2f..74a4b616 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -12,6 +12,7 @@ export class MinerComponent extends Component { } static getSchema() { + // cachedMinedItem is not serialized. return { lastMiningTime: types.ufloat, chainable: types.bool, @@ -25,8 +26,6 @@ export class MinerComponent extends Component { }); } - /** - */ constructor({ chainable = false }) { super(); this.lastMiningTime = 0; @@ -38,6 +37,11 @@ export class MinerComponent extends Component { * @type {Array} */ this.itemChainBuffer = []; + + /** + * @type {BaseItem} + */ + this.cachedMinedItem = null; } /** diff --git a/src/js/game/core.js b/src/js/game/core.js index 8b1c464d..3fc02397 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -17,7 +17,6 @@ import { SavegameSerializer } from "../savegame/savegame_serializer"; import { AutomaticSave } from "./automatic_save"; import { MetaHubBuilding } from "./buildings/hub"; import { Camera } from "./camera"; -import { CanvasClickInterceptor } from "./canvas_click_interceptor"; import { EntityManager } from "./entity_manager"; import { GameSystemManager } from "./game_system_manager"; import { HubGoals } from "./hub_goals"; @@ -98,7 +97,6 @@ export class GameCore { root.logic = new GameLogic(root); root.hud = new GameHUD(root); root.time = new GameTime(root); - root.canvasClickInterceptor = new CanvasClickInterceptor(root); root.automaticSave = new AutomaticSave(root); root.soundProxy = new SoundProxy(root); diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js index 40338600..c322c707 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -34,6 +34,7 @@ import { HUDPartTutorialHints } from "./parts/tutorial_hints"; import { HUDWaypoints } from "./parts/waypoints"; import { HUDInteractiveTutorial } from "./parts/interactive_tutorial"; import { HUDScreenshotExporter } from "./parts/screenshot_exporter"; +import { Entity } from "../entity"; export class GameHUD { /** diff --git a/src/js/game/hud/parts/blueprint_placer.js b/src/js/game/hud/parts/blueprint_placer.js index fa9faca2..ef46f101 100644 --- a/src/js/game/hud/parts/blueprint_placer.js +++ b/src/js/game/hud/parts/blueprint_placer.js @@ -1,15 +1,15 @@ import { DrawParameters } from "../../../core/draw_parameters"; import { STOP_PROPAGATION } from "../../../core/signal"; import { TrackedState } from "../../../core/tracked_state"; +import { makeDiv } from "../../../core/utils"; import { Vector } from "../../../core/vector"; +import { T } from "../../../translations"; import { enumMouseButton } from "../../camera"; import { KEYMAPPINGS } from "../../key_action_mapper"; -import { BaseHUDPart } from "../base_hud_part"; -import { Blueprint } from "./blueprint"; -import { makeDiv } from "../../../core/utils"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; import { blueprintShape } from "../../upgrades"; -import { T } from "../../../translations"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { Blueprint } from "./blueprint"; export class HUDBlueprintPlacer extends BaseHUDPart { createElements(parent) { @@ -34,9 +34,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart { const keyActionMapper = this.root.keyMapper; keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this); - keyActionMapper - .getBinding(KEYMAPPINGS.placement.abortBuildingPlacement) - .add(this.abortPlacement, this); + keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this); keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this); keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this); @@ -62,10 +60,9 @@ export class HUDBlueprintPlacer extends BaseHUDPart { } update() { - this.domAttach.update(this.currentBlueprint.get()); - this.trackedCanAfford.set( - this.currentBlueprint.get() && this.currentBlueprint.get().canAfford(this.root) - ); + const currentBlueprint = this.currentBlueprint.get(); + this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0); + this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root)); } /** diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index 3a8ed0db..5faec6ab 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -38,6 +38,10 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { this.buildingInfoElements.tutorialImage = makeDiv(this.element, null, ["buildingImage"]); this.variantsElement = makeDiv(parent, "ingame_HUD_PlacerVariants"); + + const compact = this.root.app.settings.getAllSettings().compactBuildingInfo; + this.element.classList.toggle("compact", compact); + this.variantsElement.classList.toggle("compact", compact); } initialize() { diff --git a/src/js/game/hud/parts/building_placer_logic.js b/src/js/game/hud/parts/building_placer_logic.js index 92ce44bd..0da81d4a 100644 --- a/src/js/game/hud/parts/building_placer_logic.js +++ b/src/js/game/hud/parts/building_placer_logic.js @@ -1,5 +1,6 @@ import { Math_abs, Math_degrees, Math_round } from "../../../core/builtins"; import { globalConfig } from "../../../core/config"; +import { gMetaBuildingRegistry } from "../../../core/global_registries"; import { Signal, STOP_PROPAGATION } from "../../../core/signal"; import { TrackedState } from "../../../core/tracked_state"; import { Vector } from "../../../core/vector"; @@ -9,7 +10,6 @@ import { Entity } from "../../entity"; import { KEYMAPPINGS } from "../../key_action_mapper"; import { defaultBuildingVariant, MetaBuilding } from "../../meta_building"; import { BaseHUDPart } from "../base_hud_part"; -import { lerp } from "../../../core/utils"; /** * Contains all logic for the building placer - this doesn't include the rendering @@ -97,10 +97,8 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { keyActionMapper .getBinding(KEYMAPPINGS.placement.switchDirectionLockSide) .add(this.switchDirectionLockSide, this); - keyActionMapper - .getBinding(KEYMAPPINGS.placement.abortBuildingPlacement) - .add(this.abortPlacement, this); keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this); + keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this); this.root.gameState.inputReciever.keyup.add(this.checkForDirectionLockSwitch, this); // BINDINGS TO GAME EVENTS @@ -220,6 +218,125 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { } } + /** + * Starts the pipette function + */ + startPipette() { + // Disable in overview + if (this.root.camera.getIsMapOverlayActive()) { + return; + } + + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const worldPos = this.root.camera.screenToWorld(mousePosition); + const tile = worldPos.toTileSpace(); + const contents = this.root.map.getTileContent(tile); + + if (!contents) { + this.currentMetaBuilding.set(null); + return; + } + + // Try to extract the building + const extracted = this.hack_reconstructMetaBuildingAndVariantFromBuilding(contents); + if (!extracted) { + this.currentMetaBuilding.set(null); + return; + } + + this.currentMetaBuilding.set(extracted.metaBuilding); + this.currentVariant.set(extracted.variant); + this.currentBaseRotation = contents.components.StaticMapEntity.rotation; + + // Make sure we selected something, and also make sure it's not a special entity + // if (contents && !contents.components.Unremovable) { + + // } + } + + /** + * HACK! + * + * This attempts to reconstruct the meta building and its variant from a given entity + * @param {Entity} entity + * @returns {{ metaBuilding: MetaBuilding, variant: string }} + */ + hack_reconstructMetaBuildingAndVariantFromBuilding(entity) { + if (entity.components.Hub) { + // Hub is not copyable + return null; + } + + const matches = []; + const metaBuildings = gMetaBuildingRegistry.entries; + for (let i = 0; i < metaBuildings.length; ++i) { + const metaBuilding = metaBuildings[i]; + const availableVariants = metaBuilding.getAvailableVariants(this.root); + checkVariant: for (let k = 0; k < availableVariants.length; ++k) { + const variant = availableVariants[k]; + let unplaced = metaBuilding.createEntity({ + root: this.root, + variant, + origin: new Vector(0, 0), + rotation: 0, + originalRotation: 0, + rotationVariant: 0, + }); + + // Compare if both entities share the same components + for (let component in entity.components) { + if ((entity.components[component] == null) !== (unplaced.components[component] == null)) { + continue checkVariant; + } + } + + // Check for same item processor + if ( + entity.components.ItemProcessor && + entity.components.ItemProcessor.type != unplaced.components.ItemProcessor.type + ) { + continue checkVariant; + } + + // Check for underground belt + if ( + entity.components.UndergroundBelt && + entity.components.UndergroundBelt.tier != unplaced.components.UndergroundBelt.tier + ) { + continue checkVariant; + } + + // Check for same sprite key - except for underground belts + // since the sprite may vary here + if ( + !entity.components.UndergroundBelt && + entity.components.StaticMapEntity.spriteKey != + unplaced.components.StaticMapEntity.spriteKey + ) { + continue checkVariant; + } + matches.push({ metaBuilding, variant }); + } + } + + if (matches.length == 1) { + const staticEntity = entity.components.StaticMapEntity; + const key = staticEntity.spriteKey || staticEntity.blueprintSpriteKey; + assert( + key && + key.includes(matches[0].metaBuilding.id) && + (matches[0].variant === defaultBuildingVariant || key.includes(matches[0].variant)) + ); + return matches[0]; + } + return null; + } + switchDirectionLockSide() { this.currentDirectionLockSide = 1 - this.currentDirectionLockSide; } @@ -237,28 +354,6 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { } } - /** - * Canvas click handler - * @param {Vector} mousePos - * @param {boolean} cancelAction - */ - onCanvasClick(mousePos, cancelAction = false) { - if (cancelAction) { - if (this.currentMetaBuilding.get()) { - this.currentMetaBuilding.set(null); - } else { - this.deleteBelowCursor(); - } - return STOP_PROPAGATION; - } - - if (!this.currentMetaBuilding.get()) { - return; - } - - return STOP_PROPAGATION; - } - /** * Tries to place the current building at the given tile * @param {Vector} tile @@ -479,13 +574,18 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { } // Deletion - if (button === enumMouseButton.right && !this.currentMetaBuilding.get()) { + if (button === enumMouseButton.right && !metaBuilding) { this.currentlyDragging = true; this.currentlyDeleting = true; this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace(); - this.currentMetaBuilding.set(null); + this.deleteBelowCursor(); return STOP_PROPAGATION; } + + // Cancel placement + if (button === enumMouseButton.right && metaBuilding) { + this.currentMetaBuilding.set(null); + } } /** diff --git a/src/js/game/hud/parts/keybinding_overlay.js b/src/js/game/hud/parts/keybinding_overlay.js index e469bcca..5b7f4a9d 100644 --- a/src/js/game/hud/parts/keybinding_overlay.js +++ b/src/js/game/hud/parts/keybinding_overlay.js @@ -1,123 +1,316 @@ import { makeDiv } from "../../../core/utils"; import { T } from "../../../translations"; -import { getStringForKeyCode, KEYMAPPINGS } from "../../key_action_mapper"; +import { + getStringForKeyCode, + KEYCODE_LMB, + KEYCODE_MMB, + KEYCODE_RMB, + KEYMAPPINGS, +} from "../../key_action_mapper"; import { BaseHUDPart } from "../base_hud_part"; -import { TrackedState } from "../../../core/tracked_state"; -import { MetaBuilding } from "../../meta_building"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const DIVIDER_TOKEN = "/"; +const ADDER_TOKEN = "+"; + +/** + * @typedef {{ keyCode: number }} KeyCode + */ + +/** + * @typedef {{ + * condition: () => boolean, + * keys: Array, + * label: string, + * cachedElement?: HTMLElement, + * cachedVisibility?: boolean + * }} KeyBinding + */ export class HUDKeybindingOverlay extends BaseHUDPart { - initialize() { - this.root.hud.signals.selectedPlacementBuildingChanged.add( - this.onSelectedBuildingForPlacementChanged, - this - ); + initialize() {} - this.trackedMapOverviewActive = new TrackedState(this.applyCssClasses, this); + /** + * HELPER / Returns if there is a building selected for placement + * @returns {boolean} + */ + get buildingPlacementActive() { + const placer = this.root.hud.parts.buildingPlacer; + return !this.mapOverviewActive && placer && !!placer.currentMetaBuilding.get(); } - createElements(parent) { - const mapper = this.root.keyMapper; - - const getKeycode = id => { - return getStringForKeyCode(mapper.getBinding(id).keyCode); - }; - - this.element = makeDiv( - parent, - "ingame_HUD_KeybindingOverlay", - [], - ` - -
- - ${getKeycode(KEYMAPPINGS.navigation.mapMoveUp)} - ${getKeycode(KEYMAPPINGS.navigation.mapMoveLeft)} - ${getKeycode(KEYMAPPINGS.navigation.mapMoveDown)} - ${getKeycode(KEYMAPPINGS.navigation.mapMoveRight)} - -
- - - -
- - -
- -
- - -
- - -
- ${getKeycode( - KEYMAPPINGS.massSelect.massSelectStart - )}+ - - -
- -
- - -
- -
- - ${getKeycode(KEYMAPPINGS.placement.abortBuildingPlacement)} - -
- -
- ${getKeycode(KEYMAPPINGS.placement.rotateWhilePlacing)} - -
- - ` + - (this.root.app.settings.getAllSettings().alwaysMultiplace - ? "" - : ` -
- ${getKeycode( - KEYMAPPINGS.placementModifiers.placeMultiple - )} - -
`) + - ` - -
- ${getKeycode( - KEYMAPPINGS.placementModifiers.lockBeltDirection - )} - -
- -
- ${getKeycode(KEYMAPPINGS.placement.switchDirectionLockSide)} - -
- ` + /** + * HELPER / Returns if there is a building selected for placement and + * it supports the belt planner + * @returns {boolean} + */ + get buildingPlacementSupportsBeltPlanner() { + const placer = this.root.hud.parts.buildingPlacer; + return ( + !this.mapOverviewActive && + placer && + placer.currentMetaBuilding.get() && + placer.currentMetaBuilding.get().getHasDirectionLockAvailable() ); } /** - * - * @param {MetaBuilding} selectedMetaBuilding + * HELPER / Returns if there is a building selected for placement and + * it has multiplace enabled by default + * @returns {boolean} */ - onSelectedBuildingForPlacementChanged(selectedMetaBuilding) { - this.element.classList.toggle("placementActive", !!selectedMetaBuilding); - this.element.classList.toggle( - "hasDirectionLock", - selectedMetaBuilding && selectedMetaBuilding.getHasDirectionLockAvailable() + get buildingPlacementStaysInPlacement() { + const placer = this.root.hud.parts.buildingPlacer; + return ( + !this.mapOverviewActive && + placer && + placer.currentMetaBuilding.get() && + placer.currentMetaBuilding.get().getStayInPlacementMode() ); } - applyCssClasses() { - this.element.classList.toggle("mapOverviewActive", this.root.camera.getIsMapOverlayActive()); + /** + * HELPER / Returns if there is a blueprint selected for placement + * @returns {boolean} + */ + get blueprintPlacementActive() { + const placer = this.root.hud.parts.blueprintPlacer; + return placer && !!placer.currentBlueprint.get(); + } + + /** + * HELPER / Returns if the belt planner is currently active + * @returns {boolean} + */ + get beltPlannerActive() { + const placer = this.root.hud.parts.buildingPlacer; + return !this.mapOverviewActive && placer && placer.isDirectionLockActive; + } + + /** + * HELPER / Returns if there is a last blueprint available + * @returns {boolean} + */ + get lastBlueprintAvailable() { + const placer = this.root.hud.parts.blueprintPlacer; + return placer && !!placer.lastBlueprintUsed; + } + + /** + * HELPER / Returns if there is anything selected on the map + * @returns {boolean} + */ + get anythingSelectedOnMap() { + const selector = this.root.hud.parts.massSelector; + return selector && selector.selectedUids.size > 0; + } + + /** + * HELPER / Returns if there is a building or blueprint selected for placement + * @returns {boolean} + */ + get anyPlacementActive() { + return this.buildingPlacementActive || this.blueprintPlacementActive; + } + + /** + * HELPER / Returns if the map overview is active + * @returns {boolean} + */ + get mapOverviewActive() { + return this.root.camera.getIsMapOverlayActive(); + } + + /** + * Initializes the element + * @param {HTMLElement} parent + */ + createElements(parent) { + const mapper = this.root.keyMapper; + const k = KEYMAPPINGS; + + /** @type {Array} */ + this.keybindings = [ + { + // Move map - Including mouse + label: T.ingame.keybindingsOverlay.moveMap, + keys: [ + KEYCODE_LMB, + DIVIDER_TOKEN, + k.navigation.mapMoveUp, + k.navigation.mapMoveLeft, + k.navigation.mapMoveDown, + k.navigation.mapMoveRight, + ], + condition: () => !this.anyPlacementActive, + }, + + { + // Move map - No mouse + label: T.ingame.keybindingsOverlay.moveMap, + keys: [ + k.navigation.mapMoveUp, + k.navigation.mapMoveLeft, + k.navigation.mapMoveDown, + k.navigation.mapMoveRight, + ], + condition: () => this.anyPlacementActive, + }, + + { + // [OVERVIEW] Create marker with right click + label: T.ingame.keybindingsOverlay.createMarker, + keys: [KEYCODE_RMB], + condition: () => this.mapOverviewActive && !this.blueprintPlacementActive, + }, + + { + // Pipette + label: T.ingame.keybindingsOverlay.pipette, + keys: [k.placement.pipette], + condition: () => !this.mapOverviewActive, + }, + + { + // Cancel placement + label: T.ingame.keybindingsOverlay.stopPlacement, + keys: [KEYCODE_RMB], + condition: () => this.anyPlacementActive, + }, + + { + // Delete with right click + label: T.ingame.keybindingsOverlay.delete, + keys: [KEYCODE_RMB], + condition: () => + !this.anyPlacementActive && !this.mapOverviewActive && !this.anythingSelectedOnMap, + }, + + { + // Area select + label: T.ingame.keybindingsOverlay.selectBuildings, + keys: [k.massSelect.massSelectStart, ADDER_TOKEN, KEYCODE_LMB], + condition: () => !this.anyPlacementActive && !this.anythingSelectedOnMap, + }, + + { + // Place building + label: T.ingame.keybindingsOverlay.placeBuilding, + keys: [KEYCODE_LMB], + condition: () => this.anyPlacementActive, + }, + + { + // Rotate + label: T.ingame.keybindingsOverlay.rotateBuilding, + keys: [k.placement.rotateWhilePlacing], + condition: () => this.anyPlacementActive && !this.beltPlannerActive, + }, + + { + // [BELT PLANNER] Flip Side + label: T.ingame.keybindingsOverlay.plannerSwitchSide, + keys: [k.placement.switchDirectionLockSide], + condition: () => this.beltPlannerActive, + }, + + { + // Place last blueprint + label: T.ingame.keybindingsOverlay.pasteLastBlueprint, + keys: [k.massSelect.pasteLastBlueprint], + condition: () => !this.blueprintPlacementActive && this.lastBlueprintAvailable, + }, + + { + // Belt planner + label: T.ingame.keybindingsOverlay.lockBeltDirection, + keys: [k.placementModifiers.lockBeltDirection], + condition: () => this.buildingPlacementSupportsBeltPlanner && !this.beltPlannerActive, + }, + + { + // [SELECTION] Destroy + label: T.ingame.keybindingsOverlay.delete, + keys: [k.massSelect.confirmMassDelete], + condition: () => this.anythingSelectedOnMap, + }, + + { + // [SELECTION] Cancel + label: T.ingame.keybindingsOverlay.clearSelection, + keys: [k.general.back], + condition: () => this.anythingSelectedOnMap, + }, + { + // [SELECTION] Cut + label: T.ingame.keybindingsOverlay.cutSelection, + keys: [k.massSelect.massSelectCut], + condition: () => this.anythingSelectedOnMap, + }, + + { + // [SELECTION] Copy + label: T.ingame.keybindingsOverlay.copySelection, + keys: [k.massSelect.massSelectCopy], + condition: () => this.anythingSelectedOnMap, + }, + ]; + + if (!this.root.app.settings.getAllSettings().alwaysMultiplace) { + this.keybindings.push({ + // Multiplace + label: T.ingame.keybindingsOverlay.placeMultiple, + keys: [k.placementModifiers.placeMultiple], + condition: () => this.anyPlacementActive && !this.buildingPlacementStaysInPlacement, + }); + } + + this.element = makeDiv(parent, "ingame_HUD_KeybindingOverlay", []); + + for (let i = 0; i < this.keybindings.length; ++i) { + let html = ""; + const handle = this.keybindings[i]; + + for (let k = 0; k < handle.keys.length; ++k) { + const key = handle.keys[k]; + + switch (key) { + case KEYCODE_LMB: + html += ``; + break; + case KEYCODE_RMB: + html += ``; + break; + case KEYCODE_MMB: + html += ``; + break; + case DIVIDER_TOKEN: + html += ``; + break; + case ADDER_TOKEN: + html += `+`; + break; + default: + html += `${getStringForKeyCode( + mapper.getBinding(/** @type {KeyCode} */ (key)).keyCode + )}`; + } + } + html += ``; + + handle.cachedElement = makeDiv(this.element, null, ["binding"], html); + handle.cachedVisibility = false; + } } update() { - this.trackedMapOverviewActive.set(this.root.camera.getIsMapOverlayActive()); + for (let i = 0; i < this.keybindings.length; ++i) { + const handle = this.keybindings[i]; + const visibility = handle.condition(); + if (visibility !== handle.cachedVisibility) { + handle.cachedVisibility = visibility; + handle.cachedElement.classList.toggle("visible", visibility); + } + } } } diff --git a/src/js/game/hud/parts/mass_selector.js b/src/js/game/hud/parts/mass_selector.js index 0dc872c5..7e6710c0 100644 --- a/src/js/game/hud/parts/mass_selector.js +++ b/src/js/game/hud/parts/mass_selector.js @@ -17,29 +17,7 @@ import { enumHubGoalRewards } from "../../tutorial_goals"; const logger = createLogger("hud/mass_selector"); export class HUDMassSelector extends BaseHUDPart { - createElements(parent) { - const removalKeybinding = this.root.keyMapper - .getBinding(KEYMAPPINGS.massSelect.confirmMassDelete) - .getKeyCodeString(); - const abortKeybinding = this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).getKeyCodeString(); - const cutKeybinding = this.root.keyMapper - .getBinding(KEYMAPPINGS.massSelect.massSelectCut) - .getKeyCodeString(); - const copyKeybinding = this.root.keyMapper - .getBinding(KEYMAPPINGS.massSelect.massSelectCopy) - .getKeyCodeString(); - - this.element = makeDiv( - parent, - "ingame_HUD_MassSelector", - [], - T.ingame.massSelect.infoText - .replace("", `${removalKeybinding}`) - .replace("", `${cutKeybinding}`) - .replace("", `${copyKeybinding}`) - .replace("", `${abortKeybinding}`) - ); - } + createElements(parent) {} initialize() { this.deletionMarker = Loader.getSprite("sprites/misc/deletion_marker.png"); @@ -49,6 +27,7 @@ export class HUDMassSelector extends BaseHUDPart { this.selectedUids = new Set(); this.root.signals.entityQueuedForDestroy.add(this.onEntityDestroyed, this); + this.root.hud.signals.pasteBlueprintRequested.add(this.clearSelection, this); this.root.camera.downPreHandler.add(this.onMouseDown, this); this.root.camera.movePreHandler.add(this.onMouseMove, this); @@ -61,7 +40,7 @@ export class HUDMassSelector extends BaseHUDPart { this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCut).add(this.confirmCut, this); this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCopy).add(this.startCopy, this); - this.domAttach = new DynamicDomAttach(this.root, this.element); + this.root.hud.signals.selectedPlacementBuildingChanged.add(this.clearSelection, this); } /** @@ -83,6 +62,13 @@ export class HUDMassSelector extends BaseHUDPart { } } + /** + * Clears the entire selection + */ + clearSelection() { + this.selectedUids = new Set(); + } + confirmDelete() { if (this.selectedUids.size > 100) { const { ok } = this.root.hud.parts.dialogs.showWarning( @@ -230,10 +216,6 @@ export class HUDMassSelector extends BaseHUDPart { } } - update() { - this.domAttach.update(this.selectedUids.size > 0); - } - /** * * @param {DrawParameters} parameters diff --git a/src/js/game/hud/parts/screenshot_exporter.js b/src/js/game/hud/parts/screenshot_exporter.js index dfdd8224..8623f902 100644 --- a/src/js/game/hud/parts/screenshot_exporter.js +++ b/src/js/game/hud/parts/screenshot_exporter.js @@ -5,7 +5,7 @@ import { T } from "../../../translations"; import { createLogger } from "../../../core/logging"; import { StaticMapEntityComponent } from "../../components/static_map_entity"; import { Vector } from "../../../core/vector"; -import { Math_max, Math_min } from "../../../core/builtins"; +import { Math_max, Math_min, Math_floor } from "../../../core/builtins"; import { makeOffscreenBuffer } from "../../../core/buffer_utils"; import { DrawParameters } from "../../../core/draw_parameters"; import { Rectangle } from "../../../core/rectangle"; @@ -56,7 +56,14 @@ export class HUDScreenshotExporter extends BaseHUDPart { const dimensions = maxChunk.sub(minChunk); logger.log("Dimensions:", dimensions); - const chunkSizePixels = 128; + let chunkSizePixels = 128; + const maxDimensions = Math_max(dimensions.x, dimensions.y); + + if (maxDimensions > 128) { + chunkSizePixels = Math_max(1, Math_floor(128 * (128 / maxDimensions))); + } + logger.log("ChunkSizePixels:", chunkSizePixels); + const chunkScale = chunkSizePixels / (globalConfig.mapChunkSize * globalConfig.tileSize); logger.log("Scale:", chunkScale); diff --git a/src/js/game/hud/parts/waypoints.js b/src/js/game/hud/parts/waypoints.js index ebd8ec6a..2472e57a 100644 --- a/src/js/game/hud/parts/waypoints.js +++ b/src/js/game/hud/parts/waypoints.js @@ -28,6 +28,8 @@ import { ShapeDefinition } from "../../shape_definition"; */ const SHAPE_LABEL_PLACEHOLDER = " "; +const MAX_LABEL_LENGTH = 71; + export class HUDWaypoints extends BaseHUDPart { /** * Creates the overview of waypoints @@ -220,7 +222,8 @@ export class HUDWaypoints extends BaseHUDPart { id: "markerName", label: null, placeholder: "", - validator: val => val.length > 0 && (val.length < 15 || ShapeDefinition.isValidShortKey(val)), + validator: val => + val.length > 0 && (val.length < MAX_LABEL_LENGTH || ShapeDefinition.isValidShortKey(val)), }); const dialog = new DialogWithForm({ app: this.root.app, @@ -270,8 +273,8 @@ export class HUDWaypoints extends BaseHUDPart { return 1; } return this.getWaypointLabel(a) - .padEnd(20, "0") - .localeCompare(this.getWaypointLabel(b).padEnd(20, "0")); + .padEnd(MAX_LABEL_LENGTH, "0") + .localeCompare(this.getWaypointLabel(b).padEnd(MAX_LABEL_LENGTH, "0")); }); // Show notification about creation diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index 6a1e265c..c514446d 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -24,7 +24,7 @@ export const KEYMAPPINGS = { menuOpenStats: { keyCode: key("G") }, toggleHud: { keyCode: 113 }, // F2 - exportScreenshot: { keyCode: 114 }, // F3 + exportScreenshot: { keyCode: 114 }, // F3PS toggleFPSInfo: { keyCode: 115 }, // F4 }, @@ -56,7 +56,7 @@ export const KEYMAPPINGS = { }, placement: { - abortBuildingPlacement: { keyCode: key("Q") }, + pipette: { keyCode: key("Q") }, rotateWhilePlacing: { keyCode: key("R") }, rotateInverseModifier: { keyCode: 16 }, // SHIFT cycleBuildingVariants: { keyCode: key("T") }, @@ -88,6 +88,10 @@ for (const categoryId in KEYMAPPINGS) { } } +export const KEYCODE_LMB = 1; +export const KEYCODE_MMB = 2; +export const KEYCODE_RMB = 3; + /** * Returns a keycode -> string * @param {number} code @@ -95,11 +99,11 @@ for (const categoryId in KEYMAPPINGS) { */ export function getStringForKeyCode(code) { switch (code) { - case 1: + case KEYCODE_LMB: return "LMB"; - case 2: + case KEYCODE_MMB: return "MMB"; - case 3: + case KEYCODE_RMB: return "RMB"; case 4: return "MB4"; diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js index 723e854b..11da28f3 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -147,10 +147,32 @@ export class MetaBuilding { * @param {string} param0.variant */ createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) { + const entity = this.createEntity({ + root, + origin, + rotation, + originalRotation, + rotationVariant, + variant, + }); + root.map.placeStaticEntity(entity); + root.entityMgr.registerEntity(entity); + return entity; + } + + /** + * Creates the entity without placing it + * @param {object} param0 + * @param {GameRoot} param0.root + * @param {Vector} param0.origin Origin tile + * @param {number=} param0.rotation Rotation + * @param {number} param0.originalRotation Original Rotation + * @param {number} param0.rotationVariant Rotation variant + * @param {string} param0.variant + */ + createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) { const entity = new Entity(root); - const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant); - entity.addComponent( new StaticMapEntityComponent({ spriteKey: @@ -166,12 +188,8 @@ export class MetaBuilding { blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "", }) ); - this.setupEntityComponents(entity, root); this.updateVariants(entity, rotationVariant, variant); - - root.map.placeStaticEntity(entity); - root.entityMgr.registerEntity(entity); return entity; } diff --git a/src/js/game/root.js b/src/js/game/root.js index cc6007de..0456952c 100644 --- a/src/js/game/root.js +++ b/src/js/game/root.js @@ -19,7 +19,6 @@ import { SoundProxy } from "./sound_proxy"; import { Savegame } from "../savegame/savegame"; import { GameLogic } from "./logic"; import { ShapeDefinitionManager } from "./shape_definition_manager"; -import { CanvasClickInterceptor } from "./canvas_click_interceptor"; import { HubGoals } from "./hub_goals"; import { BufferMaintainer } from "../core/buffer_maintainer"; import { ProductionAnalytics } from "./production_analytics"; @@ -110,9 +109,6 @@ export class GameRoot { /** @type {BufferMaintainer} */ this.buffers = null; - /** @type {CanvasClickInterceptor} */ - this.canvasClickInterceptor = null; - /** @type {AutomaticSave} */ this.automaticSave = null; diff --git a/src/js/game/systems/miner.js b/src/js/game/systems/miner.js index 78223516..b195e6ab 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -24,11 +24,17 @@ export class MinerSystem extends GameSystemWithFilter { // Check if miner is above an actual tile const minerComp = entity.components.Miner; - const staticComp = entity.components.StaticMapEntity; - const tileBelow = this.root.map.getLowerLayerContentXY(staticComp.origin.x, staticComp.origin.y); - if (!tileBelow) { - continue; + if (!minerComp.cachedMinedItem) { + const staticComp = entity.components.StaticMapEntity; + const tileBelow = this.root.map.getLowerLayerContentXY( + staticComp.origin.x, + staticComp.origin.y + ); + if (!tileBelow) { + continue; + } + minerComp.cachedMinedItem = tileBelow; } // First, try to get rid of chained items @@ -40,20 +46,9 @@ export class MinerSystem extends GameSystemWithFilter { } if (this.root.time.isIngameTimerExpired(minerComp.lastMiningTime, 1 / miningSpeed)) { - const lowerLayerItem = this.root.map.getLowerLayerContentXY( - staticComp.origin.x, - staticComp.origin.y - ); - - // TODO: Should not be required actually - if (!lowerLayerItem) { - // Nothing below; - continue; - } - - if (this.tryPerformMinerEject(entity, lowerLayerItem)) { + if (this.tryPerformMinerEject(entity, minerComp.cachedMinedItem)) { // Analytics hook - this.root.signals.itemProduced.dispatch(lowerLayerItem); + this.root.signals.itemProduced.dispatch(minerComp.cachedMinedItem); // Actually mine minerComp.lastMiningTime = this.root.time.now(); @@ -114,18 +109,17 @@ export class MinerSystem extends GameSystemWithFilter { if (entity && entity.components.Miner) { const staticComp = entity.components.StaticMapEntity; + const minerComp = entity.components.Miner; if (!staticComp.shouldBeDrawn(parameters)) { continue; } + if (!minerComp.cachedMinedItem) { + continue; + } - const lowerLayerItem = this.root.map.getLowerLayerContentXY( - staticComp.origin.x, - staticComp.origin.y - ); - - if (lowerLayerItem) { + if (minerComp.cachedMinedItem) { const padding = 3; - parameters.context.fillStyle = lowerLayerItem.getBackgroundColorAsResource(); + parameters.context.fillStyle = minerComp.cachedMinedItem.getBackgroundColorAsResource(); parameters.context.fillRect( staticComp.origin.x * globalConfig.tileSize + padding, staticComp.origin.y * globalConfig.tileSize + padding, @@ -134,8 +128,8 @@ export class MinerSystem extends GameSystemWithFilter { ); } - if (lowerLayerItem) { - lowerLayerItem.draw( + if (minerComp.cachedMinedItem) { + minerComp.cachedMinedItem.draw( (0.5 + staticComp.origin.x) * globalConfig.tileSize, (0.5 + staticComp.origin.y) * globalConfig.tileSize, parameters diff --git a/src/js/languages.js b/src/js/languages.js index 19e88f5a..2d40037b 100644 --- a/src/js/languages.js +++ b/src/js/languages.js @@ -80,4 +80,10 @@ export const LANGUAGES = { code: "no", region: "", }, + "zh-CN": { + name: "简体中文", + data: require("./built-temp/base-zh-CN.json"), + code: "zh", + region: "CN", + }, }; diff --git a/src/js/profile/application_settings.js b/src/js/profile/application_settings.js index 5b69c7ae..964fb885 100644 --- a/src/js/profile/application_settings.js +++ b/src/js/profile/application_settings.js @@ -160,7 +160,7 @@ export const allApplicationSettings = [ */ (app, id) => { applyGameTheme(id); - document.body.setAttribute("data-theme", id); + document.documentElement.setAttribute("data-theme", id); }, enabled: !IS_DEMO, }), @@ -200,6 +200,7 @@ export const allApplicationSettings = [ new BoolSetting("alwaysMultiplace", categoryGame, (app, value) => {}), new BoolSetting("enableTunnelSmartplace", categoryGame, (app, value) => {}), new BoolSetting("vignette", categoryGame, (app, value) => {}), + new BoolSetting("compactBuildingInfo", categoryGame, (app, value) => {}), ]; export function getApplicationSettingById(id) { @@ -223,6 +224,7 @@ class SettingsStorage { this.offerHints = true; this.enableTunnelSmartplace = true; this.vignette = true; + this.compactBuildingInfo = false; /** * @type {Object.} @@ -412,7 +414,7 @@ export class ApplicationSettings extends ReadWriteProxy { } getCurrentVersion() { - return 12; + return 13; } /** @param {{settings: SettingsStorage, version: number}} data */ @@ -459,6 +461,11 @@ export class ApplicationSettings extends ReadWriteProxy { data.version = 12; } + if (data.version < 13) { + data.settings.compactBuildingInfo = false; + data.version = 13; + } + return ExplainedResult.good(); } } diff --git a/translations/README.md b/translations/README.md index 434e3dab..e799926c 100644 --- a/translations/README.md +++ b/translations/README.md @@ -26,6 +26,7 @@ The base translation is `base-en.yaml`. It will always contain the latest phrase - [Lithuanian](base-lt.yaml) - [Arabic](base-ar.yaml) - [Norwegian](base-no.yaml) +- [Kroatian](base-hr.yaml) (If you want to translate into a new language, see below!) diff --git a/translations/base-de.yaml b/translations/base-de.yaml index d1f53b57..73efe45c 100644 --- a/translations/base-de.yaml +++ b/translations/base-de.yaml @@ -239,7 +239,7 @@ dialogs: blueprintsNotUnlocked: title: Noch nicht freigeschaltet desc: >- - Blueprints werden erst in Level 12 freigeschalten! + Blueprints werden erst in Level 12 freigeschaltet! keybindingsIntroduction: title: Nützliche Hotkeys @@ -282,15 +282,15 @@ ingame: createMarker: Marker erstellen delete: Löschen pasteLastBlueprint: Letzte Blaupause einfügen - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + lockBeltDirection: Bandplaner aktivieren + plannerSwitchSide: 'Planer: Seite wechseln' # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Drücke um zwischen den Varianten zu wählen. + cycleBuildingVariants: Drücke , um zwischen den Varianten zu wählen. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- @@ -538,7 +538,7 @@ storyRewards: desc: Der Tunnel wurde freigeschaltet! Du kannst Items nun unter Gebäuden oder Förderbändern hindurchleiten! reward_rotater_ccw: - title: gUZS Rotieren + title: Gegen UZS Rotieren desc: Du hast eine zweite Variante des Rotierers freigeschaltet! Damit können Items gegen den Uhrzeigensinn gedreht werden. Wähle den Rotierer aus und drücke 'T', um auf verschiedene Varianten zuzugreifen! reward_miner_chainable: @@ -678,20 +678,20 @@ settings: super_fast: Sehr schnell extremely_fast: Extrem schnell enableTunnelSmartplace: - title: Smart Tunnels + title: Intelligente Tunnel description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + Aktiviert das automatische Entfernen von überflüssigen Förderbändern bei der Platzierung von Tunneln. + Außerdem funktioniert das Ziehen von Tunneln und überschüssige werden ebenfalls entfernt. vignette: title: Vignette description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Aktiviert den Vignetteneffekt, der den Rand des Bildschirms zunehmend verdunkelt + und das Lesen der Textfelder vereinfacht. keybindings: title: Tastenbelegung hint: >- - Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene Platzierungsoptionen! + Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene Platzierungsoptionen. resetKeybindings: Tastenbelegung zurücksetzen. @@ -741,7 +741,7 @@ keybindings: confirmMassDelete: Massenlöschung bestätigen cycleBuildings: Gebäude rotieren - massSelectStart: Halten und ziehen zum beginnen + massSelectStart: Halten und ziehen zum Beginnen massSelectSelectMultiple: Mehrere Areale markieren massSelectCopy: Areal kopieren @@ -752,8 +752,8 @@ keybindings: massSelectCut: Areal ausschneiden exportScreenshot: Ganze Fabrik als Foto exportieren mapMoveFaster: Schneller bewegen - lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + lockBeltDirection: Bandplaner aktivieren + switchDirectionLockSide: 'Planer: Seite wechseln' about: title: Über dieses Spiel diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 8321e20b..0b754e4b 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -285,6 +285,10 @@ ingame: pasteLastBlueprint: Paste last blueprint lockBeltDirection: Enable belt planner plannerSwitchSide: Flip planner side + cutSelection: Cut + copySelection: Copy + clearSelection: Clear Selection + pipette: Pipette # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -320,11 +324,6 @@ ingame: newUpgrade: A new upgrade is available! gameSaved: Your game has been saved. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Press to cut, to copy, to remove and to cancel. - # The "Upgrades" window shop: title: Upgrades @@ -688,6 +687,11 @@ settings: description: >- Enables the vignette which darkens the screen corners and makes text easier to read. + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + keybindings: title: Keybindings hint: >- @@ -735,7 +739,7 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement + pipette: Pipette rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead diff --git a/translations/base-fr.yaml b/translations/base-fr.yaml index b1cc9e5c..9f43384f 100644 --- a/translations/base-fr.yaml +++ b/translations/base-fr.yaml @@ -275,7 +275,7 @@ ingame: # every situation keybindingsOverlay: moveMap: Déplacer - selectBuildings: Sélection de la zone + selectBuildings: Sélection d'une zone stopPlacement: Arrêter le placement rotateBuilding: Tourner le bâtiment placeMultiple: Placement multiple @@ -286,8 +286,8 @@ ingame: createMarker: Créer une balise delete: Supprimer pasteLastBlueprint: Copier le dernier patron - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + lockBeltDirection: Utiliser le plannificateur de convoyeurs + plannerSwitchSide: Échanger la direction du plannificateur # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -682,15 +682,14 @@ settings: super_fast: Très rapide extremely_fast: Extrêmement rapide enableTunnelSmartplace: - title: Smart Tunnels + title: Tunnels intelligents description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + Si cette option est sélectionnée, placer des tunnels effacera automatiquement les convoyeurs inutiles. + Cela permet aussi d'étirer les tunnels et les tunnels en surnombre seront effacés. vignette: - title: Vignette + title: Effet de vignette description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Permet l'affichage de l'effet de vignette qui assombrit les coins de l'écran afin de rendre le texte plus facile à lire. keybindings: title: Contrôles @@ -756,8 +755,8 @@ keybindings: massSelectCut: Couper la sélection exportScreenshot: Exporter toute la base en tant qu'image. mapMoveFaster: Se déplacer plus vite - lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + lockBeltDirection: Utiliser le plannificateur de convoyeurs + switchDirectionLockSide: 'Plannificateur: changer de côté' about: title: À propos de ce jeu diff --git a/translations/base-hr.yaml b/translations/base-hr.yaml new file mode 100644 index 00000000..8321e20b --- /dev/null +++ b/translations/base-hr.yaml @@ -0,0 +1,783 @@ +# +# GAME TRANSLATIONS +# +# Contributing: +# +# If you want to contribute, please make a pull request on this respository +# and I will have a look. +# +# Placeholders: +# +# Do *not* replace placeholders! Placeholders have a special syntax like +# `Hotkey: `. They are encapsulated within angle brackets. The correct +# translation for this one in German for example would be: `Taste: ` (notice +# how the placeholder stayed '' and was not replaced!) +# +# Adding a new language: +# +# If you want to add a new language, ask me in the discord and I will setup +# the basic structure so the game also detects it. +# + +steamPage: + # This is the short text appearing on the steam page + shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. + # NOTICE: + # - Do not translate the first line (This is the gif image at the start of the store) + # - Please keep the markup (Stuff like [b], [list] etc) in the same format + longText: >- + [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + + shapez.io is a game about building factories to automate the creation and combination of shapes. Deliver the requested, increasingly complex shapes to progress within the game and unlock upgrades to speed up your factory. + + Since the demand raises you will have to scale up your factory to fit the needs - Don't forget about resources though, you will have to expand in the [b]infinite map[/b]! + + Since shapes can get boring soon you need to mix colors and paint your shapes with it - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + + This game features 18 levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + + + [b]Standalone Advantages[/b] + + [list] + [*] Waypoints + [*] Unlimited Savegames + [*] Dark Mode + [*] More settings + [*] Allow me to further develop shapez.io ❤️ + [*] More features in the future! + [/list] + + [b]Planned features & Community suggestions[/b] + + This game is open source - Anybody can contribute! Besides of that, I listen [b]a lot[/b] to the community! I try to read all suggestions and take as much feedback into account as possible. + + [list] + [*] Story mode where buildings cost shapes + [*] More levels & buildings (standalone exclusive) + [*] Different maps, and maybe map obstacles + [*] Configurable map creation (Edit number and size of patches, seed, and more) + [*] More types of shapes + [*] More performance improvements (Although the game already runs pretty good!) + [*] Color blind mode + [*] And much more! + [/list] + + Be sure to check out my trello board for the full roadmap! https://trello.com/b/ISQncpJP/shapezio + +global: + loading: Loading + error: Error + + # How big numbers are rendered, e.g. "10,000" + thousandsDivider: "," + + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. + suffix: + thousands: k + millions: M + billions: B + trillions: T + + # Shown for infinitely big numbers + infinite: inf + + time: + # Used for formatting past time dates + oneSecondAgo: one second ago + xSecondsAgo: seconds ago + oneMinuteAgo: one minute ago + xMinutesAgo: minutes ago + oneHourAgo: one hour ago + xHoursAgo: hours ago + oneDayAgo: one day ago + xDaysAgo: days ago + + # Short formats for times, e.g. '5h 23m' + secondsShort: s + minutesAndSecondsShort: m s + hoursAndMinutesShort: h m + + xMinutes: minutes + + keys: + tab: TAB + control: CTRL + alt: ALT + escape: ESC + shift: SHIFT + space: SPACE + +demoBanners: + # This is the "advertisement" shown in the main menu and other various places + title: Demo Version + intro: >- + Get the standalone to unlock all features! + +mainMenu: + play: Play + continue: Continue + newGame: New Game + changelog: Changelog + importSavegame: Import + openSourceHint: This game is open source! + discordLink: Official Discord Server + helpTranslate: Help translate! + madeBy: Made by + + # This is shown when using firefox and other browsers which are not supported. + browserWarning: >- + Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. + + savegameLevel: Level + savegameLevelUnknown: Unknown Level + + contests: + contest_01_03062020: + title: "Contest #01" + desc: Win $25 for the coolest base! + longDesc: >- + To give something back to you, I thought it would be cool to make weekly contests! +

+ This weeks topic: Build the coolest base! +

+ Here's the deal:
+
    +
  • Submit a screenshot of your base to contest@shapez.io
  • +
  • Bonus points if you share it on social media!
  • +
  • I will choose 5 screenshots and propose it to the discord community to vote.
  • +
  • The winner gets $25 (Paypal, Amazon Gift Card, whatever you prefer)
  • +
  • Deadline: 07.06.2020 12:00 AM CEST
  • +
+
+ I'm looking forward to seeing your awesome creations! + + showInfo: View + contestOver: This contest has ended - Join the discord to get noticed about new contests! + +dialogs: + buttons: + ok: OK + delete: Delete + cancel: Cancel + later: Later + restart: Restart + reset: Reset + getStandalone: Get Standalone + deleteGame: I know what I do + viewUpdate: View Update + showUpgrades: Show Upgrades + showKeybindings: Show Keybindings + + importSavegameError: + title: Import Error + text: >- + Failed to import your savegame: + + importSavegameSuccess: + title: Savegame Imported + text: >- + Your savegame has been successfully imported. + + gameLoadFailure: + title: Game is broken + text: >- + Failed to load your savegame: + + confirmSavegameDelete: + title: Confirm deletion + text: >- + Are you sure you want to delete the game? + + savegameDeletionError: + title: Failed to delete + text: >- + Failed to delete the savegame: + + restartRequired: + title: Restart required + text: >- + You need to restart the game to apply the settings. + + editKeybinding: + title: Change Keybinding + desc: Press the key or mouse button you want to assign, or escape to cancel. + + resetKeybindingsConfirmation: + title: Reset keybindings + desc: This will reset all keybindings to their default values. Please confirm. + + keybindingsResetOk: + title: Keybindings reset + desc: The keybindings have been reset to their respective defaults! + + featureRestriction: + title: Demo Version + desc: You tried to access a feature () which is not available in the demo. Consider to get the standalone for the full experience! + + oneSavegameLimit: + title: Limited savegames + desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone! + + updateSummary: + title: New update! + desc: >- + Here are the changes since you last played: + + 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. + + massDeleteConfirm: + title: Confirm delete + desc: >- + You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + + massCutConfirm: + title: Confirm cut + desc: >- + You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? + + blueprintsNotUnlocked: + title: Not unlocked yet + desc: >- + Complete level 12 to unlock Blueprints! + + keybindingsIntroduction: + title: Useful keybindings + desc: >- + This game has a lot of keybindings which make it easier to build big factories. + Here are a few, but be sure to check out the keybindings!

+ CTRL + Drag: Select an area.
+ SHIFT: Hold to place multiple of one building.
+ ALT: Invert orientation of placed belts.
+ + createMarker: + title: New Marker + desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) + + markerDemoLimit: + desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + + exportScreenshotWarning: + title: Export screenshot + desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! + +ingame: + # This is shown in the top left corner and displays useful keybindings in + # every situation + keybindingsOverlay: + moveMap: Move + selectBuildings: Select area + stopPlacement: Stop placement + rotateBuilding: Rotate building + placeMultiple: Place multiple + reverseOrientation: Reverse orientation + disableAutoOrientation: Disable auto orientation + toggleHud: Toggle HUD + placeBuilding: Place building + createMarker: Create Marker + delete: Destroy + pasteLastBlueprint: Paste last blueprint + lockBeltDirection: Enable belt planner + plannerSwitchSide: Flip planner side + + # Everything related to placing buildings (I.e. as soon as you selected a building + # from the toolbar) + buildingPlacement: + # Buildings can have different variants which are unlocked at later levels, + # and this is the hint shown when there are multiple variants available. + cycleBuildingVariants: Press to cycle variants. + + # Shows the hotkey in the ui, e.g. "Hotkey: Q" + hotkeyLabel: >- + Hotkey: + + infoTexts: + speed: Speed + range: Range + storage: Storage + oneItemPerSecond: 1 item / second + itemsPerSecond: items / s + itemsPerSecondDouble: (x2) + + tiles: tiles + + # The notification when completing a level + levelCompleteNotification: + # is replaced by the actual level, so this gets 'Level 03' for example. + levelTitle: Level + completed: Completed + unlockText: Unlocked ! + buttonNextLevel: Next Level + + # Notifications on the lower right + notifications: + newUpgrade: A new upgrade is available! + gameSaved: Your game has been saved. + + # Mass select information, this is when you hold CTRL and then drag with your mouse + # to select multiple buildings + massSelect: + infoText: Press to cut, to copy, to remove and to cancel. + + # The "Upgrades" window + shop: + title: Upgrades + buttonUnlock: Upgrade + + # Gets replaced to e.g. "Tier IX" + tier: Tier + + # The roman number for each tier + tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] + + maximumLevel: MAXIMUM LEVEL (Speed x) + + # The "Statistics" window + statistics: + title: Statistics + dataSources: + stored: + title: Stored + description: Displaying amount of stored shapes in your central building. + produced: + title: Produced + description: Displaying all shapes your whole factory produces, including intermediate products. + delivered: + title: Delivered + description: Displaying shapes which are delivered to your central building. + noShapesProduced: No shapes have been produced so far. + + # Displays the shapes per minute, e.g. '523 / m' + shapesPerMinute: / m + + # Settings menu, when you press "ESC" + settingsMenu: + playtime: Playtime + + buildingsPlaced: Buildings + beltsPlaced: Belts + + buttons: + continue: Continue + settings: Settings + menu: Return to menu + + # Bottom left tutorial hints + tutorialHints: + title: Need help? + showHint: Show hint + hideHint: Close + + # When placing a blueprint + blueprintPlacer: + cost: Cost + + # Map markers + waypoints: + waypoints: Markers + hub: HUB + description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. + creationSuccessNotification: Marker has been created. + + # Interactive tutorial + interactiveTutorial: + title: Tutorial + hints: + 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_2_conveyor: >- + Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + + 1_3_expand: >- + This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + +# All shop upgrades +shopUpgrades: + belt: + name: Belts, Distributor & Tunnels + description: Speed x → x + miner: + name: Extraction + description: Speed x → x + processors: + name: Cutting, Rotating & Stacking + description: Speed x → x + painting: + name: Mixing & Painting + description: Speed x → x + +# Buildings and their name / description +buildings: + hub: + deliver: Deliver + toUnlock: to unlock + levelShortcut: LVL + + belt: + default: + name: &belt Conveyor Belt + description: Transports items, hold and drag to place multiple. + + miner: # Internal name for the Extractor + default: + name: &miner Extractor + description: Place over a shape or color to extract it. + + chainable: + name: Extractor (Chain) + description: Place over a shape or color to extract it. Can be chained. + + underground_belt: # Internal name for the Tunnel + default: + name: &underground_belt Tunnel + description: Allows to tunnel resources under buildings and belts. + + tier2: + name: Tunnel Tier II + description: Allows to tunnel resources under buildings and belts. + + splitter: # Internal name for the Balancer + default: + name: &splitter Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. + + compact: + name: Merger (compact) + description: Merges two conveyor belts into one. + + compact-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + + cutter: + default: + name: &cutter Cutter + description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! + quad: + name: Cutter (Quad) + description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! + + rotater: + default: + name: &rotater Rotate + description: Rotates shapes clockwise by 90 degrees. + ccw: + name: Rotate (CCW) + description: Rotates shapes counter clockwise by 90 degrees. + + stacker: + default: + name: &stacker Stacker + description: Stacks both items. If they can not be merged, the right item is placed above the left item. + + mixer: + default: + name: &mixer Color Mixer + description: Mixes two colors using additive blending. + + painter: + default: + name: &painter Painter + description: &painter_desc Colors the whole shape on the left input with the color from the top input. + + mirrored: + name: *painter + description: *painter_desc + + double: + name: Painter (Double) + description: Colors the shapes on the left inputs with the color from the top input. + quad: + name: Painter (Quad) + description: Allows to color each quadrant of the shape with a different color. + + trash: + default: + name: &trash Trash + description: Accepts inputs from all sides and destroys them. Forever. + + storage: + name: Storage + description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + +storyRewards: + # Those are the rewards gained from completing the store + reward_cutter_and_trash: + title: Cutting Shapes + desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + + reward_rotater: + title: Rotating + desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + + reward_painter: + title: Painting + desc: >- + The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, I'm working on a solution already! + + reward_mixer: + title: Color Mixing + desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + + reward_stacker: + title: Combiner + desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + + reward_splitter: + title: Splitter/Merger + desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ + reward_tunnel: + title: Tunnel + desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! + + reward_rotater_ccw: + title: CCW Rotating + desc: You have unlocked a variant of the rotater - It allows to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle its variants! + + reward_miner_chainable: + title: Chaining Extractor + desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + + reward_underground_belt_tier_2: + title: Tunnel Tier II + desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + + reward_splitter_compact: + title: Compact Balancer + desc: >- + You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + + reward_cutter_quad: + title: Quad Cutting + desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + + reward_painter_double: + title: Double Painting + desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + + reward_painter_quad: + title: Quad Painting + desc: You have unlocked a variant of the painter - It allows to paint each part of the shape individually! + + reward_storage: + title: Storage Buffer + desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + + reward_freeplay: + title: Freeplay + desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + + reward_blueprints: + title: Blueprints + desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + + # Special reward, which is shown when there is no reward actually + no_reward: + title: Next level + desc: >- + This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! + + no_reward_freeplay: + title: Next level + desc: >- + Congratulations! By the way, more content is planned for the standalone! + +settings: + title: Settings + categories: + game: Game + app: Application + + versionBadges: + dev: Development + staging: Staging + prod: Production + buildDate: Built + + labels: + uiScale: + title: Interface scale + description: >- + Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale. + scales: + super_small: Super small + small: Small + regular: Regular + large: Large + huge: Huge + + scrollWheelSensitivity: + title: Zoom sensitivity + description: >- + Changes how sensitive the zoom is (Either mouse wheel or trackpad). + sensitivity: + super_slow: Super slow + slow: Slow + regular: Regular + fast: Fast + super_fast: Super fast + + movementSpeed: + title: Movement speed + description: >- + Changes how fast the view moves when using the keyboard. + speeds: + super_slow: Super slow + slow: Slow + regular: Regular + fast: Fast + super_fast: Super Fast + extremely_fast: Extremely Fast + + language: + title: Language + description: >- + Change the language. All translations are user contributed and might be incomplete! + + fullscreen: + title: Fullscreen + description: >- + It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + + soundsMuted: + title: Mute Sounds + description: >- + If enabled, mutes all sound effects. + + musicMuted: + title: Mute Music + description: >- + If enabled, mutes all music. + + theme: + title: Game theme + description: >- + Choose the game theme (light / dark). + themes: + dark: Dark + light: Light + + refreshRate: + title: Simulation Target + description: >- + If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + + alwaysMultiplace: + title: Multiplace + description: >- + If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + + offerHints: + title: Hints & Tutorials + description: >- + Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + + enableTunnelSmartplace: + title: Smart Tunnels + description: >- + When enabled, placing tunnels will automatically remove unnecessary belts. This also enables to drag tunnels and excess tunnels will get removed. + + vignette: + title: Vignette + description: >- + Enables the vignette which darkens the screen corners and makes text easier to read. + +keybindings: + title: Keybindings + hint: >- + Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + + resetKeybindings: Reset Keybindings + + categoryLabels: + general: Application + ingame: Game + navigation: Navigating + placement: Placement + massSelect: Mass Select + buildings: Building Shortcuts + placementModifiers: Placement Modifiers + + mappings: + confirm: Confirm + back: Back + mapMoveUp: Move Up + mapMoveRight: Move Right + mapMoveDown: Move Down + mapMoveLeft: Move Left + mapMoveFaster: Move Faster + centerMap: Center Map + + mapZoomIn: Zoom in + mapZoomOut: Zoom out + createMarker: Create Marker + + menuOpenShop: Upgrades + menuOpenStats: Statistics + + toggleHud: Toggle HUD + toggleFPSInfo: Toggle FPS and Debug Info + exportScreenshot: Export whole Base as Image + belt: *belt + splitter: *splitter + underground_belt: *underground_belt + miner: *miner + cutter: *cutter + rotater: *rotater + stacker: *stacker + mixer: *mixer + painter: *painter + trash: *trash + + abortBuildingPlacement: Abort Placement + rotateWhilePlacing: Rotate + rotateInverseModifier: >- + Modifier: Rotate CCW instead + cycleBuildingVariants: Cycle Variants + confirmMassDelete: Confirm Mass Delete + pasteLastBlueprint: Paste last blueprint + cycleBuildings: Cycle Buildings + lockBeltDirection: Enable belt planner + switchDirectionLockSide: >- + Planner: Switch side + + massSelectStart: Hold and drag to start + massSelectSelectMultiple: Select multiple areas + massSelectCopy: Copy area + massSelectCut: Cut area + + placementDisableAutoOrientation: Disable automatic orientation + placeMultiple: Stay in placement mode + placeInverse: Invert automatic belt orientation + +about: + title: About this Game + body: >- + This game is open source and developed by Tobias Springer (this is me).

+ + If you want to contribute, check out shapez.io on github.

+ + This game wouldn't have been possible without the great discord community around my games - You should really join the discord server!

+ + The soundtrack was made by Peppsen - He's awesome.

+ + Finally, huge thanks to my best friend Niklas - Without our factorio sessions this game would never have existed. + +changelog: + title: Changelog + +demo: + features: + restoringGames: Restoring savegames + importingGames: Importing savegames + oneGameLimit: Limited to one savegame + customizeKeybindings: Customizing Keybindings + exportingBase: Exporting whole Base as Image + + settingNotAvailable: Not available in the demo. diff --git a/translations/base-nl.yaml b/translations/base-nl.yaml index 0faf9955..df5f7546 100644 --- a/translations/base-nl.yaml +++ b/translations/base-nl.yaml @@ -32,7 +32,7 @@ steamPage: shapez.io is een spel dat draait om het bouwen van fabrieken om steeds complexere vormen te produceren en deze productie te automatiseren. Lever de gevraagde, steeds complexere vormen, om verder te komen in het spel en om upgrades voor je fabrieken te ontgrendelen. - De vraag naar vormen wordt steeds hoger, wat betekent dat je fabriek moet blijven uitbreiden om dit tegemoet te komen. Om de juiste grondstoffen te delven zul je steeds verder in het [b]oneindig grote speelveld[/b] moeten gaan werken! + De vraag naar vormen wordt steeds groter, wat betekent dat je fabriek moet blijven uitbreiden om dit tegemoet te komen. Om de juiste grondstoffen te delven zul je steeds verder in het [b]oneindig grote speelveld[/b] moeten gaan werken! Omdat simpele vormen snel saai worden, moet je kleuren mengen om de vormen te verven - combineer rode, groene en blauwe grondstoffen om verschillende kleuren te produceren en gebruik deze om de vormen te verven, zodat je de vraag hiernaar tegemoet kan komen. @@ -76,10 +76,10 @@ global: # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: - thousands: d + thousands: k millions: M - billions: MJ - trillions: B + billions: B + trillions: T # Shown for infinitely big numbers infinite: inf @@ -154,7 +154,7 @@ mainMenu: showInfo: Laat zien contestOver: Deze competitie is voorbij - word lid van de discord (engelstalig) om berichten te krijgen van nieuwe competities! continue: Verder - newGame: Niew Spel + newGame: Nieuw Spel madeBy: Gemaakt door dialogs: @@ -249,11 +249,11 @@ dialogs: Hier zijn er een aantal, maar zorg dat je kijkt naar de sneltoetsen!

CTRL + slepen: selecteer een gebied om te kopiëren / verwijderen.
SHIFT: Houd ingedrukt om meerdere van het zelfde gebouw te plaatsen.
- ALT: Draai de richting van geplaatste lopende banden om.
+ ALT: Houd ingedrukt om de richting van lopende banden om te draaien wanneer je ze plaatst.
createMarker: title: Nieuwe markering - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) + desc: Geef het een betekenisvolle naam. Je kunt ook een icoontje van een vorm toevoegen (die je hier kunt maken) markerDemoLimit: desc: Je kunt maar twee markeringen plaatsen in de demo. Koop de standalone voor een ongelimiteerde hoeveelheid markeringen! @@ -263,10 +263,9 @@ dialogs: Je bent veel gebouwen aan het knippen ( om precies te zijn)! Weet je zeker dat je dit wil doen? exportScreenshotWarning: - title: Export screenshot + title: Exporteer screenshot desc: >- - You requested to export your base as a screenshot. Please note that this can - be quite slow for a big base and even crash your game! + Je hebt aangegeven dat je jouw basis wil exporteren als screenshot. Als je een grote basis hebt kan dit proces langzaam zijn en er zelfs voor zorgen dat je spel crasht! ingame: # This is shown in the top left corner and displays useful keybindings in @@ -275,7 +274,7 @@ ingame: moveMap: Beweeg speelveld selectBuildings: Selecteer gebied stopPlacement: Stop met plaatsen - rotateBuilding: Draai een gebouw + rotateBuilding: Draai gebouw placeMultiple: Plaats meerdere reverseOrientation: Omgekeerde oriëntatie disableAutoOrientation: Schakel auto-oriëntatie uit @@ -302,8 +301,8 @@ ingame: speed: Snelheid range: Bereik storage: Opslag - oneItemPerSecond: 1 item / seconde - itemsPerSecond: items / s + oneItemPerSecond: 1 voorwerp / s + itemsPerSecond: voorwerpen / s itemsPerSecondDouble: (x2) tiles: tegels @@ -324,7 +323,7 @@ ingame: # Mass select information, this is when you hold CTRL and then drag with your mouse # to select multiple buildings massSelect: - infoText: Druk op om te knippen, om te kopiëren, om te verwijderen en om de selectie te annuleren. + infoText: Druk op om te knippen, om te kopiëren, om te verwijderen en om te annuleren. # The "Upgrades" window shop: @@ -337,7 +336,7 @@ ingame: # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Snelheid x) + maximumLevel: MAXIMAAL NIVEAU (Snelheid x) # The "Statistics" window statistics: @@ -390,12 +389,12 @@ ingame: interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Plaats een ontginner op een cirkelvorm om deze te ontginnen! + 1_1_extractor: Plaats een ontginner op een cirkelvorm om deze te onttrekken! 1_2_conveyor: >- - Verbind de extractor met een lopende band aan je hub!

Tip: Klik en sleep de lopende band met je muis! + Verbind de ontginner met een lopende band aan je hub!

Tip: Klik en sleep de lopende band met je muis! 1_3_expand: >- - Dit is GEEN nietsdoen-spel! bouw meer extractors en lopende banden om het doel sneller te behalen.

Tip: Houd SHIFT ingedrukt om meerdere extractors te plaatsen en gebruik R om ze te draaien. + Dit is GEEN nietsdoen-spel! bouw meer ontginners en lopende banden om het doel sneller te behalen.

Tip: Houd SHIFT ingedrukt om meerdere ontginners te plaatsen en gebruik R om ze te draaien. # All shop upgrades shopUpgrades: @@ -422,11 +421,11 @@ buildings: miner: # Internal name for the Extractor default: name: &miner Ontginner - description: Plaats op een vorm of kleur om deze te ontginnen. + description: Plaats op een vorm of kleur om deze te onttrekken. chainable: name: Ontginner (Ketting) - description: Plaats op een vorm of kleur om deze te ontginnen. Kan achter elkaar worden geplaatst. + description: Plaats op een vorm of kleur om deze te onttrekken. Kan achter elkaar worden geplaatst. underground_belt: # Internal name for the Tunnel default: @@ -512,12 +511,12 @@ storyRewards: reward_rotater: title: Roteren - desc: De roteerder is ontgrendeld - ! Het draait vormen 90 graden met de klok mee. + desc: De roteerder is ontgrendeld - Het draait vormen 90 graden met de klok mee. reward_painter: title: Verven desc: >- - De verver is ontgrendeld - Onttrek wat kleurstoffen (net als met vormen) en combineer deze met een vorm in de verver om ze een kleur te geven!

PS: Ik werk aan een oplossing voor kleurenblinden! + De verver is ontgrendeld - Onttrek wat kleurstoffen (net als met vormen) en combineer deze met een vorm in de verver om de vorm een kleur te geven!

PS: Ik werk aan een oplossing voor kleurenblinden! reward_mixer: title: Kleuren mengen @@ -537,11 +536,11 @@ storyRewards: reward_rotater_ccw: title: Roteren (andersom) - desc: Je hebt een variant van de rotater ontgrendeld - Het roteert voorwerpen tegen de klok in! Om het te bouwen selecteer je de roteerder en druk je op 'T' om tussen varianten te wisselen! + desc: Je hebt een variant van de roteerder ontgrendeld - Het roteert voorwerpen tegen de klok in! Om het te bouwen selecteer je de roteerder en druk je op 'T' om tussen varianten te wisselen! reward_miner_chainable: - title: Ketting Extractor - desc: Je hebt de Ketting extractor ontgrendeld! Deze kan grondstoffen doorsturen naar andere extractors, waardoor je efficiënter grondstoffen kan onttrekken! + title: Ketting-ontginner + desc: Je hebt de Ketting-ontginner ontgrendeld! Deze kan grondstoffen doorsturen naar andere ontginners, waardoor je efficiënter grondstoffen kan onttrekken! reward_underground_belt_tier_2: title: Tunnel Niveau II @@ -585,7 +584,7 @@ storyRewards: no_reward_freeplay: title: Volgende level desc: >- - Gefeliciteerd! By the way, het spel wordt in de toekomst nog verder uitgebereid in de standalone! + Gefeliciteerd! Even tussendoor, het spel wordt in de toekomst nog verder uitgebereid in de standalone! settings: title: Opties @@ -677,15 +676,14 @@ settings: super_fast: Super snel extremely_fast: Extreem snel enableTunnelSmartplace: - title: Smart Tunnels + title: Slimme Tunnels description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + Wanneer dit aan staat zullen tunnels automatisch onnodige lopende banden verwijderen. + Ook kun je dan tunnels slepen en onnodige tunnels worden ook verwijderd. vignette: title: Vignette description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Schakelt de vignet in, wat de hoeken van het scherm donkerder maakt zodat de tekst makkelijker te lezen is. keybindings: title: Sneltoetsen @@ -749,30 +747,30 @@ keybindings: placeInverse: Omkeren richting lopende band pasteLastBlueprint: Plak laatst gekopiëerde blauwdruk massSelectCut: Knip geselecteerd gebied - exportScreenshot: Export whole Base as Image - mapMoveFaster: Move Faster - lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + exportScreenshot: Exporteer volledige basis als afbeelding + mapMoveFaster: Beweeg sneller + lockBeltDirection: Schakel lopende band-planner in + switchDirectionLockSide: 'Planner: Wissel van kant' about: title: Over dit spel body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Dit spel is open source en ontwikkeld door Tobias Springer (dit ben ik).

- If you want to contribute, check out shapez.io on github.

+ Als je ook bij wil dragen, ga dan naar shapez.io op github.

- This game wouldn't have been possible without the great discord community - around my games - You should really join the discord server!

+ Dit spel was niet mogelijk geweest zonder de geweldige discord community + rondom mijn spellen - Je zou eens lid moeten worden van de discord server (engelstalig)!

- The soundtrack was made by Peppsen - He's awesome.

+ De muziek is gemaakt door Peppsen - Hij is geweldig.

- Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + Tot slot wil ik mijn beste vriend Niklas bedanken - Zonder onze + factorio-sessies zou dit spel nooit bestaan hebben. changelog: title: Changelog @@ -783,6 +781,6 @@ demo: importingGames: Savegames importeren oneGameLimit: Gelimiteerd tot één savegame customizeKeybindings: Custom sneltoetsen - exportingBase: Exporting whole Base as Image + exportingBase: Exporteer volledige basis als afbeelding settingNotAvailable: Niet beschikbaar in de demo. diff --git a/translations/base-pl.yaml b/translations/base-pl.yaml index e9a30ee2..b0900b0b 100644 --- a/translations/base-pl.yaml +++ b/translations/base-pl.yaml @@ -52,13 +52,13 @@ steamPage: [b]Zaplanowana zawartość & Sugestie społeczności[/b] - Ta gra jest open-source - Kaźdy może pomóc w rozwoju! Poza tym słucham tego, co społeczność ma do powiedzenia w kwestii gry! Staram się czytać wszystkie sugestie i odbierać jak najwięcej informacji zwrotnych na temat gry. + Ta gra jest open-source - Każdy może pomóc w rozwoju! Poza tym słucham tego, co społeczność ma do powiedzenia w kwestii gry! Staram się czytać wszystkie sugestie i odbierać jak najwięcej informacji zwrotnych na temat gry. [list] [*] Kampania, gdzie do budowy potrzeba kształtów [*] Więcej poziomów i budynków (tylko w pełnej wersji) [*] Inne mapy, może z przeszkodami - [*] Możliwość modyfikowania parametrów generowanjej mapy (ilość i rozmiar surowców, ziarno świata, itd.) + [*] Możliwość modyfikowania parametrów generowanej mapy (ilość i rozmiar surowców, ziarno świata, itd.) [*] Więcej rodzajów kształtów [*] Optymalizacja (mimo wszystko gra już działa dość płynnie!) [*] Tryb dla ślepoty barw @@ -211,7 +211,7 @@ dialogs: resetKeybindingsConfirmation: title: Zresetuj klawiszologię - desc: Ta akcja zresetuje wszystkie ustawienia klawiszologii do domyśnych wartości. Proszę potwierdzić. + desc: Ta akcja zresetuje wszystkie ustawienia klawiszologii do domyślnych wartości. Proszę potwierdzić. keybindingsResetOk: title: Reset Klawiszologii @@ -271,7 +271,7 @@ dialogs: title: Tworzenie zrzutu fabryki desc: >- Zamierzasz wyeksportować swoją fabrykę jako zrzut ekranu. W przypadku dużej - fabryki ta akja może być bardzo wolna, a nawet może spowodować zawieszenie się lub awarię gry! + fabryki ta akcja może być bardzo wolna, a nawet może spowodować zawieszenie się lub awarię gry! Czy na pewno chcesz kontynuować? ingame: @@ -500,7 +500,7 @@ buildings: description: Koloruje kształt za pomocą koloru dostarczonego od boku. Koloruje 2 kształty używając 1 barwnika. quad: name: Malarz (Poczwórny) - description: Koloruje każdą ćwiarkę kształtu na inny kolor, używając dostarczonych kolorów. + description: Koloruje każdą ćwiartkę kształtu na inny kolor, używając dostarczonych kolorów. mirrored: name: *painter description: *painter_desc @@ -741,7 +741,7 @@ keybindings: menuOpenStats: Statystyki toggleHud: Przełącz widoczność interfejsu - toggleFPSInfo: Pokaż Licznik FPS i infomacje do debugowania + toggleFPSInfo: Pokaż Licznik FPS i informacje do debugowania belt: *belt splitter: *splitter underground_belt: *underground_belt diff --git a/translations/base-ru.yaml b/translations/base-ru.yaml index 1c4311fc..6935440d 100644 --- a/translations/base-ru.yaml +++ b/translations/base-ru.yaml @@ -76,10 +76,10 @@ global: # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: - thousands: тыс. - millions: млн - billions: млрд - trillions: трлн + thousands: ' тыс.' + millions: ' млн' + billions: ' млрд' + trillions: ' трлн' # Shown for infinitely big numbers infinite: ∞ @@ -120,7 +120,7 @@ demoBanners: mainMenu: play: Играть changelog: Список изменений - importSavegame: Импортировать сохраненную игру + importSavegame: Импорт openSourceHint: Это игра с открытым исходным кодом! discordLink: Оффициальный Дискорд Сервер helpTranslate: Помоги с переводом! @@ -156,7 +156,7 @@ mainMenu: contestOver: Этот конкурс закончился - присоединяйтесь в дискорде, чтобы получать уведомления о новых конкурсах! continue: Продолжить newGame: Новая Игра - madeBy: Создано + madeBy: Создал dialogs: buttons: @@ -340,7 +340,7 @@ ingame: # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: МАКСИМАЛЬНЫЙ УРОВЕНЬ (Скорость x) + maximumLevel: Скорость x (макс.) # The "Statistics" window statistics: @@ -476,8 +476,8 @@ buildings: mixer: default: - name: &mixer Смеситель - description: Смешивает два цвета с помощью аддитивного смешивания. + name: &mixer Смешиватель + description: Аддитивно смешивает цвета двух красителей. painter: default: @@ -523,7 +523,7 @@ storyRewards: reward_mixer: title: Смешивание Цветов - desc: Разблокирован смеситель! Объедините два цвета в этом здании, используя аддитивное смешивание! + desc: Разблокирован смешиватель! Объедините два цвета в этом здании, используя аддитивное смешивание! reward_stacker: title: Объединитель diff --git a/translations/base-zh-CN.yaml b/translations/base-zh-CN.yaml index 8ce591dd..4263f618 100644 --- a/translations/base-zh-CN.yaml +++ b/translations/base-zh-CN.yaml @@ -19,10 +19,37 @@ # the basic structure so the game also detects it. # +# Chinese translation dictionary. TODO: better names for the buildings. +# Standalone:独立版 +# Demo:演示版 +# Level:关/关卡 +# Shape:图形 +# tile:格子/格 +# Keybind:按键设置 +# Menu:主界面 +# Center/Hub:基地 +# Upgrade:建筑升级/升级 +# Efficiency:效率 +# Building:建筑 +# Variant:建筑变体 +# Belt: 传送带 +# Balancer:平衡机 +# Compact Balancer:小型合流机 +# Merger:合并机 +# Tunnel:隧道 +# Extractor:开采机 +# Cutter:切割机 +# Rotate:旋转机 +# Stacker:堆叠机 +# Color Mixer:混色机 +# Painter:上色机 +# Trash:垃圾桶 + steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. - + shortText: shapez.io 是一款在无边际的地图上建造工厂、自动化生产与组合愈加复杂的图形的游戏。 + # shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: # - Do not translate the first line (This is the gif image at the start of the store) @@ -30,77 +57,80 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and combination of shapes. Deliver the requested, increasingly complex shapes to progress within the game and unlock upgrades to speed up your factory. + shapez.io 是一款在无边际的地图上建造工厂、自动化生产与组合愈加复杂的图形的游戏。提交任务,制造更复杂的流水线,解锁升级来提升您工厂的运作速度。 - Since the demand raises you will have to scale up your factory to fit the needs - Don't forget about resources though, you will have to expand in the [b]infinite map[/b]! + 你将会需要随着不断上升得需求扩大你的工厂。当然,不要忘记你可以在[b]无尽[/b]的地图上开采资源! - Since shapes can get boring soon you need to mix colors and paint your shapes with it - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + 只对图形进行加工可能会使你感到无聊。我们为你准备了颜色资源——将红、绿、蓝三种颜色混合,生产更多不同的颜色并粉刷在图形上以满足需求。 - This game features 18 levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + 这个游戏目前有18个关卡(这应该已经能让你忙碌几个小时了!),并且正在不断地更新中。很多新关卡已经在开发计划当中! + - - [b]Standalone Advantages[/b] + [b]独立版优势[/b] [list] - [*] Waypoints - [*] Unlimited Savegames - [*] Dark Mode - [*] More settings - [*] Allow me to further develop shapez.io ❤️ - [*] More features in the future! + [*] 地图标记 + [*] 无限存档 + [*] 深色模式 + [*] 更多设置 + [*] 支持作者继续开发shapez.io❤️ + [*] 在以后还有更多特性! [/list] - [b]Planned features & Community suggestions[/b] - This game is open source - Anybody can contribute! Besides of that, I listen [b]a lot[/b] to the community! I try to read all suggestions and take as much feedback into account as possible. + [b]开发计划与社区意见[/b] + + 本游戏已开源,所有人都能参与游戏内容的开发!除此以外,我[b]非常重视[/b]玩家社区的反馈!我会阅读每一条建议并尽量顾及所有建议。 [list] - [*] Story mode where buildings cost shapes - [*] More levels & buildings (standalone exclusive) - [*] Different maps, and maybe map obstacles - [*] Configurable map creation (Edit number and size of patches, seed, and more) - [*] More types of shapes - [*] More performance improvements (Although the game already runs pretty good!) - [*] Color blind mode - [*] And much more! + [*] 要消耗图形来造建筑的的故事模式 + [*] 更多关卡&建筑(单机版独有) + [*] 更多地图,也许会有障碍物 + [*] 可配置的地图生成(矿脉密度与大小、 随机种子以及其他地图设置) + [*] 更多图形 + [*] 更多的性能改进(当然,现在游戏已经非常流畅了!) + [*] 色盲模式 + [*] 以及更多其他的功能! [/list] - - Be sure to check out my trello board for the full roadmap! https://trello.com/b/ISQncpJP/shapezio + + 记得查看我的Trello计划板!那里有所有的开发计划!https://trello.com/b/ISQncpJP/shapezio global: - loading: Loading - error: Error + loading: 加载中 + error: 错误 + # Chinese translation: There is typically no divider used for numbers. # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: "" + # TODO: Chinese translation: suffix changes every 10000 in Chinese numbering system. # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: - thousands: k + thousands: K millions: M billions: B trillions: T # Shown for infinitely big numbers - infinite: inf + infinite: 无限 time: # Used for formatting past time dates - oneSecondAgo: one second ago - xSecondsAgo: seconds ago - oneMinuteAgo: one minute ago - xMinutesAgo: minutes ago - oneHourAgo: one hour ago - xHoursAgo: hours ago - oneDayAgo: one day ago - xDaysAgo: days ago + oneSecondAgo: 1秒前 + xSecondsAgo: 秒前 + oneMinuteAgo: 1分钟前 + xMinutesAgo: 分钟前 + oneHourAgo: 1小时前 + xHoursAgo: 小时前 + oneDayAgo: 1天前 + xDaysAgo: 天前 # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h s + secondsShort: 秒 + minutesAndSecondsShort: 秒 + hoursAndMinutesShort: 小时 秒 - xMinutes: minutes + xMinutes: 分钟 keys: tab: TAB @@ -108,33 +138,33 @@ global: alt: ALT escape: ESC shift: SHIFT - space: SPACE + space: 空格 demoBanners: # This is the "advertisement" shown in the main menu and other various places - title: Demo Version + title: 演示版 intro: >- - Get the standalone to unlock all features! + 获取独立版以解锁所有功能! mainMenu: - play: Play - changelog: Changelog - importSavegame: Import - openSourceHint: This game is open source! - discordLink: Official Discord Server - helpTranslate: Help translate! + play: 开始游戏 + changelog: 更新日志 + importSavegame: 导入 + openSourceHint: 本游戏已开源! + discordLink: 官方Discord服务器 + helpTranslate: 帮助我们翻译! # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. + 很抱歉, 本游戏在当前浏览器上可能运行缓慢! 使用chrome或者获取独立版以得到更好的体验。 - savegameLevel: Level - savegameLevelUnknown: Unknown Level + savegameLevel: 第关 + savegameLevelUnknown: 未知关卡 contests: contest_01_03062020: - title: "Contest #01" - desc: Win $25 for the coolest base! + title: "竞赛 #01" + desc: 最6的工厂将能赢得25美元的奖金! longDesc: >- To give something back to you, I thought it would be cool to make weekly contests!

@@ -151,576 +181,602 @@ mainMenu:
I'm looking forward to seeing your awesome creations! - showInfo: View - contestOver: This contest has ended - Join the discord to get noticed about new contests! - continue: Continue - newGame: New Game - madeBy: Made by + showInfo: 详细信息 + contestOver: 本次竞赛已结束。加入官方Discord以收到关于新竞赛的提醒! + # contestOver: This contest has ended - Join the discord to get noticed about new contests! + continue: 继续游戏 + newGame: 新游戏 + madeBy: 作者: dialogs: buttons: - ok: OK - delete: Delete - cancel: Cancel - later: Later - restart: Restart - reset: Reset - getStandalone: Get Standalone - deleteGame: I know what I do - viewUpdate: View Update - showUpgrades: Show Upgrades - showKeybindings: Show Keybindings + ok: 确认 # 好 完成 + delete: 删除 # Delete + cancel: 取消 # Cancel + later: 以后 # Later + restart: 重启游戏 + reset: 重置 + getStandalone: 获取独立版 + deleteGame: 我知道我在做什么 + viewUpdate: 查看更新 + showUpgrades: 显示建筑升级 + showKeybindings: 显示按键设置 importSavegameError: - title: Import Error + title: 导入错误 text: >- - Failed to import your savegame: + 未能导入你的存档: importSavegameSuccess: - title: Savegame Imported + title: 导入成功 text: >- - Your savegame has been successfully imported. + 存档被成功导入 gameLoadFailure: - title: Game is broken + title: 存档损坏 text: >- - Failed to load your savegame: + 未能导入你的存档: confirmSavegameDelete: - title: Confirm deletion + title: 确认删除 text: >- - Are you sure you want to delete the game? + 你确定要删除这个存档吗? savegameDeletionError: - title: Failed to delete + title: 删除错误 text: >- - Failed to delete the savegame: + 未能删除你的存档 restartRequired: - title: Restart required + title: 需要重启游戏 text: >- - You need to restart the game to apply the settings. + 你需要重启游戏以应用变更的设置。 editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. + title: 更改按键设置 + desc: 请按下你想要使用的按键,或者按下ESC键来取消设置。 resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. - + title: 重置所有按键 + desc: 你将要重置所有按键,请确认。 + keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! - + title: 重置所有按键 + desc: 成功重置所有按键! + featureRestriction: - title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider to get the standalone for the full experience! - + title: 演示版 + desc: 你尝试使用了 功能。该功能在演示版中不可用。请考虑购买独立版以获得更好的体验。 + oneSavegameLimit: - title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone! + title: 存档数量限制 + desc: 演示版中只能保存一份存档。 请删除旧存档或者获取独立版! updateSummary: - title: New update! + title: 更新啦! desc: >- - Here are the changes since you last played: + 以下为自上次游戏以来更新的内容: + upgradesIntroduction: - title: Unlock Upgrades + title: 解锁建筑升级 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. + 不要销毁你之前建造的工厂!你生产过的所有图形都会被用来升级建筑。 + 升级菜单在屏幕右上角。 + # 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. massDeleteConfirm: - title: Confirm delete + title: 确认删除 desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + 你将要删除很多建筑,准确来说有幢! 你确定要这么做吗? blueprintsNotUnlocked: - title: Not unlocked yet + title: 未解锁 desc: >- - Blueprints have not been unlocked yet! Complete more levels to unlock them. + 你还没有解锁蓝图功能!完成更多的关卡来解锁蓝图。 keybindingsIntroduction: - title: Useful keybindings + title: 实用按键 desc: >- - This game has a lot of keybindings which make it easier to build big factories. - Here are a few, but be sure to check out the keybindings!

- CTRL + Drag: Select area to copy / delete.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
+ 这个游戏有很多能帮助搭建工厂的使用按键。 + 以下是其中的一些,记得在按键设置中查看其他的!

+ CTRL + 拖动:选择区域以复制或删除。
+ SHIFT: 按住以放置多个。
+ ALT: 反向放置传送带。
+ # desc: >- + # This game has a lot of keybindings which make it easier to build big factories. + # Here are a few, but be sure to check out the keybindings!

+ # CTRL + Drag: Select area to copy / delete.
+ # SHIFT: Hold to place multiple of one building.
+ # ALT: Invert orientation of placed belts.
createMarker: - title: New Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) + title: 创建地图标记 + desc: 给地图标记起一个的名字。你可以在名字中加入一个短代码以加入图形。(你可以在这里生成短代码。) markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + desc: 在演示版中你只能创建两个地图标记。请获取独立版以创建更多标记。 massCutConfirm: - title: Confirm cut + title: 确认剪切 desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? + 你将要剪切很多建筑,准确来说有幢! 你确定要这么做吗? exportScreenshotWarning: - title: Export screenshot + title: 工厂截图 desc: >- - You requested to export your base as a screenshot. Please note that this can - be quite slow for a big base and even crash your game! + 你将要导出你的工厂的截图。如果你的基地很大,截图过程将会很慢,且有可能导致游戏崩溃! ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: - moveMap: Move - selectBuildings: Select area - stopPlacement: Stop placement - rotateBuilding: Rotate building - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto orientation - toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create Marker - delete: Destroy - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + moveMap: 移动地图 + selectBuildings: 选择区域 + stopPlacement: 停止放置 + rotateBuilding: 转动建筑 + placeMultiple: 放置多个 + reverseOrientation: 反向放置 + disableAutoOrientation: 关闭自动定向 + toggleHud: 开关HUD + placeBuilding: 放置建筑 + createMarker: 创建地图标记 + delete: 销毁 + pasteLastBlueprint: 粘贴上一个蓝图 + lockBeltDirection: 启用传送带规划 + plannerSwitchSide: 规划器换边 # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Press to cycle variants. + cycleBuildingVariants: 按键以选择建筑变体. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- - Hotkey: + 快捷键: infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s - itemsPerSecondDouble: (x2) + speed: 效率 + range: 范围 + storage: 容量 + oneItemPerSecond: 1个/秒 + itemsPerSecond: 个/秒 + itemsPerSecondDouble: (2倍) - tiles: tiles + tiles: 格 # The notification when completing a level levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level + levelTitle: 第关 + completed: 完成 + unlockText: 解锁! + buttonNextLevel: 下一关 # Notifications on the lower right notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. + newUpgrade: 有新更新啦! + gameSaved: 游戏已保存。 # Mass select information, this is when you hold CTRL and then drag with your mouse # to select multiple buildings massSelect: - infoText: Press to cut, to copy, to remove and to cancel. + infoText: 剪切,复制,删除,取消. # The "Upgrades" window shop: - title: Upgrades - buttonUnlock: Upgrade + title: 建筑升级 + buttonUnlock: 升级 # Gets replaced to e.g. "Tier IX" - tier: Tier + tier: 级 # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] + # Chinese translation: Chinese characters for each tier + tierLabels: [一, 二, 三, 四, 五, 六, 七, 八, 九, 十] - maximumLevel: MAXIMUM LEVEL (Speed x) + maximumLevel: 最高级(倍效率) # The "Statistics" window statistics: - title: Statistics + title: 统计信息 dataSources: stored: - title: Stored - description: Displaying amount of stored shapes in your central building. + title: 储存 + description: 显示基地中每种图形储存的数量。 produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + title: 生产 + description: 显示所有正在被生产的图形数量,包括中间产物。 delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + title: 送达 + description: 显示图形送达基地的速度。 + noShapesProduced: 你还没有生产任何图形。 # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m + shapesPerMinute: 个/分钟 + # Settings menu, when you press "ESC" settingsMenu: - playtime: Playtime + playtime: 游戏时间 - buildingsPlaced: Buildings - beltsPlaced: Belts + buildingsPlaced: 建筑数量 + beltsPlaced: 传送带数量 buttons: - continue: Continue - settings: Settings - menu: Return to menu + continue: 继续 + settings: 设置 + menu: 回到主界面 # Bottom left tutorial hints tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close + title: 需要帮助? + showHint: 显示帮助 + hideHint: 关闭 # When placing a blueprint blueprintPlacer: - cost: Cost + cost: 需要 # Map markers waypoints: - waypoints: Markers - hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. + waypoints: 地图标记 + hub: 基地 + description: 左键快速跳转到地图标记,右键删除地图标记。

从当前视图中创建地图标记,或者在选定的位置上使用右键创建地图标记。 + creationSuccessNotification: 成功创建地图标记。 # Interactive tutorial interactiveTutorial: - title: Tutorial + title: 教程 hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: 在圆形矿脉上放一个开采机来获取圆形! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + 用传送带将你的开采机连接到基地上!

提示:用你的鼠标按下并拖动传送带! 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + 这不是一个挂机游戏!建造更多的开采机和传送带来更快地完成目标。

+ 提示:按住SHIFT键来放置多个开采机,用R键旋转它们。 # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: 传送带、平衡机、隧道 + description: 效率 倍 → 倍 miner: - name: Extraction - description: Speed x → x + name: 开采 + description: 效率 倍 → 倍 processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: 切割、旋转、堆叠 + description: 效率 倍 → 倍 painting: - name: Mixing & Painting - description: Speed x → x + name: 混色、上色 + description: 效率 倍 → 倍 # Buildings and their name / description buildings: belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. + name: &belt 传送带 + description: 运送物品,按住并拖动来放置多个传送带。 miner: # Internal name for the Extractor default: - name: &miner Extractor - description: Place over a shape or color to extract it. + name: &miner 开采机 + description: 在图形或者颜色上放置来开采他们。 chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. + name: 链式开采机 + description: 在图形或者颜色上放置来开采他们。可以被链接在一起。 underground_belt: # Internal name for the Tunnel default: - name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. + name: &underground_belt 隧道 + description: 可以从其他传送带或建筑底下方运送物品。 tier2: - name: Tunnel Tier II - description: Allows to tunnel resources under buildings and belts. + name: 二级隧道 + description: 可以从其他传送带或建筑底下方运送物品。 splitter: # Internal name for the Balancer default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. + name: &splitter 平衡机 + description: 多功能——将所有输入平均分配到所有输出。 compact: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: 小型合流机 + description: 把两个输入合并到一个输出上。 compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: 小型合流机 + description: 把两个输入合并到一个输出上。 cutter: default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! + name: &cutter 切割机 + description: 将图形从上到下切开并输出。 如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other part or it will stall! + name: 切割机(四分) + description: 将输入的图形切成四块。 如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater 旋转机 + description: 将图形顺时针旋转90度。 ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. + name: 旋转机(逆时针) + description: 将图形逆时针旋转90度。 stacker: default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. + name: &stacker 堆叠机 + description: 将输入的图形拼贴在一起。如果不能被直接拼贴,右边的图形会被堆叠在左边的图形上面. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. + name: &mixer 混色机 + description: 将两个颜色混合在一起。(加法混合) painter: default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the right input. + name: &painter 上色机 + description: &painter_desc 将整个图形涂上输入的颜色。 double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + name: 上色机(双倍) + description: 同时为两个输入的图形上色,每次上色只消耗一份颜色。 quad: - name: Painter (Quad) - description: Allows to color each quadrant of the shape with a different color. + name: 上色机(四向) + description: 为图形的四个角涂上不同的颜色。 mirrored: name: *painter description: *painter_desc trash: default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. + name: &trash 垃圾桶 + description: 从所有四个方向上输入物品并销毁它们。永远。 storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + name: 仓库 + description: 储存多余的物品,有一定储存上限。可以被用来作为溢流门。 hub: - deliver: Deliver - toUnlock: to unlock + deliver: 交付 + toUnlock: 来解锁 levelShortcut: LVL storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: - title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + title: 切割图形 + desc: 切割机已解锁。不论切割机的方向,它都会把图形从上到下切成两半。

记得把不需要的部分处理掉,否则这个这个建筑会停止工作。为此我给你准备了垃圾桶,它会把所有放进去的物品销毁掉。 reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + title: 顺时针旋转 + desc: 旋转机已解锁。它会顺时针旋转输入的图形90度。 reward_painter: - title: Painting + title: 上色 desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, I'm working on a solution already! + 上色机已解锁。和图形一样,从颜色矿脉中开采颜色,然后将在上色机中将颜色涂在图形上。

PS:我们正在开发色盲模式! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + title: 混合颜色 + desc: 混色机已解锁。在这个建筑中将两个颜色混合在一起(加法混合)。 reward_stacker: - title: Combiner - desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + title: 堆叠 + desc: 堆叠机已解锁。堆叠机会尝试把两个输入的图形拼贴在一起。如果有重叠的部分,右边的输入会被堆叠在左边的输入上方! reward_splitter: - title: Splitter/Merger - desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ title: 分离与合并 + desc: 平衡机已解锁。在大型工厂中,平衡机负责合并或分离多个传送带上的物品。

reward_tunnel: - title: Tunnel - desc: The tunnel has been unlocked - You can now pipe items through belts and buildings with it! + title: 隧道 + desc: 隧道已解锁。你现在可以从其他传送带或建筑底下运送物品了! reward_rotater_ccw: - title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle its variants! + title: 逆时针旋转 + desc: 旋转机逆时针变体已解锁。这个变体可以逆时针旋转图形。选择旋转机然后按“T”键来选取这个变体。 reward_miner_chainable: - title: Chaining Extractor - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + title: 链式开采机 + desc: 链式开采机变体已解锁。它是开采机的一个变体。它可以将开采出来的资源传递给其他的开采机,使得资源提取更加高效! reward_underground_belt_tier_2: - title: Tunnel Tier II - desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + title: 二级隧道 + desc: 二级隧道变体已解锁。这个隧道有更长的传输距离。你还可以混用不同的隧道变体! reward_splitter_compact: - title: Compact Balancer + title: 小型合流机 desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + 小型合流机变体已解锁。它可以把两个输入合并到一个输出上。 reward_cutter_quad: - title: Quad Cutting - desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + title: 四分切割机 + desc: 切割机四分变体已解锁。它可以将输入的图形切成四块而不只是左右两块。 reward_painter_double: - title: Double Painting - desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + title: 双倍上色机 + desc: 上色机双倍变体已解锁。 它像普通上色机一样为图形上色,只是它可以同时为两个图形上色,每次只消耗一份颜色! reward_painter_quad: - title: Quad Painting - desc: You have unlocked a variant of the painter - It allows to paint each part of the shape individually! + title: 四向上色机 + desc: 上色机四向变体已解锁。它可以在一个图形的四个角上涂不同的颜色! reward_storage: - title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + title: 仓库 + desc: 仓库变体已解锁。它可以暂时储存一些材料,有容量上限。 reward_freeplay: - title: Freeplay - desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + title: 自由模式 + desc: 恭喜你!你解锁了自由模式!现在图形将会是随机生成的!(不用担心,我计划在独立版本中加入更多内容!) reward_blueprints: - title: Blueprints - desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + title: 蓝图 + desc: 你现在可以复制粘贴你的工厂的一部分了!按住CTRL键并拖动鼠标来选择一块区域,然后按C键复制。

粘贴并不是免费的,你需要使用蓝图图形来粘贴你的蓝图。蓝图图形是你刚刚交付的图形。 # Special reward, which is shown when there is no reward actually no_reward: - title: Next level + title: 下一关 desc: >- - This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! + 这一关没有奖励,但是下一关有!

PS: 你生产过的所有图形都会被用来升级建筑。 no_reward_freeplay: - title: Next level + title: 下一关 desc: >- - Congratulations! By the way, more content is planned for the standalone! + 恭喜你!另外,我们已经计划在独立版中加入更多内容! settings: - title: Settings + title: 设置 categories: - game: Game - app: Application + game: 游戏内容 + app: 应用 versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built + dev: 开发版本 # Development + staging: 预览版本 # Staging + prod: 正式版本 # Production + buildDate: 于编译 labels: uiScale: - title: Interface scale + title: 用户界面大小 description: >- - Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale. + 改变用户界面大小。用户界面会随着设备分辨率缩放,这个设置决定缩放比例。 scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge + super_small: 最小 + small: 较小 + regular: 正常 + large: 较大 + huge: 最大 scrollWheelSensitivity: - title: Zoom sensitivity + title: 缩放灵敏度 description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + 改变缩放灵敏度(鼠标滚轮或者触控板)。 sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast + super_slow: 最低 + slow: 较低 + regular: 正常 + fast: 较高 + super_fast: 最高 language: - title: Language + title: 语言 description: >- - Change the language. All translations are user contributed and might be incomplete! + 改变语言。所有的翻译皆由玩家提供,且有可能正在施工中! fullscreen: - title: Fullscreen + title: 全屏 description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + 全屏以获得更好的游戏体验。仅在独立版中可用。 soundsMuted: - title: Mute Sounds + title: 关闭音效 description: >- - If enabled, mutes all sound effects. + 关闭所有音效。 musicMuted: - title: Mute Music + title: 关闭音乐 description: >- - If enabled, mutes all music. + 关闭所有音乐。 theme: - title: Game theme + title: 界面主题 description: >- - Choose the game theme (light / dark). + 选择界面主题(深色或浅色)。 themes: - dark: Dark - light: Light + dark: 深色 + light: 浅色 refreshRate: - title: Simulation Target + title: 模拟频率、刷新频率 description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + 如果你的显示器是144hz的,请在这里更改刷新频率,这样游戏可以正确地根据你的屏幕进行模拟。但是如果你的电脑性能不佳,提高刷新频率可能降低帧数。 + # description: >- + # If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. alwaysMultiplace: - title: Multiplace + title: 多重放置 description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下SHIFT键。 + # description: >- + # If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. offerHints: - title: Hints & Tutorials + title: 提示与教程 description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + 是否显示提示、教程以及一些其他的帮助理解游戏的UI元素。 + # description: >- + # Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. movementSpeed: - title: Movement speed - description: Changes how fast the view moves when using the keyboard. + title: 移动速度 + description: 改变摄像头移动速度 speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast + super_slow: 最慢 + slow: 较慢 + regular: 正常 + fast: 较快 + super_fast: 非常快 + extremely_fast: 最快 + enableTunnelSmartplace: - title: Smart Tunnels + title: 智能隧道放置 description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + 启用后,放置隧道时会将多余的传送带移除。 + 此外,拖动隧道可以快速铺设隧道,以及移除不必要的隧道。 vignette: - title: Vignette + title: 晕映 description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + 启用晕映,将屏幕角落里的颜色变深,更容易阅读文本。 keybindings: - title: Keybindings + title: 按键设置 hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + 提示:使用CTRL、SHIFT、ALT! 这些建在放置建筑时有不同的效果。 + # hint: >- + # Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - resetKeybindings: Reset Keyinbindings + resetKeybindings: 重置按键设置 categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + general: 通用 + ingame: 游戏 + navigation: 视角 + placement: 放置 + massSelect: 批量选择 + buildings: 建筑快捷键 + placementModifiers: 放置建筑修饰键 mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - centerMap: Center Map + confirm: 确认 + back: 返回 + mapMoveUp: 上 + mapMoveRight: 右 + mapMoveDown: 下 + mapMoveLeft: 左 + centerMap: 回到基地 + # confirm: Confirm + # back: Back + # mapMoveUp: Move Up + # mapMoveRight: Move Right + # mapMoveDown: Move Down + # mapMoveLeft: Move Left + # centerMap: Center Map - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: 放大 + mapZoomOut: 缩小 + createMarker: 创建地图标记 - menuOpenShop: Upgrades - menuOpenStats: Statistics + menuOpenShop: 升级菜单 + menuOpenStats: 统计菜单 - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info + toggleHud: 开关HUD + toggleFPSInfo: 开关帧数与调试信息 belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -732,57 +788,61 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement - rotateWhilePlacing: Rotate + abortBuildingPlacement: 取消放置 + rotateWhilePlacing: 顺时针旋转 rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete - cycleBuildings: Cycle Buildings + 修饰键: 改为逆时针旋转 + cycleBuildingVariants: 选择建筑变体 + # cycleBuildingVariants: Cycle Variants + confirmMassDelete: 确认批量删除 + cycleBuildings: 选择建筑 + # cycleBuildings: Cycle Buildings + massSelectStart: 开始批量选择 + massSelectSelectMultiple: 选择多个区域 + massSelectCopy: 复制 - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area + placementDisableAutoOrientation: 取消自动定向 + placeMultiple: 继续放置 + placeInverse: 反向放置传送带 + pasteLastBlueprint: 粘贴上一张蓝图 + massSelectCut: 剪切 + exportScreenshot: 导出截图 + mapMoveFaster: 快速移动 - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation - pasteLastBlueprint: Paste last blueprint - massSelectCut: Cut area - exportScreenshot: Export whole Base as Image - mapMoveFaster: Move Faster - lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + lockBeltDirection: 启用传送带规划 + switchDirectionLockSide: '规划器:换边' about: - title: About this Game + title: 关于游戏 + # title: About this Game body: >- - This game is open source and developed by Tobias Springer (this is me).

+ 本游戏由Tobias Springer(我)开发,并且已经开源。

- If you want to contribute, check out shapez.io on github.

+ 如果你想参与开发,请查看shapez.io on github

- This game wouldn't have been possible without the great discord community - around my games - You should really join the discord server!

+ 这个游戏的开发少不了热情的Discord社区。请加入我们的Discord 服务器

- The soundtrack was made by Peppsen - He's awesome.

- - Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + 本游戏的音乐由Peppsen制作——他是个很棒的伙伴。

+ 最后,我想感谢我最好的朋友Niklas——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 changelog: - title: Changelog + title: 版本日志 demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image + restoringGames: 恢复存档 #中? + importingGames: 倒入存档 #中? + oneGameLimit: 最多一个存档 + customizeKeybindings: 按键设置 + # customizeKeybindings: Customizing Keybindings + exportingBase: 导出工厂截图 + settingNotAvailable: 在演示版中不可用。 + + + - settingNotAvailable: Not available in the demo.