diff --git a/.gitignore b/.gitignore index 566478c8..3c599ecc 100644 --- a/.gitignore +++ b/.gitignore @@ -115,3 +115,4 @@ tmp_standalone_files # Local config config.local.js +.DS_Store diff --git a/artwork/buildings/buildings_2x2.psd b/artwork/buildings/buildings_2x2.psd index 7017b4d9..00f31093 100644 --- a/artwork/buildings/buildings_2x2.psd +++ b/artwork/buildings/buildings_2x2.psd @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7931a4ba2104bbf7de3a1332617d5a056e34c55bab751821a168a83e0b91793 -size 683910 +oid sha256:9d8a4254944d83882513a062e77406419d94c3058a7ad657a5a318d45cc5443f +size 902131 diff --git a/artwork/steam/announcement.png b/artwork/steam/announcement.png index 1aacc62e..cc0861db 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 30dce1e6..518a49ac 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:ebde52e75e54d2f4add0cf498c85f059082a0745212a23c4de7328a7d78b00a5 -size 238170 +oid sha256:ae83b8805191eeba13016e40216fc4781ac3958e6886769ce8677ea28370d13e +size 239706 diff --git a/artwork/steam/devlog.png b/artwork/steam/devlog.png index 8e5c29e6..9abdefe1 100644 Binary files a/artwork/steam/devlog.png and b/artwork/steam/devlog.png differ diff --git a/artwork/steam/devlog.psd b/artwork/steam/devlog.psd index 0c06ba5d..7cd9b0a7 100644 --- a/artwork/steam/devlog.psd +++ b/artwork/steam/devlog.psd @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:746c6cf3f0284798a78c08f77d7e9d0c28b02323081fda42b5fa876a7ade29a0 -size 205925 +oid sha256:40d458f800344d819ad4d3f38943f53f399258369ee5c20f6583d1b49847465f +size 188255 diff --git a/artwork/ui/toolbar-icons.psd b/artwork/ui/toolbar-icons.psd index e8efcfa3..9b453e15 100644 --- a/artwork/ui/toolbar-icons.psd +++ b/artwork/ui/toolbar-icons.psd @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:037d27409bf78b828470e553ee0f29304eda24c46598151bb4b9c69c66a6c6c1 -size 146363 +oid sha256:27c8d1eaa48beb7187e37244bd6ef7f43429be84ac88fffa96a4d72eb0e6565b +size 158809 diff --git a/gulp/gulpfile.js b/gulp/gulpfile.js index cf0077bd..f2fdd9d4 100644 --- a/gulp/gulpfile.js +++ b/gulp/gulpfile.js @@ -269,7 +269,7 @@ gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.post // Builds everything (standalone-beta) gulp.task( "step.standalone-beta.code", - gulp.series("sounds.fullbuild", "translations.fullBuild", "js.standalone-beta") + gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta") ); gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code")); gulp.task( @@ -284,7 +284,7 @@ gulp.task( // Builds everything (standalone-prod) gulp.task( "step.standalone-prod.code", - gulp.series("sounds.fullbuild", "translations.fullBuild", "js.standalone-prod") + gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod") ); gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code")); gulp.task( diff --git a/gulp/package.json b/gulp/package.json index 653db52d..1fd39c40 100644 --- a/gulp/package.json +++ b/gulp/package.json @@ -23,6 +23,7 @@ "browser-sync": "^2.24.6", "circular-dependency-plugin": "^5.0.2", "circular-json": "^0.5.9", + "clipboard-copy": "^3.1.0", "colors": "^1.3.3", "core-js": "3", "crypto": "^1.0.1", diff --git a/gulp/sounds.js b/gulp/sounds.js index 0e8dee12..c38e7a6e 100644 --- a/gulp/sounds.js +++ b/gulp/sounds.js @@ -40,6 +40,30 @@ function gulptasksSounds($, gulp, buildFolder) { .pipe(gulp.dest(path.join(builtSoundsDir, "music"))); }); + // Encodes the game music in high quality for the standalone + gulp.task("sounds.musicHQ", () => { + return gulp + .src([path.join(soundsDir, "music", "**", "*.wav"), path.join(soundsDir, "music", "**", "*.mp3")]) + .pipe($.plumber()) + .pipe( + $.cache( + $.fluentFfmpeg("mp3", function (cmd) { + return cmd + .audioBitrate(256) + .audioChannels(2) + .audioFrequency(44100) + .audioCodec("libmp3lame") + .audioFilters(["volume=0.15"]); + }), + { + name: "music-high-quality", + fileCache, + } + ) + ) + .pipe(gulp.dest(path.join(builtSoundsDir, "music"))); + }); + // Encodes the ui sounds gulp.task("sounds.sfxGenerateSprites", () => { return gulp @@ -91,8 +115,10 @@ function gulptasksSounds($, gulp, buildFolder) { }); gulp.task("sounds.buildall", gulp.parallel("sounds.music", "sounds.sfx")); + gulp.task("sounds.buildallHQ", gulp.parallel("sounds.musicHQ", "sounds.sfx")); gulp.task("sounds.fullbuild", gulp.series("sounds.clear", "sounds.buildall", "sounds.copy")); + gulp.task("sounds.fullbuildHQ", gulp.series("sounds.clear", "sounds.buildallHQ", "sounds.copy")); gulp.task("sounds.dev", gulp.series("sounds.buildall", "sounds.copy")); } diff --git a/gulp/webpack.config.js b/gulp/webpack.config.js index 274cc3ef..26923796 100644 --- a/gulp/webpack.config.js +++ b/gulp/webpack.config.js @@ -36,7 +36,6 @@ module.exports = ({ watch = false, standalone = false }) => { lzString.compressToEncodedURIComponent("http://localhost:10005/v1") ), G_IS_DEV: "true", - G_IS_PROD: "false", G_IS_RELEASE: "false", G_IS_MOBILE_APP: "false", G_IS_BROWSER: "true", diff --git a/gulp/webpack.production.config.js b/gulp/webpack.production.config.js index 837cfe8b..f80a69d2 100644 --- a/gulp/webpack.production.config.js +++ b/gulp/webpack.production.config.js @@ -24,7 +24,6 @@ module.exports = ({ assertAlways: "window.assert", abstract: "window.assert(false, 'abstract method called');", G_IS_DEV: "false", - G_IS_PROD: "true", G_IS_RELEASE: environment === "prod" ? "true" : "false", G_IS_STANDALONE: standalone ? "true" : "false", G_IS_BROWSER: isBrowser ? "true" : "false", diff --git a/gulp/yarn.lock b/gulp/yarn.lock index 755d1648..a0a8d4f2 100644 --- a/gulp/yarn.lock +++ b/gulp/yarn.lock @@ -2923,6 +2923,11 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= +clipboard-copy@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/clipboard-copy/-/clipboard-copy-3.1.0.tgz#4c59030a43d4988990564a664baeafba99f78ca4" + integrity sha512-Xsu1NddBXB89IUauda5BIq3Zq73UWkjkaQlPQbLNvNsd5WBMnTWPNKYR6HGaySOxGYZ+BKxP2E9X4ElnI3yiPA== + cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" diff --git a/res/ui/building_icons/energy_generator.png b/res/ui/building_icons/energy_generator.png new file mode 100644 index 00000000..ab724a7b Binary files /dev/null and b/res/ui/building_icons/energy_generator.png differ diff --git a/res/ui/building_tutorials/underground_belt-tier2.png b/res/ui/building_tutorials/underground_belt-tier2.png index 476ad4da..69981b26 100644 Binary files a/res/ui/building_tutorials/underground_belt-tier2.png and b/res/ui/building_tutorials/underground_belt-tier2.png differ diff --git a/res/ui/icons/info_button.png b/res/ui/icons/info_button.png new file mode 100644 index 00000000..abdf2af9 Binary files /dev/null and b/res/ui/icons/info_button.png differ diff --git a/res/ui/languages/es-419.svg b/res/ui/languages/es-419.svg index 7deefd93..5f671625 100644 --- a/res/ui/languages/es-419.svg +++ b/res/ui/languages/es-419.svg @@ -1,25 +1,78 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/ui/main_menu/changelog.svg b/res/ui/main_menu/changelog.svg new file mode 100644 index 00000000..f12bff7b --- /dev/null +++ b/res/ui/main_menu/changelog.svg @@ -0,0 +1,2 @@ + + diff --git a/res/ui/main_menu/reddit.svg b/res/ui/main_menu/reddit.svg new file mode 100644 index 00000000..46310cbf --- /dev/null +++ b/res/ui/main_menu/reddit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/ui/main_menu/translate.svg b/res/ui/main_menu/translate.svg new file mode 100644 index 00000000..e38b3392 --- /dev/null +++ b/res/ui/main_menu/translate.svg @@ -0,0 +1,2 @@ + + diff --git a/res_built/atlas/atlas0_10.json b/res_built/atlas/atlas0_10.json index 8aeef6ae..342ea730 100644 --- a/res_built/atlas/atlas0_10.json +++ b/res_built/atlas/atlas0_10.json @@ -2,7 +2,7 @@ "sprites/belt/forward_0.png": { - "frame": {"x":204,"y":26,"w":13,"h":13}, + "frame": {"x":205,"y":110,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -10,7 +10,7 @@ }, "sprites/belt/forward_1.png": { - "frame": {"x":221,"y":26,"w":13,"h":13}, + "frame": {"x":222,"y":110,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -18,7 +18,7 @@ }, "sprites/belt/forward_2.png": { - "frame": {"x":238,"y":26,"w":13,"h":13}, + "frame": {"x":311,"y":26,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -26,7 +26,7 @@ }, "sprites/belt/forward_3.png": { - "frame": {"x":255,"y":26,"w":13,"h":13}, + "frame": {"x":379,"y":26,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -34,7 +34,7 @@ }, "sprites/belt/forward_4.png": { - "frame": {"x":272,"y":26,"w":13,"h":13}, + "frame": {"x":376,"y":66,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -42,7 +42,183 @@ }, "sprites/belt/forward_5.png": { - "frame": {"x":245,"y":112,"w":13,"h":13}, + "frame": {"x":396,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_6.png": +{ + "frame": {"x":393,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_7.png": +{ + "frame": {"x":413,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_8.png": +{ + "frame": {"x":410,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_9.png": +{ + "frame": {"x":430,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_10.png": +{ + "frame": {"x":239,"y":110,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_11.png": +{ + "frame": {"x":206,"y":68,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_12.png": +{ + "frame": {"x":223,"y":68,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_13.png": +{ + "frame": {"x":240,"y":68,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_14.png": +{ + "frame": {"x":243,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_15.png": +{ + "frame": {"x":260,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_16.png": +{ + "frame": {"x":277,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_17.png": +{ + "frame": {"x":257,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_18.png": +{ + "frame": {"x":274,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_19.png": +{ + "frame": {"x":294,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_20.png": +{ + "frame": {"x":328,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_21.png": +{ + "frame": {"x":291,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_22.png": +{ + "frame": {"x":308,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_23.png": +{ + "frame": {"x":325,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_24.png": +{ + "frame": {"x":345,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_25.png": +{ + "frame": {"x":362,"y":26,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_26.png": +{ + "frame": {"x":342,"y":66,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/forward_27.png": +{ + "frame": {"x":359,"y":66,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -50,7 +226,7 @@ }, "sprites/belt/left_0.png": { - "frame": {"x":262,"y":112,"w":13,"h":13}, + "frame": {"x":443,"y":83,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -58,7 +234,7 @@ }, "sprites/belt/left_1.png": { - "frame": {"x":279,"y":112,"w":13,"h":13}, + "frame": {"x":450,"y":63,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -66,7 +242,7 @@ }, "sprites/belt/left_2.png": { - "frame": {"x":296,"y":112,"w":13,"h":13}, + "frame": {"x":484,"y":3,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -74,7 +250,7 @@ }, "sprites/belt/left_3.png": { - "frame": {"x":289,"y":49,"w":13,"h":13}, + "frame": {"x":501,"y":54,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -82,7 +258,7 @@ }, "sprites/belt/left_4.png": { - "frame": {"x":306,"y":49,"w":13,"h":13}, + "frame": {"x":513,"y":37,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -90,7 +266,183 @@ }, "sprites/belt/left_5.png": { - "frame": {"x":323,"y":49,"w":13,"h":13}, + "frame": {"x":515,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_6.png": +{ + "frame": {"x":518,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_7.png": +{ + "frame": {"x":485,"y":105,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_8.png": +{ + "frame": {"x":497,"y":88,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_9.png": +{ + "frame": {"x":511,"y":71,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_10.png": +{ + "frame": {"x":460,"y":80,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_11.png": +{ + "frame": {"x":433,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_12.png": +{ + "frame": {"x":447,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_13.png": +{ + "frame": {"x":450,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_14.png": +{ + "frame": {"x":462,"y":37,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_15.png": +{ + "frame": {"x":464,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_16.png": +{ + "frame": {"x":467,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_17.png": +{ + "frame": {"x":467,"y":54,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_18.png": +{ + "frame": {"x":479,"y":37,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_19.png": +{ + "frame": {"x":481,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_20.png": +{ + "frame": {"x":463,"y":97,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_21.png": +{ + "frame": {"x":477,"y":71,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_22.png": +{ + "frame": {"x":484,"y":54,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_23.png": +{ + "frame": {"x":496,"y":37,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_24.png": +{ + "frame": {"x":498,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_25.png": +{ + "frame": {"x":501,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_26.png": +{ + "frame": {"x":480,"y":88,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/left_27.png": +{ + "frame": {"x":494,"y":71,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -98,7 +450,7 @@ }, "sprites/belt/right_0.png": { - "frame": {"x":313,"y":112,"w":13,"h":13}, + "frame": {"x":518,"y":54,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -106,7 +458,7 @@ }, "sprites/belt/right_1.png": { - "frame": {"x":330,"y":112,"w":13,"h":13}, + "frame": {"x":530,"y":37,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -114,7 +466,7 @@ }, "sprites/belt/right_2.png": { - "frame": {"x":340,"y":49,"w":13,"h":13}, + "frame": {"x":531,"y":88,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -122,7 +474,7 @@ }, "sprites/belt/right_3.png": { - "frame": {"x":347,"y":112,"w":13,"h":13}, + "frame": {"x":569,"y":54,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -130,7 +482,7 @@ }, "sprites/belt/right_4.png": { - "frame": {"x":357,"y":49,"w":13,"h":13}, + "frame": {"x":581,"y":37,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -138,7 +490,183 @@ }, "sprites/belt/right_5.png": { - "frame": {"x":374,"y":49,"w":13,"h":13}, + "frame": {"x":583,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_6.png": +{ + "frame": {"x":586,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_7.png": +{ + "frame": {"x":553,"y":105,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_8.png": +{ + "frame": {"x":565,"y":88,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_9.png": +{ + "frame": {"x":579,"y":71,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_10.png": +{ + "frame": {"x":532,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_11.png": +{ + "frame": {"x":535,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_12.png": +{ + "frame": {"x":502,"y":105,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_13.png": +{ + "frame": {"x":514,"y":88,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_14.png": +{ + "frame": {"x":528,"y":71,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_15.png": +{ + "frame": {"x":535,"y":54,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_16.png": +{ + "frame": {"x":547,"y":37,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_17.png": +{ + "frame": {"x":549,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_18.png": +{ + "frame": {"x":552,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_19.png": +{ + "frame": {"x":519,"y":105,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_20.png": +{ + "frame": {"x":545,"y":71,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_21.png": +{ + "frame": {"x":552,"y":54,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_22.png": +{ + "frame": {"x":564,"y":37,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_23.png": +{ + "frame": {"x":566,"y":20,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_24.png": +{ + "frame": {"x":569,"y":3,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_25.png": +{ + "frame": {"x":536,"y":105,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_26.png": +{ + "frame": {"x":548,"y":88,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/belt/right_27.png": +{ + "frame": {"x":562,"y":71,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -146,7 +674,7 @@ }, "sprites/blueprints/belt_left.png": { - "frame": {"x":391,"y":48,"w":13,"h":13}, + "frame": {"x":586,"y":54,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -154,7 +682,7 @@ }, "sprites/blueprints/belt_right.png": { - "frame": {"x":404,"y":25,"w":13,"h":13}, + "frame": {"x":596,"y":71,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -162,7 +690,7 @@ }, "sprites/blueprints/belt_top.png": { - "frame": {"x":400,"y":85,"w":13,"h":13}, + "frame": {"x":570,"y":105,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -178,15 +706,23 @@ }, "sprites/blueprints/cutter.png": { - "frame": {"x":245,"y":66,"w":36,"h":19}, + "frame": {"x":284,"y":3,"w":36,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, "sourceSize": {"w":38,"h":19} }, +"sprites/blueprints/energy_generator.png": +{ + "frame": {"x":126,"y":79,"w":36,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":36,"h":38}, + "sourceSize": {"w":38,"h":38} +}, "sprites/blueprints/miner-chainable.png": { - "frame": {"x":285,"y":66,"w":19,"h":19}, + "frame": {"x":364,"y":3,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -194,7 +730,7 @@ }, "sprites/blueprints/miner.png": { - "frame": {"x":285,"y":89,"w":19,"h":19}, + "frame": {"x":302,"y":106,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -202,7 +738,7 @@ }, "sprites/blueprints/mixer.png": { - "frame": {"x":204,"y":68,"w":37,"h":19}, + "frame": {"x":247,"y":85,"w":37,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, @@ -242,7 +778,7 @@ }, "sprites/blueprints/rotater-ccw.png": { - "frame": {"x":289,"y":26,"w":19,"h":19}, + "frame": {"x":325,"y":106,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -250,7 +786,7 @@ }, "sprites/blueprints/rotater.png": { - "frame": {"x":312,"y":26,"w":19,"h":19}, + "frame": {"x":328,"y":83,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -258,7 +794,7 @@ }, "sprites/blueprints/splitter-compact-inverse.png": { - "frame": {"x":327,"y":3,"w":19,"h":19}, + "frame": {"x":348,"y":106,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -266,7 +802,7 @@ }, "sprites/blueprints/splitter-compact.png": { - "frame": {"x":308,"y":66,"w":19,"h":19}, + "frame": {"x":351,"y":83,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -274,7 +810,7 @@ }, "sprites/blueprints/splitter.png": { - "frame": {"x":249,"y":43,"w":36,"h":19}, + "frame": {"x":324,"y":3,"w":36,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, @@ -282,7 +818,7 @@ }, "sprites/blueprints/stacker.png": { - "frame": {"x":204,"y":91,"w":37,"h":19}, + "frame": {"x":243,"y":3,"w":37,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, @@ -290,7 +826,7 @@ }, "sprites/blueprints/trash-storage.png": { - "frame": {"x":126,"y":79,"w":35,"h":38}, + "frame": {"x":204,"y":3,"w":35,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":35,"h":38}, @@ -298,7 +834,7 @@ }, "sprites/blueprints/trash.png": { - "frame": {"x":335,"y":26,"w":19,"h":19}, + "frame": {"x":371,"y":106,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -306,7 +842,7 @@ }, "sprites/blueprints/underground_belt_entry-tier2.png": { - "frame": {"x":381,"y":26,"w":19,"h":18}, + "frame": {"x":417,"y":106,"w":19,"h":18}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, @@ -314,7 +850,7 @@ }, "sprites/blueprints/underground_belt_entry.png": { - "frame": {"x":354,"y":89,"w":19,"h":16}, + "frame": {"x":256,"y":108,"w":19,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, @@ -322,7 +858,7 @@ }, "sprites/blueprints/underground_belt_exit-tier2.png": { - "frame": {"x":364,"y":109,"w":19,"h":16}, + "frame": {"x":279,"y":108,"w":19,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, @@ -330,7 +866,7 @@ }, "sprites/blueprints/underground_belt_exit.png": { - "frame": {"x":377,"y":66,"w":19,"h":16}, + "frame": {"x":440,"y":105,"w":19,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, @@ -338,7 +874,7 @@ }, "sprites/buildings/belt_left.png": { - "frame": {"x":262,"y":112,"w":13,"h":13}, + "frame": {"x":582,"y":88,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -346,7 +882,7 @@ }, "sprites/buildings/belt_right.png": { - "frame": {"x":313,"y":112,"w":13,"h":13}, + "frame": {"x":587,"y":105,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -354,7 +890,7 @@ }, "sprites/buildings/belt_top.png": { - "frame": {"x":204,"y":26,"w":13,"h":13}, + "frame": {"x":205,"y":110,"w":13,"h":13}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, @@ -370,12 +906,20 @@ }, "sprites/buildings/cutter.png": { - "frame": {"x":287,"y":3,"w":36,"h":19}, + "frame": {"x":288,"y":83,"w":36,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, "sourceSize": {"w":38,"h":19} }, +"sprites/buildings/energy_generator.png": +{ + "frame": {"x":166,"y":45,"w":36,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":36,"h":38}, + "sourceSize": {"w":38,"h":38} +}, "sprites/buildings/hub.png": { "frame": {"x":3,"y":3,"w":75,"h":76}, @@ -386,7 +930,7 @@ }, "sprites/buildings/miner-chainable.png": { - "frame": {"x":350,"y":3,"w":19,"h":19}, + "frame": {"x":374,"y":83,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -394,7 +938,7 @@ }, "sprites/buildings/miner.png": { - "frame": {"x":308,"y":89,"w":19,"h":19}, + "frame": {"x":394,"y":106,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -402,7 +946,7 @@ }, "sprites/buildings/mixer.png": { - "frame": {"x":208,"y":43,"w":37,"h":19}, + "frame": {"x":248,"y":43,"w":37,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, @@ -418,7 +962,7 @@ }, "sprites/buildings/painter-mirrored.png": { - "frame": {"x":166,"y":45,"w":38,"h":19}, + "frame": {"x":205,"y":87,"w":38,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, @@ -434,7 +978,7 @@ }, "sprites/buildings/painter.png": { - "frame": {"x":204,"y":3,"w":38,"h":19}, + "frame": {"x":206,"y":45,"w":38,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, @@ -442,7 +986,7 @@ }, "sprites/buildings/rotater-ccw.png": { - "frame": {"x":331,"y":66,"w":19,"h":19}, + "frame": {"x":370,"y":43,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -450,7 +994,7 @@ }, "sprites/buildings/rotater.png": { - "frame": {"x":331,"y":89,"w":19,"h":19}, + "frame": {"x":387,"y":3,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -458,7 +1002,7 @@ }, "sprites/buildings/splitter-compact-inverse.png": { - "frame": {"x":354,"y":66,"w":19,"h":19}, + "frame": {"x":393,"y":43,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -466,7 +1010,7 @@ }, "sprites/buildings/splitter-compact.png": { - "frame": {"x":358,"y":26,"w":19,"h":19}, + "frame": {"x":410,"y":3,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -474,7 +1018,7 @@ }, "sprites/buildings/splitter.png": { - "frame": {"x":245,"y":89,"w":36,"h":19}, + "frame": {"x":330,"y":43,"w":36,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, @@ -482,7 +1026,7 @@ }, "sprites/buildings/stacker.png": { - "frame": {"x":246,"y":3,"w":37,"h":19}, + "frame": {"x":289,"y":43,"w":37,"h":19}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, @@ -490,7 +1034,7 @@ }, "sprites/buildings/trash-storage.png": { - "frame": {"x":165,"y":72,"w":35,"h":38}, + "frame": {"x":166,"y":87,"w":35,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":35,"h":38}, @@ -498,7 +1042,7 @@ }, "sprites/buildings/trash.png": { - "frame": {"x":373,"y":3,"w":19,"h":19}, + "frame": {"x":397,"y":83,"w":19,"h":19}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, @@ -506,7 +1050,7 @@ }, "sprites/buildings/underground_belt_entry-tier2.png": { - "frame": {"x":396,"y":3,"w":19,"h":18}, + "frame": {"x":420,"y":83,"w":19,"h":18}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, @@ -514,7 +1058,7 @@ }, "sprites/buildings/underground_belt_entry.png": { - "frame": {"x":377,"y":86,"w":19,"h":16}, + "frame": {"x":416,"y":43,"w":19,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, @@ -522,7 +1066,7 @@ }, "sprites/buildings/underground_belt_exit-tier2.png": { - "frame": {"x":387,"y":106,"w":19,"h":16}, + "frame": {"x":427,"y":63,"w":19,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, @@ -530,7 +1074,7 @@ }, "sprites/buildings/underground_belt_exit.png": { - "frame": {"x":400,"y":65,"w":19,"h":16}, + "frame": {"x":439,"y":43,"w":19,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, @@ -578,7 +1122,7 @@ }, "sprites/misc/deletion_marker.png": { - "frame": {"x":187,"y":114,"w":10,"h":10}, + "frame": {"x":598,"y":37,"w":10,"h":10}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, @@ -602,7 +1146,7 @@ }, "sprites/misc/slot_bad_arrow.png": { - "frame": {"x":187,"y":114,"w":10,"h":10}, + "frame": {"x":598,"y":37,"w":10,"h":10}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, @@ -610,7 +1154,7 @@ }, "sprites/misc/slot_good_arrow.png": { - "frame": {"x":201,"y":114,"w":10,"h":10}, + "frame": {"x":599,"y":88,"w":10,"h":10}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, @@ -618,7 +1162,7 @@ }, "sprites/misc/storage_overlay.png": { - "frame": {"x":165,"y":114,"w":18,"h":9}, + "frame": {"x":463,"y":114,"w":18,"h":9}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":18,"h":9}, @@ -637,8 +1181,8 @@ "version": "1.0", "image": "atlas0_10.png", "format": "RGBA8888", - "size": {"w":422,"h":128}, + "size": {"w":612,"h":128}, "scale": "0.1", - "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$" + "smartupdate": "$TexturePacker:SmartUpdate:dc34796c028235bbc69e5b8d854254ca:2765d0b8c8bcbb7a4aaaf1104853ad41:8778749683c68f53155587e6d831729a$" } } diff --git a/res_built/atlas/atlas0_10.png b/res_built/atlas/atlas0_10.png index adab820d..d774ecac 100644 Binary files a/res_built/atlas/atlas0_10.png and b/res_built/atlas/atlas0_10.png differ diff --git a/res_built/atlas/atlas0_100.json b/res_built/atlas/atlas0_100.json index ba671365..05465e84 100644 --- a/res_built/atlas/atlas0_100.json +++ b/res_built/atlas/atlas0_100.json @@ -2,7 +2,7 @@ "sprites/belt/forward_0.png": { - "frame": {"x":1876,"y":1166,"w":100,"h":126}, + "frame": {"x":1202,"y":1870,"w":100,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, @@ -10,7 +10,7 @@ }, "sprites/belt/forward_1.png": { - "frame": {"x":1876,"y":1296,"w":100,"h":126}, + "frame": {"x":1871,"y":250,"w":100,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, @@ -18,31 +18,103 @@ }, "sprites/belt/forward_2.png": { - "frame": {"x":1869,"y":1543,"w":100,"h":126}, + "frame": {"x":1631,"y":1865,"w":100,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/forward_3.png": +"sprites/belt/forward_10.png": { - "frame": {"x":1857,"y":395,"w":100,"h":126}, + "frame": {"x":1450,"y":1487,"w":100,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/forward_4.png": +"sprites/belt/forward_11.png": { - "frame": {"x":1865,"y":1690,"w":100,"h":126}, + "frame": {"x":1423,"y":1849,"w":100,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/forward_5.png": +"sprites/belt/forward_12.png": { - "frame": {"x":920,"y":1370,"w":100,"h":126}, + "frame": {"x":1455,"y":1617,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_13.png": +{ + "frame": {"x":1793,"y":1624,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_14.png": +{ + "frame": {"x":1897,"y":1624,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_15.png": +{ + "frame": {"x":1559,"y":1735,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_16.png": +{ + "frame": {"x":1663,"y":1735,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_17.png": +{ + "frame": {"x":1767,"y":1754,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_18.png": +{ + "frame": {"x":1871,"y":1754,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_19.png": +{ + "frame": {"x":1527,"y":1865,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_20.png": +{ + "frame": {"x":1735,"y":1884,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_21.png": +{ + "frame": {"x":1839,"y":1884,"w":100,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, @@ -50,7 +122,7 @@ }, "sprites/belt/left_0.png": { - "frame": {"x":1870,"y":1426,"w":113,"h":113}, + "frame": {"x":239,"y":1898,"w":113,"h":113}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, @@ -58,95 +130,71 @@ }, "sprites/belt/left_1.png": { - "frame": {"x":920,"y":1500,"w":113,"h":113}, + "frame": {"x":1085,"y":1870,"w":113,"h":113}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/left_2.png": +"sprites/belt/left_10.png": { - "frame": {"x":935,"y":1617,"w":113,"h":113}, + "frame": {"x":1306,"y":1849,"w":113,"h":113}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/left_3.png": +"sprites/belt/left_11.png": { - "frame": {"x":935,"y":1734,"w":113,"h":113}, + "frame": {"x":1873,"y":133,"w":113,"h":113}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/left_4.png": +"sprites/belt/left_12.png": { - "frame": {"x":1052,"y":1721,"w":113,"h":113}, + "frame": {"x":1582,"y":1501,"w":113,"h":113}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/left_5.png": +"sprites/belt/left_13.png": { - "frame": {"x":1169,"y":1721,"w":113,"h":113}, + "frame": {"x":1699,"y":1501,"w":113,"h":113}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/right_0.png": +"sprites/belt/left_14.png": { - "frame": {"x":1286,"y":1721,"w":113,"h":113}, + "frame": {"x":1816,"y":1507,"w":113,"h":113}, "rotated": false, "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/right_1.png": +"sprites/belt/left_15.png": { - "frame": {"x":1403,"y":1721,"w":113,"h":113}, + "frame": {"x":1559,"y":1618,"w":113,"h":113}, "rotated": false, "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, -"sprites/belt/right_2.png": +"sprites/belt/left_16.png": { - "frame": {"x":1520,"y":1721,"w":113,"h":113}, + "frame": {"x":1676,"y":1618,"w":113,"h":113}, "rotated": false, "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":1052,"y":1552,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":1169,"y":1552,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":1286,"y":1554,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "sourceSize": {"w":126,"h":126} }, "sprites/blueprints/belt_left.png": { - "frame": {"x":1873,"y":122,"w":114,"h":114}, + "frame": {"x":3,"y":1898,"w":114,"h":114}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":12,"w":114,"h":114}, @@ -154,15 +202,15 @@ }, "sprites/blueprints/belt_right.png": { - "frame": {"x":1873,"y":3,"w":114,"h":115}, + "frame": {"x":121,"y":1898,"w":114,"h":114}, "rotated": false, "trimmed": true, - "spriteSourceSize": {"x":12,"y":11,"w":114,"h":115}, + "spriteSourceSize": {"x":12,"y":12,"w":114,"h":114}, "sourceSize": {"w":126,"h":126} }, "sprites/blueprints/belt_top.png": { - "frame": {"x":1871,"y":240,"w":102,"h":126}, + "frame": {"x":1873,"y":3,"w":102,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":12,"y":0,"w":102,"h":126}, @@ -178,15 +226,23 @@ }, "sprites/blueprints/cutter.png": { - "frame": {"x":1433,"y":785,"w":341,"h":191}, + "frame": {"x":391,"y":1707,"w":341,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":23,"y":0,"w":341,"h":191}, "sourceSize": {"w":384,"h":192} }, +"sprites/blueprints/energy_generator.png": +{ + "frame": {"x":735,"y":590,"w":339,"h":373}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":25,"y":11,"w":339,"h":373}, + "sourceSize": {"w":384,"h":384} +}, "sprites/blueprints/miner-chainable.png": { - "frame": {"x":749,"y":1655,"w":182,"h":190}, + "frame": {"x":1842,"y":783,"w":182,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, @@ -194,7 +250,7 @@ }, "sprites/blueprints/miner.png": { - "frame": {"x":1690,"y":1174,"w":182,"h":190}, + "frame": {"x":1843,"y":977,"w":182,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, @@ -202,7 +258,7 @@ }, "sprites/blueprints/mixer.png": { - "frame": {"x":1123,"y":590,"w":347,"h":191}, + "frame": {"x":726,"y":1162,"w":347,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, @@ -218,7 +274,7 @@ }, "sprites/blueprints/painter-mirrored.png": { - "frame": {"x":1485,"y":3,"w":384,"h":192}, + "frame": {"x":3,"y":1702,"w":384,"h":192}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":192}, @@ -234,7 +290,7 @@ }, "sprites/blueprints/painter.png": { - "frame": {"x":1483,"y":199,"w":384,"h":192}, + "frame": {"x":1485,"y":3,"w":384,"h":192}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":192}, @@ -242,7 +298,7 @@ }, "sprites/blueprints/rotater-ccw.png": { - "frame": {"x":922,"y":1174,"w":189,"h":191}, + "frame": {"x":1458,"y":956,"w":189,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, @@ -250,7 +306,7 @@ }, "sprites/blueprints/rotater.png": { - "frame": {"x":1115,"y":1173,"w":189,"h":191}, + "frame": {"x":1811,"y":588,"w":189,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, @@ -258,7 +314,7 @@ }, "sprites/blueprints/splitter-compact-inverse.png": { - "frame": {"x":1756,"y":980,"w":188,"h":182}, + "frame": {"x":1651,"y":977,"w":188,"h":182}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":4,"w":188,"h":182}, @@ -266,7 +322,7 @@ }, "sprites/blueprints/splitter-compact.png": { - "frame": {"x":1306,"y":1368,"w":185,"h":182}, + "frame": {"x":1649,"y":1163,"w":185,"h":182}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":4,"w":185,"h":182}, @@ -274,7 +330,7 @@ }, "sprites/blueprints/splitter.png": { - "frame": {"x":726,"y":979,"w":340,"h":191}, + "frame": {"x":1114,"y":966,"w":340,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":23,"y":0,"w":340,"h":191}, @@ -282,7 +338,7 @@ }, "sprites/blueprints/stacker.png": { - "frame": {"x":1474,"y":590,"w":347,"h":191}, + "frame": {"x":724,"y":1357,"w":347,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, @@ -298,7 +354,7 @@ }, "sprites/blueprints/trash.png": { - "frame": {"x":726,"y":1174,"w":192,"h":192}, + "frame": {"x":1419,"y":590,"w":192,"h":192}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, @@ -306,7 +362,7 @@ }, "sprites/blueprints/underground_belt_entry-tier2.png": { - "frame": {"x":1683,"y":1368,"w":183,"h":166}, + "frame": {"x":1419,"y":786,"w":183,"h":166}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":26,"w":183,"h":166}, @@ -314,7 +370,7 @@ }, "sprites/blueprints/underground_belt_entry.png": { - "frame": {"x":192,"y":1702,"w":182,"h":148}, + "frame": {"x":1646,"y":1349,"w":182,"h":148}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":44,"w":182,"h":148}, @@ -322,7 +378,7 @@ }, "sprites/blueprints/underground_belt_exit-tier2.png": { - "frame": {"x":3,"y":1702,"w":185,"h":148}, + "frame": {"x":1457,"y":1335,"w":185,"h":148}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":185,"h":148}, @@ -330,31 +386,15 @@ }, "sprites/blueprints/underground_belt_exit.png": { - "frame": {"x":1683,"y":1538,"w":182,"h":148}, + "frame": {"x":1832,"y":1355,"w":182,"h":148}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":182,"h":148}, "sourceSize": {"w":192,"h":192} }, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":1870,"y":1426,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":1286,"y":1721,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, "sprites/buildings/belt_top.png": { - "frame": {"x":1876,"y":1166,"w":100,"h":126}, + "frame": {"x":1202,"y":1870,"w":100,"h":126}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, @@ -370,12 +410,20 @@ }, "sprites/buildings/cutter.png": { - "frame": {"x":1070,"y":979,"w":339,"h":190}, + "frame": {"x":736,"y":1552,"w":339,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, "sourceSize": {"w":384,"h":192} }, +"sprites/buildings/energy_generator.png": +{ + "frame": {"x":1078,"y":590,"w":337,"h":372}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":26,"y":12,"w":337,"h":372}, + "sourceSize": {"w":384,"h":384} +}, "sprites/buildings/hub.png": { "frame": {"x":3,"y":3,"w":728,"h":730}, @@ -386,7 +434,7 @@ }, "sprites/buildings/miner-chainable.png": { - "frame": {"x":1825,"y":590,"w":179,"h":188}, + "frame": {"x":1258,"y":1355,"w":179,"h":188}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":1,"w":179,"h":188}, @@ -394,7 +442,7 @@ }, "sprites/buildings/miner.png": { - "frame": {"x":1778,"y":785,"w":179,"h":189}, + "frame": {"x":1075,"y":1357,"w":179,"h":189}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":0,"w":179,"h":189}, @@ -402,7 +450,7 @@ }, "sprites/buildings/mixer.png": { - "frame": {"x":735,"y":785,"w":345,"h":190}, + "frame": {"x":736,"y":1746,"w":345,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":19,"y":0,"w":345,"h":190}, @@ -418,7 +466,7 @@ }, "sprites/buildings/painter-mirrored.png": { - "frame": {"x":735,"y":590,"w":384,"h":191}, + "frame": {"x":1483,"y":199,"w":384,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":191}, @@ -434,7 +482,7 @@ }, "sprites/buildings/painter.png": { - "frame": {"x":1469,"y":395,"w":384,"h":191}, + "frame": {"x":726,"y":967,"w":384,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":191}, @@ -442,7 +490,7 @@ }, "sprites/buildings/rotater-ccw.png": { - "frame": {"x":1308,"y":1174,"w":187,"h":190}, + "frame": {"x":1832,"y":394,"w":187,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, @@ -450,7 +498,7 @@ }, "sprites/buildings/rotater.png": { - "frame": {"x":1499,"y":1174,"w":187,"h":190}, + "frame": {"x":1651,"y":783,"w":187,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, @@ -458,7 +506,7 @@ }, "sprites/buildings/splitter-compact-inverse.png": { - "frame": {"x":1115,"y":1368,"w":187,"h":180}, + "frame": {"x":1458,"y":1151,"w":187,"h":180}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":5,"w":187,"h":180}, @@ -466,7 +514,7 @@ }, "sprites/buildings/splitter-compact.png": { - "frame": {"x":1495,"y":1368,"w":184,"h":180}, + "frame": {"x":1838,"y":1171,"w":184,"h":180}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":5,"w":184,"h":180}, @@ -474,7 +522,7 @@ }, "sprites/buildings/splitter.png": { - "frame": {"x":1413,"y":980,"w":339,"h":190}, + "frame": {"x":1114,"y":1161,"w":339,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, @@ -482,7 +530,7 @@ }, "sprites/buildings/stacker.png": { - "frame": {"x":1084,"y":785,"w":345,"h":190}, + "frame": {"x":1483,"y":394,"w":345,"h":190}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":19,"y":0,"w":345,"h":190}, @@ -498,7 +546,7 @@ }, "sprites/buildings/trash.png": { - "frame": {"x":724,"y":1370,"w":192,"h":191}, + "frame": {"x":1615,"y":588,"w":192,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":192,"h":191}, @@ -506,7 +554,7 @@ }, "sprites/buildings/underground_belt_entry-tier2.png": { - "frame": {"x":1495,"y":1552,"w":181,"h":165}, + "frame": {"x":1079,"y":1550,"w":181,"h":165}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":27,"w":181,"h":165}, @@ -514,7 +562,7 @@ }, "sprites/buildings/underground_belt_entry.png": { - "frame": {"x":564,"y":1707,"w":181,"h":147}, + "frame": {"x":1085,"y":1719,"w":181,"h":147}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":45,"w":181,"h":147}, @@ -522,7 +570,7 @@ }, "sprites/buildings/underground_belt_exit-tier2.png": { - "frame": {"x":378,"y":1707,"w":182,"h":147}, + "frame": {"x":1264,"y":1547,"w":182,"h":147}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":0,"w":182,"h":147}, @@ -530,7 +578,7 @@ }, "sprites/buildings/underground_belt_exit.png": { - "frame": {"x":1680,"y":1690,"w":181,"h":147}, + "frame": {"x":1270,"y":1698,"w":181,"h":147}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":0,"w":181,"h":147}, @@ -538,7 +586,7 @@ }, "sprites/debug/acceptor_slot.png": { - "frame": {"x":1961,"y":782,"w":50,"h":64}, + "frame": {"x":1975,"y":250,"w":50,"h":64}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, @@ -546,7 +594,7 @@ }, "sprites/debug/ejector_slot.png": { - "frame": {"x":1961,"y":850,"w":50,"h":64}, + "frame": {"x":1975,"y":318,"w":50,"h":64}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, @@ -554,7 +602,7 @@ }, "sprites/map_overview/belt_forward.png": { - "frame": {"x":1637,"y":1721,"w":24,"h":32}, + "frame": {"x":706,"y":1902,"w":24,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, @@ -562,7 +610,7 @@ }, "sprites/map_overview/belt_left.png": { - "frame": {"x":1893,"y":525,"w":28,"h":28}, + "frame": {"x":1077,"y":1162,"w":28,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":4,"w":28,"h":28}, @@ -570,7 +618,7 @@ }, "sprites/map_overview/belt_right.png": { - "frame": {"x":1080,"y":1669,"w":28,"h":28}, + "frame": {"x":1979,"y":3,"w":28,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":4,"w":28,"h":28}, @@ -578,7 +626,7 @@ }, "sprites/misc/deletion_marker.png": { - "frame": {"x":1403,"y":1554,"w":82,"h":82}, + "frame": {"x":620,"y":1902,"w":82,"h":82}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, @@ -586,7 +634,7 @@ }, "sprites/misc/hub_direction_indicator.png": { - "frame": {"x":1857,"y":525,"w":32,"h":32}, + "frame": {"x":1615,"y":783,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -594,7 +642,7 @@ }, "sprites/misc/lock_direction_indicator.png": { - "frame": {"x":1961,"y":918,"w":48,"h":30}, + "frame": {"x":1306,"y":1966,"w":48,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":48,"h":30}, @@ -602,7 +650,7 @@ }, "sprites/misc/slot_bad_arrow.png": { - "frame": {"x":1403,"y":1554,"w":82,"h":82}, + "frame": {"x":620,"y":1902,"w":82,"h":82}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, @@ -610,7 +658,7 @@ }, "sprites/misc/slot_good_arrow.png": { - "frame": {"x":1024,"y":1369,"w":80,"h":96}, + "frame": {"x":536,"y":1902,"w":80,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":0,"w":80,"h":96}, @@ -618,7 +666,7 @@ }, "sprites/misc/storage_overlay.png": { - "frame": {"x":724,"y":1565,"w":176,"h":86}, + "frame": {"x":356,"y":1902,"w":176,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":4,"w":176,"h":86}, @@ -626,7 +674,7 @@ }, "sprites/misc/waypoint.png": { - "frame": {"x":1052,"y":1669,"w":24,"h":32}, + "frame": {"x":1554,"y":1487,"w":24,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, @@ -637,8 +685,9 @@ "version": "1.0", "image": "atlas0_100.png", "format": "RGBA8888", - "size": {"w":2014,"h":1857}, + "size": {"w":2028,"h":2015}, "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$" + "related_multi_packs": [ "atlas1_100.json" ], + "smartupdate": "$TexturePacker:SmartUpdate:dc34796c028235bbc69e5b8d854254ca:2765d0b8c8bcbb7a4aaaf1104853ad41:8778749683c68f53155587e6d831729a$" } } diff --git a/res_built/atlas/atlas0_100.png b/res_built/atlas/atlas0_100.png index 181adc30..2fb0cffb 100644 Binary files a/res_built/atlas/atlas0_100.png and b/res_built/atlas/atlas0_100.png differ diff --git a/res_built/atlas/atlas0_25.json b/res_built/atlas/atlas0_25.json index a4aac8ed..2065027f 100644 --- a/res_built/atlas/atlas0_25.json +++ b/res_built/atlas/atlas0_25.json @@ -2,7 +2,7 @@ "sprites/belt/forward_0.png": { - "frame": {"x":3,"y":1010,"w":28,"h":32}, + "frame": {"x":191,"y":155,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -10,7 +10,7 @@ }, "sprites/belt/forward_1.png": { - "frame": {"x":3,"y":967,"w":28,"h":32}, + "frame": {"x":223,"y":155,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -18,7 +18,7 @@ }, "sprites/belt/forward_2.png": { - "frame": {"x":3,"y":1046,"w":28,"h":32}, + "frame": {"x":865,"y":55,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -26,7 +26,7 @@ }, "sprites/belt/forward_3.png": { - "frame": {"x":35,"y":1044,"w":28,"h":32}, + "frame": {"x":1121,"y":55,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -34,7 +34,7 @@ }, "sprites/belt/forward_4.png": { - "frame": {"x":67,"y":1044,"w":28,"h":32}, + "frame": {"x":1149,"y":3,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -42,7 +42,183 @@ }, "sprites/belt/forward_5.png": { - "frame": {"x":133,"y":1053,"w":28,"h":32}, + "frame": {"x":1087,"y":194,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_6.png": +{ + "frame": {"x":1108,"y":139,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_7.png": +{ + "frame": {"x":1122,"y":91,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_8.png": +{ + "frame": {"x":1153,"y":51,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_9.png": +{ + "frame": {"x":1181,"y":3,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_10.png": +{ + "frame": {"x":255,"y":155,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_11.png": +{ + "frame": {"x":287,"y":155,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_12.png": +{ + "frame": {"x":319,"y":155,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_13.png": +{ + "frame": {"x":351,"y":155,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_14.png": +{ + "frame": {"x":673,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_15.png": +{ + "frame": {"x":705,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_16.png": +{ + "frame": {"x":737,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_17.png": +{ + "frame": {"x":769,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_18.png": +{ + "frame": {"x":801,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_19.png": +{ + "frame": {"x":833,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_20.png": +{ + "frame": {"x":897,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_21.png": +{ + "frame": {"x":929,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_22.png": +{ + "frame": {"x":961,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_23.png": +{ + "frame": {"x":993,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_24.png": +{ + "frame": {"x":1025,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_25.png": +{ + "frame": {"x":1057,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_26.png": +{ + "frame": {"x":1089,"y":55,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/forward_27.png": +{ + "frame": {"x":1090,"y":91,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -50,7 +226,7 @@ }, "sprites/belt/left_0.png": { - "frame": {"x":143,"y":883,"w":30,"h":30}, + "frame": {"x":1140,"y":139,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -58,7 +234,7 @@ }, "sprites/belt/left_1.png": { - "frame": {"x":143,"y":917,"w":30,"h":30}, + "frame": {"x":1123,"y":211,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -66,7 +242,7 @@ }, "sprites/belt/left_2.png": { - "frame": {"x":143,"y":951,"w":30,"h":30}, + "frame": {"x":1208,"y":107,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -74,7 +250,7 @@ }, "sprites/belt/left_3.png": { - "frame": {"x":35,"y":960,"w":30,"h":30}, + "frame": {"x":1315,"y":3,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -82,7 +258,7 @@ }, "sprites/belt/left_4.png": { - "frame": {"x":69,"y":967,"w":30,"h":30}, + "frame": {"x":1225,"y":175,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -90,7 +266,183 @@ }, "sprites/belt/left_5.png": { - "frame": {"x":35,"y":994,"w":30,"h":30}, + "frame": {"x":1253,"y":139,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_6.png": +{ + "frame": {"x":1276,"y":105,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_7.png": +{ + "frame": {"x":1290,"y":71,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_8.png": +{ + "frame": {"x":1321,"y":37,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_9.png": +{ + "frame": {"x":1349,"y":3,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_10.png": +{ + "frame": {"x":1151,"y":173,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_11.png": +{ + "frame": {"x":1157,"y":207,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_12.png": +{ + "frame": {"x":1154,"y":87,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_13.png": +{ + "frame": {"x":1185,"y":39,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_14.png": +{ + "frame": {"x":1213,"y":3,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_15.png": +{ + "frame": {"x":1174,"y":121,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_16.png": +{ + "frame": {"x":1188,"y":73,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_17.png": +{ + "frame": {"x":1219,"y":37,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_18.png": +{ + "frame": {"x":1247,"y":3,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_19.png": +{ + "frame": {"x":1185,"y":155,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_20.png": +{ + "frame": {"x":1222,"y":71,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_21.png": +{ + "frame": {"x":1253,"y":37,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_22.png": +{ + "frame": {"x":1281,"y":3,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_23.png": +{ + "frame": {"x":1191,"y":189,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_24.png": +{ + "frame": {"x":1219,"y":141,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_25.png": +{ + "frame": {"x":1242,"y":105,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_26.png": +{ + "frame": {"x":1256,"y":71,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/left_27.png": +{ + "frame": {"x":1287,"y":37,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -98,7 +450,7 @@ }, "sprites/belt/right_0.png": { - "frame": {"x":103,"y":967,"w":30,"h":30}, + "frame": {"x":1259,"y":173,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -106,7 +458,7 @@ }, "sprites/belt/right_1.png": { - "frame": {"x":137,"y":985,"w":30,"h":30}, + "frame": {"x":1287,"y":139,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -114,7 +466,7 @@ }, "sprites/belt/right_2.png": { - "frame": {"x":171,"y":997,"w":30,"h":30}, + "frame": {"x":1417,"y":3,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -122,7 +474,7 @@ }, "sprites/belt/right_3.png": { - "frame": {"x":205,"y":1010,"w":30,"h":30}, + "frame": {"x":1361,"y":173,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -130,7 +482,7 @@ }, "sprites/belt/right_4.png": { - "frame": {"x":99,"y":1001,"w":30,"h":30}, + "frame": {"x":1389,"y":139,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -138,7 +490,183 @@ }, "sprites/belt/right_5.png": { - "frame": {"x":133,"y":1019,"w":30,"h":30}, + "frame": {"x":1412,"y":105,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_6.png": +{ + "frame": {"x":1426,"y":71,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_7.png": +{ + "frame": {"x":1446,"y":105,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_8.png": +{ + "frame": {"x":1368,"y":207,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_9.png": +{ + "frame": {"x":1395,"y":173,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_10.png": +{ + "frame": {"x":1310,"y":105,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_11.png": +{ + "frame": {"x":1324,"y":71,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_12.png": +{ + "frame": {"x":1355,"y":37,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_13.png": +{ + "frame": {"x":1383,"y":3,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_14.png": +{ + "frame": {"x":1266,"y":207,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_15.png": +{ + "frame": {"x":1293,"y":173,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_16.png": +{ + "frame": {"x":1321,"y":139,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_17.png": +{ + "frame": {"x":1344,"y":105,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_18.png": +{ + "frame": {"x":1358,"y":71,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_19.png": +{ + "frame": {"x":1389,"y":37,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_20.png": +{ + "frame": {"x":1451,"y":3,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_21.png": +{ + "frame": {"x":1300,"y":207,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_22.png": +{ + "frame": {"x":1327,"y":173,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_23.png": +{ + "frame": {"x":1355,"y":139,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_24.png": +{ + "frame": {"x":1378,"y":105,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_25.png": +{ + "frame": {"x":1392,"y":71,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_26.png": +{ + "frame": {"x":1423,"y":37,"w":30,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/belt/right_27.png": +{ + "frame": {"x":1334,"y":207,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -146,7 +674,7 @@ }, "sprites/blueprints/belt_left.png": { - "frame": {"x":99,"y":1035,"w":30,"h":30}, + "frame": {"x":1423,"y":139,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -154,7 +682,7 @@ }, "sprites/blueprints/belt_right.png": { - "frame": {"x":167,"y":1031,"w":30,"h":30}, + "frame": {"x":1402,"y":207,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -162,7 +690,7 @@ }, "sprites/blueprints/belt_top.png": { - "frame": {"x":201,"y":1044,"w":28,"h":32}, + "frame": {"x":1119,"y":175,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -170,7 +698,7 @@ }, "sprites/blueprints/cutter-quad.png": { - "frame": {"x":3,"y":296,"w":184,"h":48}, + "frame": {"x":195,"y":191,"w":184,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, @@ -178,15 +706,23 @@ }, "sprites/blueprints/cutter.png": { - "frame": {"x":155,"y":419,"w":87,"h":48}, + "frame": {"x":844,"y":91,"w":87,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, "sourceSize": {"w":96,"h":48} }, +"sprites/blueprints/energy_generator.png": +{ + "frame": {"x":472,"y":103,"w":87,"h":94}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":2,"w":87,"h":94}, + "sourceSize": {"w":96,"h":96} +}, "sprites/blueprints/miner-chainable.png": { - "frame": {"x":195,"y":3,"w":47,"h":48}, + "frame": {"x":1006,"y":143,"w":47,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, @@ -194,7 +730,7 @@ }, "sprites/blueprints/miner.png": { - "frame": {"x":195,"y":55,"w":47,"h":48}, + "frame": {"x":1039,"y":91,"w":47,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, @@ -202,7 +738,7 @@ }, "sprites/blueprints/mixer.png": { - "frame": {"x":3,"y":808,"w":89,"h":48}, + "frame": {"x":751,"y":91,"w":89,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, @@ -210,7 +746,7 @@ }, "sprites/blueprints/painter-double.png": { - "frame": {"x":3,"y":400,"w":96,"h":96}, + "frame": {"x":191,"y":3,"w":96,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, @@ -218,7 +754,7 @@ }, "sprites/blueprints/painter-mirrored.png": { - "frame": {"x":3,"y":600,"w":96,"h":48}, + "frame": {"x":589,"y":195,"w":96,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, @@ -226,7 +762,7 @@ }, "sprites/blueprints/painter-quad.png": { - "frame": {"x":3,"y":3,"w":188,"h":48}, + "frame": {"x":3,"y":192,"w":188,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, @@ -234,7 +770,7 @@ }, "sprites/blueprints/painter.png": { - "frame": {"x":3,"y":652,"w":96,"h":48}, + "frame": {"x":689,"y":195,"w":96,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, @@ -242,7 +778,7 @@ }, "sprites/blueprints/rotater-ccw.png": { - "frame": {"x":191,"y":107,"w":48,"h":48}, + "frame": {"x":935,"y":91,"w":48,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, @@ -250,7 +786,7 @@ }, "sprites/blueprints/rotater.png": { - "frame": {"x":191,"y":159,"w":48,"h":48}, + "frame": {"x":880,"y":195,"w":48,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, @@ -258,7 +794,7 @@ }, "sprites/blueprints/splitter-compact-inverse.png": { - "frame": {"x":191,"y":211,"w":48,"h":48}, + "frame": {"x":932,"y":195,"w":48,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, @@ -266,7 +802,7 @@ }, "sprites/blueprints/splitter-compact.png": { - "frame": {"x":103,"y":780,"w":47,"h":47}, + "frame": {"x":538,"y":201,"w":47,"h":47}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, @@ -274,7 +810,7 @@ }, "sprites/blueprints/splitter.png": { - "frame": {"x":155,"y":471,"w":87,"h":48}, + "frame": {"x":955,"y":3,"w":87,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, @@ -282,7 +818,7 @@ }, "sprites/blueprints/stacker.png": { - "frame": {"x":96,"y":831,"w":89,"h":48}, + "frame": {"x":770,"y":143,"w":89,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, @@ -290,7 +826,7 @@ }, "sprites/blueprints/trash-storage.png": { - "frame": {"x":155,"y":627,"w":85,"h":96}, + "frame": {"x":383,"y":103,"w":85,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, @@ -298,7 +834,7 @@ }, "sprites/blueprints/trash.png": { - "frame": {"x":191,"y":263,"w":48,"h":48}, + "frame": {"x":954,"y":143,"w":48,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, @@ -306,7 +842,7 @@ }, "sprites/blueprints/underground_belt_entry-tier2.png": { - "frame": {"x":103,"y":503,"w":48,"h":43}, + "frame": {"x":383,"y":203,"w":48,"h":43}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, @@ -314,7 +850,7 @@ }, "sprites/blueprints/underground_belt_entry.png": { - "frame": {"x":103,"y":550,"w":48,"h":38}, + "frame": {"x":563,"y":153,"w":48,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, @@ -322,7 +858,7 @@ }, "sprites/blueprints/underground_belt_exit-tier2.png": { - "frame": {"x":103,"y":592,"w":48,"h":38}, + "frame": {"x":615,"y":153,"w":48,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, @@ -330,7 +866,7 @@ }, "sprites/blueprints/underground_belt_exit.png": { - "frame": {"x":103,"y":634,"w":48,"h":38}, + "frame": {"x":667,"y":153,"w":48,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, @@ -338,7 +874,7 @@ }, "sprites/buildings/belt_left.png": { - "frame": {"x":143,"y":883,"w":30,"h":30}, + "frame": {"x":1429,"y":173,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, @@ -346,7 +882,7 @@ }, "sprites/buildings/belt_right.png": { - "frame": {"x":103,"y":967,"w":30,"h":30}, + "frame": {"x":1436,"y":207,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, @@ -354,7 +890,7 @@ }, "sprites/buildings/belt_top.png": { - "frame": {"x":3,"y":1010,"w":28,"h":32}, + "frame": {"x":191,"y":155,"w":28,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, @@ -362,7 +898,7 @@ }, "sprites/buildings/cutter-quad.png": { - "frame": {"x":3,"y":348,"w":184,"h":48}, + "frame": {"x":563,"y":101,"w":184,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, @@ -370,15 +906,23 @@ }, "sprites/buildings/cutter.png": { - "frame": {"x":155,"y":523,"w":87,"h":48}, + "frame": {"x":789,"y":195,"w":87,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, "sourceSize": {"w":96,"h":48} }, +"sprites/buildings/energy_generator.png": +{ + "frame": {"x":480,"y":3,"w":87,"h":94}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":2,"w":87,"h":94}, + "sourceSize": {"w":96,"h":96} +}, "sprites/buildings/hub.png": { - "frame": {"x":3,"y":107,"w":184,"h":185}, + "frame": {"x":3,"y":3,"w":184,"h":185}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, @@ -386,7 +930,7 @@ }, "sprites/buildings/miner-chainable.png": { - "frame": {"x":103,"y":676,"w":47,"h":48}, + "frame": {"x":1098,"y":3,"w":47,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, @@ -394,7 +938,7 @@ }, "sprites/buildings/miner.png": { - "frame": {"x":103,"y":728,"w":47,"h":48}, + "frame": {"x":1036,"y":195,"w":47,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, @@ -402,7 +946,7 @@ }, "sprites/buildings/mixer.png": { - "frame": {"x":154,"y":727,"w":88,"h":48}, + "frame": {"x":771,"y":3,"w":88,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, @@ -410,7 +954,7 @@ }, "sprites/buildings/painter-double.png": { - "frame": {"x":3,"y":500,"w":96,"h":96}, + "frame": {"x":291,"y":3,"w":96,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, @@ -418,7 +962,7 @@ }, "sprites/buildings/painter-mirrored.png": { - "frame": {"x":3,"y":704,"w":96,"h":48}, + "frame": {"x":571,"y":3,"w":96,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, @@ -426,7 +970,7 @@ }, "sprites/buildings/painter-quad.png": { - "frame": {"x":3,"y":55,"w":188,"h":48}, + "frame": {"x":191,"y":103,"w":188,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, @@ -434,7 +978,7 @@ }, "sprites/buildings/painter.png": { - "frame": {"x":3,"y":756,"w":96,"h":48}, + "frame": {"x":671,"y":3,"w":96,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, @@ -442,7 +986,7 @@ }, "sprites/buildings/rotater-ccw.png": { - "frame": {"x":191,"y":315,"w":48,"h":48}, + "frame": {"x":987,"y":91,"w":48,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, @@ -450,7 +994,7 @@ }, "sprites/buildings/rotater.png": { - "frame": {"x":191,"y":367,"w":48,"h":48}, + "frame": {"x":1046,"y":3,"w":48,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, @@ -458,7 +1002,7 @@ }, "sprites/buildings/splitter-compact-inverse.png": { - "frame": {"x":103,"y":452,"w":48,"h":47}, + "frame": {"x":486,"y":201,"w":48,"h":47}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, @@ -466,7 +1010,7 @@ }, "sprites/buildings/splitter-compact.png": { - "frame": {"x":189,"y":831,"w":47,"h":47}, + "frame": {"x":1057,"y":143,"w":47,"h":47}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, @@ -474,7 +1018,7 @@ }, "sprites/buildings/splitter.png": { - "frame": {"x":155,"y":575,"w":87,"h":48}, + "frame": {"x":863,"y":143,"w":87,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, @@ -482,7 +1026,7 @@ }, "sprites/buildings/stacker.png": { - "frame": {"x":154,"y":779,"w":88,"h":48}, + "frame": {"x":863,"y":3,"w":88,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, @@ -490,7 +1034,7 @@ }, "sprites/buildings/trash-storage.png": { - "frame": {"x":3,"y":860,"w":85,"h":96}, + "frame": {"x":391,"y":3,"w":85,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, @@ -498,7 +1042,7 @@ }, "sprites/buildings/trash.png": { - "frame": {"x":103,"y":400,"w":48,"h":48}, + "frame": {"x":984,"y":195,"w":48,"h":48}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, @@ -506,7 +1050,7 @@ }, "sprites/buildings/underground_belt_entry-tier2.png": { - "frame": {"x":189,"y":882,"w":47,"h":42}, + "frame": {"x":435,"y":203,"w":47,"h":42}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, @@ -514,7 +1058,7 @@ }, "sprites/buildings/underground_belt_entry.png": { - "frame": {"x":92,"y":883,"w":47,"h":38}, + "frame": {"x":719,"y":153,"w":47,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, @@ -522,7 +1066,7 @@ }, "sprites/buildings/underground_belt_exit-tier2.png": { - "frame": {"x":92,"y":925,"w":47,"h":38}, + "frame": {"x":571,"y":55,"w":47,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, @@ -530,7 +1074,7 @@ }, "sprites/buildings/underground_belt_exit.png": { - "frame": {"x":189,"y":928,"w":47,"h":38}, + "frame": {"x":622,"y":55,"w":47,"h":38}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, @@ -538,7 +1082,7 @@ }, "sprites/debug/acceptor_slot.png": { - "frame": {"x":226,"y":970,"w":14,"h":16}, + "frame": {"x":1087,"y":230,"w":14,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, @@ -546,7 +1090,7 @@ }, "sprites/debug/ejector_slot.png": { - "frame": {"x":226,"y":990,"w":14,"h":16}, + "frame": {"x":1105,"y":230,"w":14,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, @@ -554,7 +1098,7 @@ }, "sprites/map_overview/belt_forward.png": { - "frame": {"x":171,"y":400,"w":8,"h":8}, + "frame": {"x":1106,"y":127,"w":8,"h":8}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, @@ -562,7 +1106,7 @@ }, "sprites/map_overview/belt_left.png": { - "frame": {"x":177,"y":883,"w":8,"h":8}, + "frame": {"x":1149,"y":39,"w":8,"h":8}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, @@ -570,7 +1114,7 @@ }, "sprites/map_overview/belt_right.png": { - "frame": {"x":177,"y":895,"w":8,"h":8}, + "frame": {"x":1118,"y":127,"w":8,"h":8}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, @@ -578,7 +1122,7 @@ }, "sprites/misc/deletion_marker.png": { - "frame": {"x":165,"y":1065,"w":22,"h":22}, + "frame": {"x":1457,"y":37,"w":22,"h":22}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, @@ -586,7 +1130,7 @@ }, "sprites/misc/hub_direction_indicator.png": { - "frame": {"x":177,"y":907,"w":8,"h":8}, + "frame": {"x":1130,"y":127,"w":8,"h":8}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, @@ -594,7 +1138,7 @@ }, "sprites/misc/lock_direction_indicator.png": { - "frame": {"x":155,"y":400,"w":12,"h":10}, + "frame": {"x":1090,"y":127,"w":12,"h":10}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":12,"h":10}, @@ -602,7 +1146,7 @@ }, "sprites/misc/slot_bad_arrow.png": { - "frame": {"x":165,"y":1065,"w":22,"h":22}, + "frame": {"x":1457,"y":37,"w":22,"h":22}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, @@ -610,7 +1154,7 @@ }, "sprites/misc/slot_good_arrow.png": { - "frame": {"x":69,"y":1001,"w":22,"h":24}, + "frame": {"x":1191,"y":223,"w":22,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":22,"h":24}, @@ -618,7 +1162,7 @@ }, "sprites/misc/storage_overlay.png": { - "frame": {"x":177,"y":970,"w":45,"h":23}, + "frame": {"x":1217,"y":223,"w":45,"h":23}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":45,"h":23}, @@ -626,7 +1170,7 @@ }, "sprites/misc/waypoint.png": { - "frame": {"x":177,"y":919,"w":8,"h":8}, + "frame": {"x":1161,"y":39,"w":8,"h":8}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, @@ -637,8 +1181,8 @@ "version": "1.0", "image": "atlas0_25.png", "format": "RGBA8888", - "size": {"w":245,"h":1090}, + "size": {"w":1484,"h":251}, "scale": "0.25", - "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$" + "smartupdate": "$TexturePacker:SmartUpdate:dc34796c028235bbc69e5b8d854254ca:2765d0b8c8bcbb7a4aaaf1104853ad41:8778749683c68f53155587e6d831729a$" } } diff --git a/res_built/atlas/atlas0_25.png b/res_built/atlas/atlas0_25.png index 4581d71d..0d49e2e8 100644 Binary files a/res_built/atlas/atlas0_25.png and b/res_built/atlas/atlas0_25.png differ diff --git a/res_built/atlas/atlas0_50.json b/res_built/atlas/atlas0_50.json index f31bbb3d..f9651cb6 100644 --- a/res_built/atlas/atlas0_50.json +++ b/res_built/atlas/atlas0_50.json @@ -2,7 +2,7 @@ "sprites/belt/forward_0.png": { - "frame": {"x":1966,"y":3,"w":51,"h":63}, + "frame": {"x":1234,"y":403,"w":51,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, @@ -10,7 +10,7 @@ }, "sprites/belt/forward_1.png": { - "frame": {"x":1835,"y":203,"w":51,"h":63}, + "frame": {"x":905,"y":503,"w":51,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, @@ -18,7 +18,7 @@ }, "sprites/belt/forward_2.png": { - "frame": {"x":1879,"y":304,"w":51,"h":63}, + "frame": {"x":588,"y":678,"w":51,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, @@ -26,7 +26,7 @@ }, "sprites/belt/forward_3.png": { - "frame": {"x":1934,"y":304,"w":51,"h":63}, + "frame": {"x":753,"y":666,"w":51,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, @@ -34,7 +34,7 @@ }, "sprites/belt/forward_4.png": { - "frame": {"x":1844,"y":381,"w":51,"h":63}, + "frame": {"x":753,"y":733,"w":51,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, @@ -42,7 +42,183 @@ }, "sprites/belt/forward_5.png": { - "frame": {"x":1899,"y":371,"w":51,"h":63}, + "frame": {"x":808,"y":676,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_6.png": +{ + "frame": {"x":808,"y":743,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_7.png": +{ + "frame": {"x":863,"y":692,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_8.png": +{ + "frame": {"x":863,"y":759,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_9.png": +{ + "frame": {"x":918,"y":698,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_10.png": +{ + "frame": {"x":960,"y":503,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_11.png": +{ + "frame": {"x":966,"y":570,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_12.png": +{ + "frame": {"x":1021,"y":564,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_13.png": +{ + "frame": {"x":1076,"y":564,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_14.png": +{ + "frame": {"x":1131,"y":564,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_15.png": +{ + "frame": {"x":1198,"y":503,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_16.png": +{ + "frame": {"x":1247,"y":570,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_17.png": +{ + "frame": {"x":472,"y":657,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_18.png": +{ + "frame": {"x":463,"y":785,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_19.png": +{ + "frame": {"x":466,"y":852,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_20.png": +{ + "frame": {"x":643,"y":677,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_21.png": +{ + "frame": {"x":588,"y":745,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_22.png": +{ + "frame": {"x":643,"y":744,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_23.png": +{ + "frame": {"x":521,"y":852,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_24.png": +{ + "frame": {"x":698,"y":677,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_25.png": +{ + "frame": {"x":698,"y":744,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_26.png": +{ + "frame": {"x":722,"y":599,"w":51,"h":63}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/forward_27.png": +{ + "frame": {"x":777,"y":597,"w":51,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, @@ -50,7 +226,7 @@ }, "sprites/belt/left_0.png": { - "frame": {"x":1890,"y":243,"w":57,"h":57}, + "frame": {"x":1015,"y":503,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, @@ -58,7 +234,7 @@ }, "sprites/belt/left_1.png": { - "frame": {"x":1951,"y":243,"w":57,"h":57}, + "frame": {"x":1076,"y":503,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, @@ -66,7 +242,7 @@ }, "sprites/belt/left_2.png": { - "frame": {"x":1783,"y":381,"w":57,"h":57}, + "frame": {"x":973,"y":698,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, @@ -74,7 +250,7 @@ }, "sprites/belt/left_3.png": { - "frame": {"x":1954,"y":371,"w":57,"h":57}, + "frame": {"x":1156,"y":692,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, @@ -82,7 +258,7 @@ }, "sprites/belt/left_4.png": { - "frame": {"x":1954,"y":432,"w":57,"h":57}, + "frame": {"x":1162,"y":753,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, @@ -90,7 +266,183 @@ }, "sprites/belt/left_5.png": { - "frame": {"x":1363,"y":403,"w":57,"h":57}, + "frame": {"x":576,"y":812,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_6.png": +{ + "frame": {"x":576,"y":873,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_7.png": +{ + "frame": {"x":561,"y":934,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_8.png": +{ + "frame": {"x":622,"y":934,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_9.png": +{ + "frame": {"x":979,"y":820,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_10.png": +{ + "frame": {"x":1137,"y":503,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_11.png": +{ + "frame": {"x":905,"y":570,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_12.png": +{ + "frame": {"x":1186,"y":570,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_13.png": +{ + "frame": {"x":527,"y":678,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_14.png": +{ + "frame": {"x":466,"y":724,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_15.png": +{ + "frame": {"x":527,"y":739,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_16.png": +{ + "frame": {"x":832,"y":615,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_17.png": +{ + "frame": {"x":893,"y":631,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_18.png": +{ + "frame": {"x":954,"y":637,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_19.png": +{ + "frame": {"x":918,"y":765,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_20.png": +{ + "frame": {"x":979,"y":759,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_21.png": +{ + "frame": {"x":1015,"y":637,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_22.png": +{ + "frame": {"x":1076,"y":631,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_23.png": +{ + "frame": {"x":1137,"y":631,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_24.png": +{ + "frame": {"x":1034,"y":698,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_25.png": +{ + "frame": {"x":1040,"y":759,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_26.png": +{ + "frame": {"x":1095,"y":692,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/left_27.png": +{ + "frame": {"x":1101,"y":753,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, @@ -98,7 +450,7 @@ }, "sprites/belt/right_0.png": { - "frame": {"x":1424,"y":403,"w":57,"h":57}, + "frame": {"x":1040,"y":820,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, @@ -106,7 +458,7 @@ }, "sprites/belt/right_1.png": { - "frame": {"x":1485,"y":403,"w":57,"h":57}, + "frame": {"x":1101,"y":814,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, @@ -114,7 +466,7 @@ }, "sprites/belt/right_2.png": { - "frame": {"x":1546,"y":403,"w":57,"h":57}, + "frame": {"x":881,"y":826,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, @@ -122,7 +474,7 @@ }, "sprites/belt/right_3.png": { - "frame": {"x":1607,"y":402,"w":57,"h":57}, + "frame": {"x":1186,"y":875,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, @@ -130,7 +482,7 @@ }, "sprites/belt/right_4.png": { - "frame": {"x":1668,"y":402,"w":57,"h":57}, + "frame": {"x":927,"y":948,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, @@ -138,7 +490,183 @@ }, "sprites/belt/right_5.png": { - "frame": {"x":1952,"y":181,"w":57,"h":57}, + "frame": {"x":988,"y":942,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_6.png": +{ + "frame": {"x":1049,"y":942,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_7.png": +{ + "frame": {"x":1110,"y":942,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_8.png": +{ + "frame": {"x":1171,"y":936,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_9.png": +{ + "frame": {"x":1232,"y":936,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_10.png": +{ + "frame": {"x":1162,"y":814,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_11.png": +{ + "frame": {"x":637,"y":812,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_12.png": +{ + "frame": {"x":637,"y":873,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_13.png": +{ + "frame": {"x":698,"y":811,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_14.png": +{ + "frame": {"x":698,"y":872,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_15.png": +{ + "frame": {"x":683,"y":934,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_16.png": +{ + "frame": {"x":744,"y":933,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_17.png": +{ + "frame": {"x":759,"y":810,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_18.png": +{ + "frame": {"x":759,"y":871,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_19.png": +{ + "frame": {"x":820,"y":826,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_20.png": +{ + "frame": {"x":820,"y":887,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_21.png": +{ + "frame": {"x":881,"y":887,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_22.png": +{ + "frame": {"x":805,"y":948,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_23.png": +{ + "frame": {"x":866,"y":948,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_24.png": +{ + "frame": {"x":942,"y":881,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_25.png": +{ + "frame": {"x":1003,"y":881,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_26.png": +{ + "frame": {"x":1064,"y":881,"w":57,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, + "sourceSize": {"w":63,"h":63} +}, +"sprites/belt/right_27.png": +{ + "frame": {"x":1125,"y":875,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, @@ -146,7 +674,7 @@ }, "sprites/blueprints/belt_left.png": { - "frame": {"x":1301,"y":400,"w":58,"h":58}, + "frame": {"x":843,"y":491,"w":58,"h":58}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":5,"w":58,"h":58}, @@ -154,7 +682,7 @@ }, "sprites/blueprints/belt_right.png": { - "frame": {"x":1890,"y":181,"w":58,"h":58}, + "frame": {"x":843,"y":553,"w":58,"h":58}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":5,"w":58,"h":58}, @@ -162,7 +690,7 @@ }, "sprites/blueprints/belt_top.png": { - "frame": {"x":1151,"y":403,"w":53,"h":63}, + "frame": {"x":472,"y":590,"w":53,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":53,"h":63}, @@ -178,15 +706,23 @@ }, "sprites/blueprints/cutter.png": { - "frame": {"x":1285,"y":203,"w":172,"h":96}, + "frame": {"x":1126,"y":103,"w":172,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, "sourceSize": {"w":192,"h":96} }, +"sprites/blueprints/energy_generator.png": +{ + "frame": {"x":199,"y":474,"w":170,"h":187}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":5,"w":170,"h":187}, + "sourceSize": {"w":192,"h":192} +}, "sprites/blueprints/miner-chainable.png": { - "frame": {"x":1401,"y":303,"w":92,"h":96}, + "frame": {"x":173,"y":669,"w":92,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, @@ -194,7 +730,7 @@ }, "sprites/blueprints/miner.png": { - "frame": {"x":1497,"y":303,"w":92,"h":96}, + "frame": {"x":178,"y":864,"w":92,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, @@ -202,7 +738,7 @@ }, "sprites/blueprints/mixer.png": { - "frame": {"x":1143,"y":103,"w":175,"h":96}, + "frame": {"x":1121,"y":3,"w":175,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, @@ -234,7 +770,7 @@ }, "sprites/blueprints/painter.png": { - "frame": {"x":1121,"y":3,"w":192,"h":96}, + "frame": {"x":740,"y":203,"w":192,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, @@ -242,7 +778,7 @@ }, "sprites/blueprints/rotater-ccw.png": { - "frame": {"x":1866,"y":3,"w":96,"h":96}, + "frame": {"x":1188,"y":303,"w":96,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, @@ -250,7 +786,7 @@ }, "sprites/blueprints/rotater.png": { - "frame": {"x":1675,"y":103,"w":96,"h":96}, + "frame": {"x":743,"y":497,"w":96,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, @@ -258,7 +794,7 @@ }, "sprites/blueprints/splitter-compact-inverse.png": { - "frame": {"x":1205,"y":303,"w":95,"h":93}, + "frame": {"x":269,"y":665,"w":95,"h":93}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, @@ -266,7 +802,7 @@ }, "sprites/blueprints/splitter-compact.png": { - "frame": {"x":1304,"y":303,"w":93,"h":93}, + "frame": {"x":270,"y":762,"w":93,"h":93}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, @@ -274,7 +810,7 @@ }, "sprites/blueprints/splitter.png": { - "frame": {"x":1691,"y":3,"w":171,"h":96}, + "frame": {"x":3,"y":865,"w":171,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, @@ -282,7 +818,7 @@ }, "sprites/blueprints/stacker.png": { - "frame": {"x":1106,"y":203,"w":175,"h":96}, + "frame": {"x":947,"y":103,"w":175,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, @@ -290,7 +826,7 @@ }, "sprites/blueprints/trash-storage.png": { - "frame": {"x":765,"y":203,"w":167,"h":192}, + "frame": {"x":569,"y":203,"w":167,"h":192}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, @@ -298,7 +834,7 @@ }, "sprites/blueprints/trash.png": { - "frame": {"x":1636,"y":203,"w":96,"h":96}, + "frame": {"x":935,"y":403,"w":96,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, @@ -306,7 +842,7 @@ }, "sprites/blueprints/underground_belt_entry-tier2.png": { - "frame": {"x":764,"y":399,"w":93,"h":84}, + "frame": {"x":838,"y":403,"w":93,"h":84}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, @@ -314,7 +850,7 @@ }, "sprites/blueprints/underground_belt_entry.png": { - "frame": {"x":373,"y":399,"w":93,"h":75}, + "frame": {"x":369,"y":856,"w":93,"h":75}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, @@ -322,7 +858,7 @@ }, "sprites/blueprints/underground_belt_exit-tier2.png": { - "frame": {"x":957,"y":399,"w":94,"h":75}, + "frame": {"x":368,"y":690,"w":94,"h":75}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, @@ -330,7 +866,7 @@ }, "sprites/blueprints/underground_belt_exit.png": { - "frame": {"x":470,"y":399,"w":93,"h":75}, + "frame": {"x":529,"y":599,"w":93,"h":75}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, @@ -338,7 +874,7 @@ }, "sprites/buildings/belt_left.png": { - "frame": {"x":1890,"y":243,"w":57,"h":57}, + "frame": {"x":1228,"y":637,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, @@ -346,7 +882,7 @@ }, "sprites/buildings/belt_right.png": { - "frame": {"x":1424,"y":403,"w":57,"h":57}, + "frame": {"x":1223,"y":698,"w":57,"h":57}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, @@ -354,7 +890,7 @@ }, "sprites/buildings/belt_top.png": { - "frame": {"x":1966,"y":3,"w":51,"h":63}, + "frame": {"x":1234,"y":403,"w":51,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, @@ -370,12 +906,20 @@ }, "sprites/buildings/cutter.png": { - "frame": {"x":1500,"y":103,"w":171,"h":96}, + "frame": {"x":838,"y":303,"w":171,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, "sourceSize": {"w":192,"h":96} }, +"sprites/buildings/energy_generator.png": +{ + "frame": {"x":373,"y":399,"w":170,"h":187}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":5,"w":170,"h":187}, + "sourceSize": {"w":192,"h":192} +}, "sprites/buildings/hub.png": { "frame": {"x":3,"y":3,"w":366,"h":367}, @@ -386,7 +930,7 @@ }, "sprites/buildings/miner-chainable.png": { - "frame": {"x":1593,"y":303,"w":91,"h":95}, + "frame": {"x":743,"y":398,"w":91,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, @@ -394,7 +938,7 @@ }, "sprites/buildings/miner.png": { - "frame": {"x":1688,"y":303,"w":91,"h":95}, + "frame": {"x":274,"y":859,"w":91,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, @@ -402,7 +946,7 @@ }, "sprites/buildings/mixer.png": { - "frame": {"x":1513,"y":3,"w":174,"h":96}, + "frame": {"x":936,"y":203,"w":174,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, @@ -410,7 +954,7 @@ }, "sprites/buildings/painter-double.png": { - "frame": {"x":569,"y":203,"w":192,"h":191}, + "frame": {"x":3,"y":474,"w":192,"h":191}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, @@ -418,7 +962,7 @@ }, "sprites/buildings/painter-mirrored.png": { - "frame": {"x":947,"y":103,"w":192,"h":96}, + "frame": {"x":547,"y":399,"w":192,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, @@ -434,7 +978,7 @@ }, "sprites/buildings/painter.png": { - "frame": {"x":1317,"y":3,"w":192,"h":96}, + "frame": {"x":547,"y":499,"w":192,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, @@ -442,7 +986,7 @@ }, "sprites/buildings/rotater-ccw.png": { - "frame": {"x":1736,"y":203,"w":95,"h":96}, + "frame": {"x":1135,"y":403,"w":95,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, @@ -450,7 +994,7 @@ }, "sprites/buildings/rotater.png": { - "frame": {"x":1106,"y":303,"w":95,"h":96}, + "frame": {"x":373,"y":590,"w":95,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, @@ -458,7 +1002,7 @@ }, "sprites/buildings/splitter-compact-inverse.png": { - "frame": {"x":569,"y":398,"w":94,"h":91}, + "frame": {"x":740,"y":303,"w":94,"h":91}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, @@ -466,7 +1010,7 @@ }, "sprites/buildings/splitter-compact.png": { - "frame": {"x":667,"y":398,"w":93,"h":91}, + "frame": {"x":173,"y":769,"w":93,"h":91}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, @@ -474,7 +1018,7 @@ }, "sprites/buildings/splitter.png": { - "frame": {"x":1461,"y":203,"w":171,"h":96}, + "frame": {"x":1013,"y":303,"w":171,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, @@ -482,7 +1026,7 @@ }, "sprites/buildings/stacker.png": { - "frame": {"x":1322,"y":103,"w":174,"h":96}, + "frame": {"x":1114,"y":203,"w":174,"h":96}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, @@ -490,7 +1034,7 @@ }, "sprites/buildings/trash-storage.png": { - "frame": {"x":936,"y":203,"w":166,"h":192}, + "frame": {"x":3,"y":669,"w":166,"h":192}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, @@ -498,7 +1042,7 @@ }, "sprites/buildings/trash.png": { - "frame": {"x":1775,"y":103,"w":96,"h":96}, + "frame": {"x":1035,"y":403,"w":96,"h":96}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, @@ -506,7 +1050,7 @@ }, "sprites/buildings/underground_belt_entry-tier2.png": { - "frame": {"x":861,"y":399,"w":92,"h":83}, + "frame": {"x":367,"y":769,"w":92,"h":83}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, @@ -514,7 +1058,7 @@ }, "sprites/buildings/underground_belt_entry.png": { - "frame": {"x":1875,"y":103,"w":92,"h":74}, + "frame": {"x":369,"y":935,"w":92,"h":74}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, @@ -522,7 +1066,7 @@ }, "sprites/buildings/underground_belt_exit-tier2.png": { - "frame": {"x":1783,"y":303,"w":92,"h":74}, + "frame": {"x":465,"y":935,"w":92,"h":74}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, @@ -530,7 +1074,7 @@ }, "sprites/buildings/underground_belt_exit.png": { - "frame": {"x":1055,"y":403,"w":92,"h":74}, + "frame": {"x":626,"y":599,"w":92,"h":74}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, @@ -538,7 +1082,7 @@ }, "sprites/debug/acceptor_slot.png": { - "frame": {"x":1989,"y":304,"w":26,"h":32}, + "frame": {"x":142,"y":965,"w":26,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, @@ -546,7 +1090,7 @@ }, "sprites/debug/ejector_slot.png": { - "frame": {"x":1971,"y":116,"w":26,"h":32}, + "frame": {"x":1198,"y":631,"w":26,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, @@ -554,7 +1098,7 @@ }, "sprites/map_overview/belt_forward.png": { - "frame": {"x":1835,"y":270,"w":14,"h":16}, + "frame": {"x":1284,"y":698,"w":14,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, @@ -562,7 +1106,7 @@ }, "sprites/map_overview/belt_left.png": { - "frame": {"x":3,"y":474,"w":15,"h":15}, + "frame": {"x":744,"y":994,"w":15,"h":15}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":15,"h":15}, @@ -570,7 +1114,7 @@ }, "sprites/map_overview/belt_right.png": { - "frame": {"x":22,"y":474,"w":15,"h":15}, + "frame": {"x":763,"y":994,"w":15,"h":15}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":15,"h":15}, @@ -578,7 +1122,7 @@ }, "sprites/misc/deletion_marker.png": { - "frame": {"x":1971,"y":70,"w":42,"h":42}, + "frame": {"x":96,"y":965,"w":42,"h":42}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, @@ -586,7 +1130,7 @@ }, "sprites/misc/hub_direction_indicator.png": { - "frame": {"x":2001,"y":116,"w":16,"h":16}, + "frame": {"x":942,"y":826,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -594,7 +1138,7 @@ }, "sprites/misc/lock_direction_indicator.png": { - "frame": {"x":1208,"y":448,"w":24,"h":16}, + "frame": {"x":1234,"y":470,"w":24,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":4,"w":24,"h":16}, @@ -602,7 +1146,7 @@ }, "sprites/misc/slot_bad_arrow.png": { - "frame": {"x":1971,"y":70,"w":42,"h":42}, + "frame": {"x":96,"y":965,"w":42,"h":42}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, @@ -610,7 +1154,7 @@ }, "sprites/misc/slot_good_arrow.png": { - "frame": {"x":1729,"y":402,"w":42,"h":48}, + "frame": {"x":518,"y":800,"w":42,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, @@ -618,7 +1162,7 @@ }, "sprites/misc/storage_overlay.png": { - "frame": {"x":1208,"y":400,"w":89,"h":44}, + "frame": {"x":3,"y":965,"w":89,"h":44}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, @@ -626,7 +1170,7 @@ }, "sprites/misc/waypoint.png": { - "frame": {"x":1989,"y":340,"w":14,"h":16}, + "frame": {"x":1284,"y":718,"w":14,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, @@ -637,8 +1181,8 @@ "version": "1.0", "image": "atlas0_50.png", "format": "RGBA8888", - "size": {"w":2020,"h":492}, + "size": {"w":1301,"h":1012}, "scale": "0.5", - "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$" + "smartupdate": "$TexturePacker:SmartUpdate:dc34796c028235bbc69e5b8d854254ca:2765d0b8c8bcbb7a4aaaf1104853ad41:8778749683c68f53155587e6d831729a$" } } diff --git a/res_built/atlas/atlas0_50.png b/res_built/atlas/atlas0_50.png index 60e1f644..29116b1b 100644 Binary files a/res_built/atlas/atlas0_50.png and b/res_built/atlas/atlas0_50.png differ diff --git a/res_built/atlas/atlas0_75.json b/res_built/atlas/atlas0_75.json index 392448be..147b55c9 100644 --- a/res_built/atlas/atlas0_75.json +++ b/res_built/atlas/atlas0_75.json @@ -2,7 +2,7 @@ "sprites/belt/forward_0.png": { - "frame": {"x":1963,"y":102,"w":77,"h":95}, + "frame": {"x":86,"y":1431,"w":77,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, @@ -10,7 +10,7 @@ }, "sprites/belt/forward_1.png": { - "frame": {"x":1963,"y":201,"w":77,"h":95}, + "frame": {"x":167,"y":1431,"w":77,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, @@ -18,7 +18,7 @@ }, "sprites/belt/forward_2.png": { - "frame": {"x":1967,"y":300,"w":77,"h":95}, + "frame": {"x":1519,"y":1282,"w":77,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, @@ -26,7 +26,7 @@ }, "sprites/belt/forward_3.png": { - "frame": {"x":1967,"y":399,"w":77,"h":95}, + "frame": {"x":960,"y":3,"w":77,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, @@ -34,7 +34,7 @@ }, "sprites/belt/forward_4.png": { - "frame": {"x":1967,"y":498,"w":77,"h":95}, + "frame": {"x":1041,"y":3,"w":77,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, @@ -42,7 +42,183 @@ }, "sprites/belt/forward_5.png": { - "frame": {"x":1679,"y":952,"w":77,"h":95}, + "frame": {"x":774,"y":548,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_6.png": +{ + "frame": {"x":815,"y":254,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_7.png": +{ + "frame": {"x":815,"y":353,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_8.png": +{ + "frame": {"x":855,"y":542,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_9.png": +{ + "frame": {"x":896,"y":254,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_10.png": +{ + "frame": {"x":248,"y":1431,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_11.png": +{ + "frame": {"x":329,"y":1428,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_12.png": +{ + "frame": {"x":410,"y":1428,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_13.png": +{ + "frame": {"x":491,"y":1428,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_14.png": +{ + "frame": {"x":572,"y":1428,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_15.png": +{ + "frame": {"x":653,"y":1426,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_16.png": +{ + "frame": {"x":734,"y":1426,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_17.png": +{ + "frame": {"x":815,"y":1426,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_18.png": +{ + "frame": {"x":1438,"y":1284,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_19.png": +{ + "frame": {"x":1811,"y":806,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_20.png": +{ + "frame": {"x":1600,"y":1282,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_21.png": +{ + "frame": {"x":1681,"y":1282,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_22.png": +{ + "frame": {"x":1755,"y":1406,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_23.png": +{ + "frame": {"x":555,"y":3,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_24.png": +{ + "frame": {"x":636,"y":3,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_25.png": +{ + "frame": {"x":717,"y":3,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_26.png": +{ + "frame": {"x":798,"y":3,"w":77,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/forward_27.png": +{ + "frame": {"x":879,"y":3,"w":77,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, @@ -50,7 +226,7 @@ }, "sprites/belt/left_0.png": { - "frame": {"x":1217,"y":969,"w":86,"h":86}, + "frame": {"x":1707,"y":1102,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, @@ -58,7 +234,7 @@ }, "sprites/belt/left_1.png": { - "frame": {"x":1307,"y":969,"w":86,"h":86}, + "frame": {"x":1797,"y":1136,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, @@ -66,7 +242,7 @@ }, "sprites/belt/left_2.png": { - "frame": {"x":1916,"y":597,"w":86,"h":86}, + "frame": {"x":995,"y":434,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, @@ -74,7 +250,7 @@ }, "sprites/belt/left_3.png": { - "frame": {"x":1916,"y":687,"w":86,"h":86}, + "frame": {"x":1212,"y":3,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, @@ -82,7 +258,7 @@ }, "sprites/belt/left_4.png": { - "frame": {"x":1916,"y":777,"w":86,"h":86}, + "frame": {"x":1166,"y":287,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, @@ -90,7 +266,183 @@ }, "sprites/belt/left_5.png": { - "frame": {"x":1914,"y":867,"w":86,"h":86}, + "frame": {"x":1247,"y":197,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_6.png": +{ + "frame": {"x":1287,"y":107,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_7.png": +{ + "frame": {"x":1302,"y":3,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_8.png": +{ + "frame": {"x":1175,"y":377,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_9.png": +{ + "frame": {"x":1256,"y":287,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_10.png": +{ + "frame": {"x":1707,"y":1192,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_11.png": +{ + "frame": {"x":1797,"y":1226,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_12.png": +{ + "frame": {"x":1762,"y":1316,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_13.png": +{ + "frame": {"x":815,"y":452,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_14.png": +{ + "frame": {"x":896,"y":353,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_15.png": +{ + "frame": {"x":977,"y":254,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_16.png": +{ + "frame": {"x":905,"y":443,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_17.png": +{ + "frame": {"x":986,"y":344,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_18.png": +{ + "frame": {"x":1067,"y":254,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_19.png": +{ + "frame": {"x":936,"y":533,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_20.png": +{ + "frame": {"x":1076,"y":344,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_21.png": +{ + "frame": {"x":1026,"y":524,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_22.png": +{ + "frame": {"x":1085,"y":434,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_23.png": +{ + "frame": {"x":1116,"y":524,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_24.png": +{ + "frame": {"x":1107,"y":107,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_25.png": +{ + "frame": {"x":1122,"y":3,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_26.png": +{ + "frame": {"x":1157,"y":197,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/left_27.png": +{ + "frame": {"x":1197,"y":107,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, @@ -98,7 +450,7 @@ }, "sprites/belt/right_0.png": { - "frame": {"x":1499,"y":852,"w":86,"h":86}, + "frame": {"x":1337,"y":197,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, @@ -106,7 +458,7 @@ }, "sprites/belt/right_1.png": { - "frame": {"x":1397,"y":967,"w":86,"h":86}, + "frame": {"x":1377,"y":107,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, @@ -114,7 +466,7 @@ }, "sprites/belt/right_2.png": { - "frame": {"x":1589,"y":862,"w":86,"h":86}, + "frame": {"x":1647,"y":107,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, @@ -122,7 +474,7 @@ }, "sprites/belt/right_3.png": { - "frame": {"x":1679,"y":862,"w":86,"h":86}, + "frame": {"x":1386,"y":543,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, @@ -130,7 +482,7 @@ }, "sprites/belt/right_4.png": { - "frame": {"x":1499,"y":942,"w":86,"h":86}, + "frame": {"x":1476,"y":453,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, @@ -138,7 +490,183 @@ }, "sprites/belt/right_5.png": { - "frame": {"x":1589,"y":952,"w":86,"h":86}, + "frame": {"x":1476,"y":543,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_6.png": +{ + "frame": {"x":1566,"y":377,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_7.png": +{ + "frame": {"x":1656,"y":377,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_8.png": +{ + "frame": {"x":1566,"y":467,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_9.png": +{ + "frame": {"x":1656,"y":467,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_10.png": +{ + "frame": {"x":1392,"y":3,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_11.png": +{ + "frame": {"x":1206,"y":467,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_12.png": +{ + "frame": {"x":1265,"y":377,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_13.png": +{ + "frame": {"x":1346,"y":287,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_14.png": +{ + "frame": {"x":1427,"y":197,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_15.png": +{ + "frame": {"x":1467,"y":107,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_16.png": +{ + "frame": {"x":1206,"y":557,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_17.png": +{ + "frame": {"x":1482,"y":3,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_18.png": +{ + "frame": {"x":1572,"y":3,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_19.png": +{ + "frame": {"x":1557,"y":93,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_20.png": +{ + "frame": {"x":1557,"y":183,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_21.png": +{ + "frame": {"x":1647,"y":197,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_22.png": +{ + "frame": {"x":1517,"y":273,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_23.png": +{ + "frame": {"x":1607,"y":287,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_24.png": +{ + "frame": {"x":1436,"y":363,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_25.png": +{ + "frame": {"x":1296,"y":467,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_26.png": +{ + "frame": {"x":1296,"y":557,"w":86,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, + "sourceSize": {"w":95,"h":95} +}, +"sprites/belt/right_27.png": +{ + "frame": {"x":1386,"y":453,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, @@ -146,7 +674,7 @@ }, "sprites/blueprints/belt_left.png": { - "frame": {"x":1397,"y":593,"w":87,"h":87}, + "frame": {"x":1803,"y":954,"w":87,"h":87}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":8,"w":87,"h":87}, @@ -154,7 +682,7 @@ }, "sprites/blueprints/belt_right.png": { - "frame": {"x":1397,"y":684,"w":87,"h":87}, + "frame": {"x":1803,"y":1045,"w":87,"h":87}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":8,"w":87,"h":87}, @@ -162,7 +690,7 @@ }, "sprites/blueprints/belt_top.png": { - "frame": {"x":1963,"y":3,"w":79,"h":95}, + "frame": {"x":3,"y":1431,"w":79,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":8,"y":0,"w":79,"h":95}, @@ -170,7 +698,7 @@ }, "sprites/blueprints/cutter-quad.png": { - "frame": {"x":3,"y":556,"w":548,"h":144}, + "frame": {"x":547,"y":988,"w":548,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":17,"y":0,"w":548,"h":144}, @@ -178,15 +706,23 @@ }, "sprites/blueprints/cutter.png": { - "frame": {"x":1411,"y":150,"w":256,"h":144}, + "frame": {"x":1111,"y":807,"w":256,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, "sourceSize": {"w":288,"h":144} }, +"sprites/blueprints/energy_generator.png": +{ + "frame": {"x":257,"y":556,"w":255,"h":280}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":8,"w":255,"h":280}, + "sourceSize": {"w":288,"h":288} +}, "sprites/blueprints/miner-chainable.png": { - "frame": {"x":1827,"y":447,"w":136,"h":143}, + "frame": {"x":1755,"y":3,"w":136,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, @@ -194,7 +730,7 @@ }, "sprites/blueprints/miner.png": { - "frame": {"x":1076,"y":739,"w":136,"h":143}, + "frame": {"x":1755,"y":150,"w":136,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, @@ -202,7 +738,7 @@ }, "sprites/blueprints/mixer.png": { - "frame": {"x":547,"y":738,"w":261,"h":144}, + "frame": {"x":774,"y":659,"w":261,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, @@ -210,7 +746,7 @@ }, "sprites/blueprints/painter-double.png": { - "frame": {"x":555,"y":299,"w":288,"h":287}, + "frame": {"x":3,"y":1140,"w":288,"h":287}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, @@ -218,7 +754,7 @@ }, "sprites/blueprints/painter-mirrored.png": { - "frame": {"x":1119,"y":150,"w":288,"h":144}, + "frame": {"x":859,"y":1136,"w":288,"h":144}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, @@ -226,7 +762,7 @@ }, "sprites/blueprints/painter-quad.png": { - "frame": {"x":555,"y":3,"w":560,"h":144}, + "frame": {"x":295,"y":1138,"w":560,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, @@ -234,7 +770,7 @@ }, "sprites/blueprints/painter.png": { - "frame": {"x":1671,"y":3,"w":288,"h":144}, + "frame": {"x":1099,"y":988,"w":288,"h":144}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, @@ -242,7 +778,7 @@ }, "sprites/blueprints/rotater-ccw.png": { - "frame": {"x":1639,"y":299,"w":143,"h":144}, + "frame": {"x":1519,"y":807,"w":143,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, @@ -250,7 +786,7 @@ }, "sprites/blueprints/rotater.png": { - "frame": {"x":1786,"y":299,"w":143,"h":144}, + "frame": {"x":1564,"y":659,"w":143,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, @@ -258,7 +794,7 @@ }, "sprites/blueprints/splitter-compact-inverse.png": { - "frame": {"x":1071,"y":886,"w":142,"h":138}, + "frame": {"x":295,"y":1286,"w":142,"h":138}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, @@ -266,7 +802,7 @@ }, "sprites/blueprints/splitter-compact.png": { - "frame": {"x":1488,"y":594,"w":139,"h":138}, + "frame": {"x":441,"y":1286,"w":139,"h":138}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, @@ -274,7 +810,7 @@ }, "sprites/blueprints/splitter.png": { - "frame": {"x":811,"y":886,"w":256,"h":144}, + "frame": {"x":1304,"y":659,"w":256,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, @@ -282,7 +818,7 @@ }, "sprites/blueprints/stacker.png": { - "frame": {"x":847,"y":591,"w":261,"h":144}, + "frame": {"x":1039,"y":659,"w":261,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, @@ -290,7 +826,7 @@ }, "sprites/blueprints/trash-storage.png": { - "frame": {"x":847,"y":299,"w":250,"h":288}, + "frame": {"x":3,"y":556,"w":250,"h":288}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":21,"y":0,"w":250,"h":288}, @@ -298,7 +834,7 @@ }, "sprites/blueprints/trash.png": { - "frame": {"x":1241,"y":445,"w":144,"h":144}, + "frame": {"x":1371,"y":807,"w":144,"h":144}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, @@ -306,7 +842,7 @@ }, "sprites/blueprints/underground_belt_entry-tier2.png": { - "frame": {"x":1774,"y":594,"w":138,"h":125}, + "frame": {"x":872,"y":1284,"w":138,"h":125}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, @@ -314,7 +850,7 @@ }, "sprites/blueprints/underground_belt_entry.png": { - "frame": {"x":1774,"y":723,"w":138,"h":112}, + "frame": {"x":1039,"y":1412,"w":138,"h":112}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, @@ -322,7 +858,7 @@ }, "sprites/blueprints/underground_belt_exit-tier2.png": { - "frame": {"x":1488,"y":736,"w":139,"h":112}, + "frame": {"x":896,"y":1413,"w":139,"h":112}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, @@ -330,7 +866,7 @@ }, "sprites/blueprints/underground_belt_exit.png": { - "frame": {"x":1772,"y":839,"w":138,"h":112}, + "frame": {"x":1155,"y":1284,"w":138,"h":112}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, @@ -338,7 +874,7 @@ }, "sprites/buildings/belt_left.png": { - "frame": {"x":1217,"y":969,"w":86,"h":86}, + "frame": {"x":1566,"y":557,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, @@ -346,7 +882,7 @@ }, "sprites/buildings/belt_right.png": { - "frame": {"x":1499,"y":852,"w":86,"h":86}, + "frame": {"x":1656,"y":557,"w":86,"h":86}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, @@ -354,7 +890,7 @@ }, "sprites/buildings/belt_top.png": { - "frame": {"x":1963,"y":102,"w":77,"h":95}, + "frame": {"x":86,"y":1431,"w":77,"h":95}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, @@ -362,7 +898,7 @@ }, "sprites/buildings/cutter-quad.png": { - "frame": {"x":1119,"y":3,"w":548,"h":143}, + "frame": {"x":555,"y":107,"w":548,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":17,"y":0,"w":548,"h":143}, @@ -370,12 +906,20 @@ }, "sprites/buildings/cutter.png": { - "frame": {"x":1119,"y":298,"w":256,"h":143}, + "frame": {"x":555,"y":254,"w":256,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, "sourceSize": {"w":288,"h":144} }, +"sprites/buildings/energy_generator.png": +{ + "frame": {"x":516,"y":556,"w":254,"h":280}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":19,"y":8,"w":254,"h":280}, + "sourceSize": {"w":288,"h":288} +}, "sprites/buildings/hub.png": { "frame": {"x":3,"y":3,"w":548,"h":549}, @@ -386,7 +930,7 @@ }, "sprites/buildings/miner-chainable.png": { - "frame": {"x":1101,"y":445,"w":136,"h":142}, + "frame": {"x":1755,"y":297,"w":136,"h":142}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, @@ -394,7 +938,7 @@ }, "sprites/buildings/miner.png": { - "frame": {"x":1112,"y":593,"w":136,"h":142}, + "frame": {"x":1755,"y":443,"w":136,"h":142}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, @@ -402,7 +946,7 @@ }, "sprites/buildings/mixer.png": { - "frame": {"x":812,"y":739,"w":260,"h":143}, + "frame": {"x":1443,"y":1103,"w":260,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, @@ -410,7 +954,7 @@ }, "sprites/buildings/painter-double.png": { - "frame": {"x":3,"y":704,"w":288,"h":286}, + "frame": {"x":255,"y":848,"w":288,"h":286}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, @@ -418,7 +962,7 @@ }, "sprites/buildings/painter-mirrored.png": { - "frame": {"x":1671,"y":151,"w":288,"h":144}, + "frame": {"x":1151,"y":1136,"w":288,"h":144}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, @@ -426,7 +970,7 @@ }, "sprites/buildings/painter-quad.png": { - "frame": {"x":555,"y":151,"w":560,"h":144}, + "frame": {"x":547,"y":840,"w":560,"h":144}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, @@ -434,7 +978,7 @@ }, "sprites/buildings/painter.png": { - "frame": {"x":555,"y":590,"w":288,"h":144}, + "frame": {"x":1463,"y":1383,"w":288,"h":144}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, @@ -442,7 +986,7 @@ }, "sprites/buildings/rotater-ccw.png": { - "frame": {"x":1537,"y":447,"w":141,"h":143}, + "frame": {"x":1666,"y":807,"w":141,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, @@ -450,7 +994,7 @@ }, "sprites/buildings/rotater.png": { - "frame": {"x":1682,"y":447,"w":141,"h":143}, + "frame": {"x":1711,"y":659,"w":141,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, @@ -458,7 +1002,7 @@ }, "sprites/buildings/splitter-compact-inverse.png": { - "frame": {"x":1252,"y":593,"w":141,"h":136}, + "frame": {"x":584,"y":1286,"w":141,"h":136}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, @@ -466,7 +1010,7 @@ }, "sprites/buildings/splitter-compact.png": { - "frame": {"x":1631,"y":594,"w":139,"h":136}, + "frame": {"x":729,"y":1286,"w":139,"h":136}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, @@ -474,7 +1018,7 @@ }, "sprites/buildings/splitter.png": { - "frame": {"x":1379,"y":298,"w":256,"h":143}, + "frame": {"x":555,"y":401,"w":256,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, @@ -482,7 +1026,7 @@ }, "sprites/buildings/stacker.png": { - "frame": {"x":547,"y":886,"w":260,"h":143}, + "frame": {"x":1539,"y":955,"w":260,"h":143}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, @@ -490,7 +1034,7 @@ }, "sprites/buildings/trash-storage.png": { - "frame": {"x":295,"y":704,"w":248,"h":288}, + "frame": {"x":3,"y":848,"w":248,"h":288}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":22,"y":0,"w":248,"h":288}, @@ -498,7 +1042,7 @@ }, "sprites/buildings/trash.png": { - "frame": {"x":1389,"y":445,"w":144,"h":144}, + "frame": {"x":1391,"y":955,"w":144,"h":144}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, @@ -506,7 +1050,7 @@ }, "sprites/buildings/underground_belt_entry-tier2.png": { - "frame": {"x":1631,"y":734,"w":137,"h":124}, + "frame": {"x":1014,"y":1284,"w":137,"h":124}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, @@ -514,7 +1058,7 @@ }, "sprites/buildings/underground_belt_entry.png": { - "frame": {"x":1216,"y":739,"w":137,"h":111}, + "frame": {"x":1181,"y":1400,"w":137,"h":111}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, @@ -522,7 +1066,7 @@ }, "sprites/buildings/underground_belt_exit-tier2.png": { - "frame": {"x":1217,"y":854,"w":137,"h":111}, + "frame": {"x":1297,"y":1284,"w":137,"h":111}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, @@ -530,7 +1074,7 @@ }, "sprites/buildings/underground_belt_exit.png": { - "frame": {"x":1358,"y":852,"w":137,"h":111}, + "frame": {"x":1322,"y":1399,"w":137,"h":111}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, @@ -538,7 +1082,7 @@ }, "sprites/debug/acceptor_slot.png": { - "frame": {"x":2006,"y":597,"w":38,"h":48}, + "frame": {"x":1711,"y":3,"w":38,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, @@ -546,7 +1090,7 @@ }, "sprites/debug/ejector_slot.png": { - "frame": {"x":2006,"y":649,"w":38,"h":48}, + "frame": {"x":1711,"y":55,"w":38,"h":48}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, @@ -554,7 +1098,7 @@ }, "sprites/map_overview/belt_forward.png": { - "frame": {"x":1826,"y":955,"w":20,"h":24}, + "frame": {"x":842,"y":807,"w":20,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, @@ -562,7 +1106,7 @@ }, "sprites/map_overview/belt_left.png": { - "frame": {"x":206,"y":994,"w":22,"h":22}, + "frame": {"x":890,"y":807,"w":22,"h":22}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":22,"h":22}, @@ -570,7 +1114,7 @@ }, "sprites/map_overview/belt_right.png": { - "frame": {"x":2006,"y":701,"w":22,"h":22}, + "frame": {"x":916,"y":807,"w":22,"h":22}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":22,"h":22}, @@ -578,7 +1122,7 @@ }, "sprites/misc/deletion_marker.png": { - "frame": {"x":140,"y":994,"w":62,"h":62}, + "frame": {"x":1355,"y":377,"w":62,"h":62}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, @@ -586,7 +1130,7 @@ }, "sprites/misc/hub_direction_indicator.png": { - "frame": {"x":1933,"y":299,"w":24,"h":24}, + "frame": {"x":814,"y":807,"w":24,"h":24}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":24,"h":24}, @@ -594,7 +1138,7 @@ }, "sprites/misc/lock_direction_indicator.png": { - "frame": {"x":1357,"y":733,"w":36,"h":24}, + "frame": {"x":774,"y":807,"w":36,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":6,"w":36,"h":24}, @@ -602,7 +1146,7 @@ }, "sprites/misc/slot_bad_arrow.png": { - "frame": {"x":140,"y":994,"w":62,"h":62}, + "frame": {"x":1355,"y":377,"w":62,"h":62}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, @@ -610,7 +1154,7 @@ }, "sprites/misc/slot_good_arrow.png": { - "frame": {"x":1760,"y":955,"w":62,"h":72}, + "frame": {"x":1436,"y":287,"w":62,"h":72}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":0,"w":62,"h":72}, @@ -618,7 +1162,7 @@ }, "sprites/misc/storage_overlay.png": { - "frame": {"x":3,"y":994,"w":133,"h":66}, + "frame": {"x":1755,"y":589,"w":133,"h":66}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":2,"w":133,"h":66}, @@ -626,7 +1170,7 @@ }, "sprites/misc/waypoint.png": { - "frame": {"x":1357,"y":761,"w":20,"h":24}, + "frame": {"x":866,"y":807,"w":20,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, @@ -637,8 +1181,8 @@ "version": "1.0", "image": "atlas0_75.png", "format": "RGBA8888", - "size": {"w":2047,"h":1063}, + "size": {"w":1894,"h":1530}, "scale": "0.75", - "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$" + "smartupdate": "$TexturePacker:SmartUpdate:dc34796c028235bbc69e5b8d854254ca:2765d0b8c8bcbb7a4aaaf1104853ad41:8778749683c68f53155587e6d831729a$" } } diff --git a/res_built/atlas/atlas0_75.png b/res_built/atlas/atlas0_75.png index f4844add..5b42712a 100644 Binary files a/res_built/atlas/atlas0_75.png and b/res_built/atlas/atlas0_75.png differ diff --git a/res_built/atlas/atlas1_100.json b/res_built/atlas/atlas1_100.json new file mode 100644 index 00000000..3581b36a --- /dev/null +++ b/res_built/atlas/atlas1_100.json @@ -0,0 +1,509 @@ +{"frames": { + +"sprites/belt/forward_3.png": +{ + "frame": {"x":3,"y":783,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_4.png": +{ + "frame": {"x":3,"y":913,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_5.png": +{ + "frame": {"x":3,"y":1043,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_6.png": +{ + "frame": {"x":3,"y":1173,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_7.png": +{ + "frame": {"x":3,"y":1303,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_8.png": +{ + "frame": {"x":107,"y":3,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_9.png": +{ + "frame": {"x":107,"y":133,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_22.png": +{ + "frame": {"x":3,"y":3,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_23.png": +{ + "frame": {"x":3,"y":133,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_24.png": +{ + "frame": {"x":3,"y":263,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_25.png": +{ + "frame": {"x":3,"y":393,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_26.png": +{ + "frame": {"x":3,"y":523,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/forward_27.png": +{ + "frame": {"x":3,"y":653,"w":100,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_2.png": +{ + "frame": {"x":3,"y":1784,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_3.png": +{ + "frame": {"x":107,"y":965,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_4.png": +{ + "frame": {"x":107,"y":1082,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_5.png": +{ + "frame": {"x":107,"y":1199,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_6.png": +{ + "frame": {"x":107,"y":1316,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_7.png": +{ + "frame": {"x":120,"y":1433,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_8.png": +{ + "frame": {"x":120,"y":1550,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_9.png": +{ + "frame": {"x":120,"y":1667,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_17.png": +{ + "frame": {"x":3,"y":1433,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_18.png": +{ + "frame": {"x":3,"y":1550,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_19.png": +{ + "frame": {"x":3,"y":1667,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_20.png": +{ + "frame": {"x":107,"y":263,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_21.png": +{ + "frame": {"x":211,"y":3,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_22.png": +{ + "frame": {"x":211,"y":120,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_23.png": +{ + "frame": {"x":107,"y":380,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_24.png": +{ + "frame": {"x":107,"y":497,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_25.png": +{ + "frame": {"x":107,"y":614,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_26.png": +{ + "frame": {"x":107,"y":731,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/left_27.png": +{ + "frame": {"x":107,"y":848,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_0.png": +{ + "frame": {"x":120,"y":1784,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_1.png": +{ + "frame": {"x":224,"y":237,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_2.png": +{ + "frame": {"x":224,"y":1290,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_3.png": +{ + "frame": {"x":341,"y":705,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_4.png": +{ + "frame": {"x":341,"y":822,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_5.png": +{ + "frame": {"x":341,"y":939,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_6.png": +{ + "frame": {"x":341,"y":1056,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_7.png": +{ + "frame": {"x":341,"y":1173,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_8.png": +{ + "frame": {"x":341,"y":1290,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_9.png": +{ + "frame": {"x":354,"y":1407,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_10.png": +{ + "frame": {"x":328,"y":3,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_11.png": +{ + "frame": {"x":328,"y":120,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_12.png": +{ + "frame": {"x":224,"y":354,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_13.png": +{ + "frame": {"x":224,"y":471,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_14.png": +{ + "frame": {"x":224,"y":588,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_15.png": +{ + "frame": {"x":224,"y":705,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_16.png": +{ + "frame": {"x":224,"y":822,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_17.png": +{ + "frame": {"x":224,"y":939,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_18.png": +{ + "frame": {"x":224,"y":1056,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_19.png": +{ + "frame": {"x":224,"y":1173,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_20.png": +{ + "frame": {"x":237,"y":1407,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_21.png": +{ + "frame": {"x":237,"y":1524,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_22.png": +{ + "frame": {"x":237,"y":1641,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_23.png": +{ + "frame": {"x":237,"y":1758,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_24.png": +{ + "frame": {"x":341,"y":237,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_25.png": +{ + "frame": {"x":341,"y":354,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_26.png": +{ + "frame": {"x":341,"y":471,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/belt/right_27.png": +{ + "frame": {"x":341,"y":588,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":354,"y":1524,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":354,"y":1641,"w":113,"h":113}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, + "sourceSize": {"w":126,"h":126} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas1_100.png", + "format": "RGBA8888", + "size": {"w":470,"h":1900}, + "scale": "1", + "related_multi_packs": [ "atlas0_100.json" ], + "smartupdate": "$TexturePacker:SmartUpdate:dc34796c028235bbc69e5b8d854254ca:2765d0b8c8bcbb7a4aaaf1104853ad41:8778749683c68f53155587e6d831729a$" +} +} diff --git a/res_built/atlas/atlas1_100.png b/res_built/atlas/atlas1_100.png new file mode 100644 index 00000000..75210aad Binary files /dev/null and b/res_built/atlas/atlas1_100.png differ diff --git a/res_raw/atlas.tps b/res_raw/atlas.tps index 07da7809..d4e8f4e0 100644 --- a/res_raw/atlas.tps +++ b/res_raw/atlas.tps @@ -269,21 +269,87 @@ scale9FromFile + sprites/belt/forward_10.png + sprites/belt/forward_11.png + sprites/belt/forward_12.png + sprites/belt/forward_13.png + sprites/belt/forward_14.png + sprites/belt/forward_15.png + sprites/belt/forward_16.png + sprites/belt/forward_17.png + sprites/belt/forward_18.png + sprites/belt/forward_19.png + sprites/belt/forward_20.png + sprites/belt/forward_21.png + sprites/belt/forward_22.png + sprites/belt/forward_23.png + sprites/belt/forward_24.png + sprites/belt/forward_25.png + sprites/belt/forward_26.png + sprites/belt/forward_27.png sprites/belt/forward_3.png sprites/belt/forward_4.png sprites/belt/forward_5.png + sprites/belt/forward_6.png + sprites/belt/forward_7.png + sprites/belt/forward_8.png + sprites/belt/forward_9.png sprites/belt/left_0.png sprites/belt/left_1.png + sprites/belt/left_10.png + sprites/belt/left_11.png + sprites/belt/left_12.png + sprites/belt/left_13.png + sprites/belt/left_14.png + sprites/belt/left_15.png + sprites/belt/left_16.png + sprites/belt/left_17.png + sprites/belt/left_18.png + sprites/belt/left_19.png sprites/belt/left_2.png + sprites/belt/left_20.png + sprites/belt/left_21.png + sprites/belt/left_22.png + sprites/belt/left_23.png + sprites/belt/left_24.png + sprites/belt/left_25.png + sprites/belt/left_26.png + sprites/belt/left_27.png sprites/belt/left_3.png sprites/belt/left_4.png sprites/belt/left_5.png + sprites/belt/left_6.png + sprites/belt/left_7.png + sprites/belt/left_8.png + sprites/belt/left_9.png sprites/belt/right_0.png sprites/belt/right_1.png + sprites/belt/right_10.png + sprites/belt/right_11.png + sprites/belt/right_12.png + sprites/belt/right_13.png + sprites/belt/right_14.png + sprites/belt/right_15.png + sprites/belt/right_16.png + sprites/belt/right_17.png + sprites/belt/right_18.png + sprites/belt/right_19.png sprites/belt/right_2.png + sprites/belt/right_20.png + sprites/belt/right_21.png + sprites/belt/right_22.png + sprites/belt/right_23.png + sprites/belt/right_24.png + sprites/belt/right_25.png + sprites/belt/right_26.png + sprites/belt/right_27.png sprites/belt/right_3.png sprites/belt/right_4.png sprites/belt/right_5.png + sprites/belt/right_6.png + sprites/belt/right_7.png + sprites/belt/right_8.png + sprites/belt/right_9.png sprites/blueprints/belt_left.png sprites/blueprints/belt_right.png sprites/blueprints/belt_top.png @@ -343,6 +409,25 @@ scale9FromFile + sprites/blueprints/energy_generator.png + sprites/blueprints/painter-double.png + sprites/blueprints/trash-storage.png + sprites/buildings/energy_generator.png + sprites/buildings/painter-double.png + + pivotPoint + 0.5,0.5 + spriteScale + 1 + scale9Enabled + + scale9Borders + 96,96,192,192 + scale9Paddings + 96,96,192,192 + scale9FromFile + + sprites/blueprints/miner-chainable.png sprites/blueprints/miner.png sprites/blueprints/rotater-ccw.png @@ -376,23 +461,6 @@ scale9FromFile - sprites/blueprints/painter-double.png - sprites/blueprints/trash-storage.png - sprites/buildings/painter-double.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 96,96,192,192 - scale9Paddings - 96,96,192,192 - scale9FromFile - - sprites/buildings/cutter.png sprites/buildings/mixer.png sprites/buildings/painter.png diff --git a/res_raw/sounds/sfx/destroy_building.wav b/res_raw/sounds/sfx/destroy_building.wav new file mode 100644 index 00000000..ffb38158 --- /dev/null +++ b/res_raw/sounds/sfx/destroy_building.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1dc8775fdf5155097d6e1d60a436f48916af56eec14fb9034e71b32ad3b6f1b0 +size 358896 diff --git a/res_raw/sprites/belt/forward_0.png b/res_raw/sprites/belt/forward_0.png index def37d7d..cf5b20d7 100644 Binary files a/res_raw/sprites/belt/forward_0.png and b/res_raw/sprites/belt/forward_0.png differ diff --git a/res_raw/sprites/belt/forward_1.png b/res_raw/sprites/belt/forward_1.png index 1ed11ef2..44e5b8c8 100644 Binary files a/res_raw/sprites/belt/forward_1.png and b/res_raw/sprites/belt/forward_1.png differ diff --git a/res_raw/sprites/belt/forward_10.png b/res_raw/sprites/belt/forward_10.png new file mode 100644 index 00000000..d599463d Binary files /dev/null and b/res_raw/sprites/belt/forward_10.png differ diff --git a/res_raw/sprites/belt/forward_11.png b/res_raw/sprites/belt/forward_11.png new file mode 100644 index 00000000..69fff65c Binary files /dev/null and b/res_raw/sprites/belt/forward_11.png differ diff --git a/res_raw/sprites/belt/forward_12.png b/res_raw/sprites/belt/forward_12.png new file mode 100644 index 00000000..a278e6f0 Binary files /dev/null and b/res_raw/sprites/belt/forward_12.png differ diff --git a/res_raw/sprites/belt/forward_13.png b/res_raw/sprites/belt/forward_13.png new file mode 100644 index 00000000..13630f42 Binary files /dev/null and b/res_raw/sprites/belt/forward_13.png differ diff --git a/res_raw/sprites/belt/forward_14.png b/res_raw/sprites/belt/forward_14.png new file mode 100644 index 00000000..1c6bdfb8 Binary files /dev/null and b/res_raw/sprites/belt/forward_14.png differ diff --git a/res_raw/sprites/belt/forward_15.png b/res_raw/sprites/belt/forward_15.png new file mode 100644 index 00000000..be3daa82 Binary files /dev/null and b/res_raw/sprites/belt/forward_15.png differ diff --git a/res_raw/sprites/belt/forward_16.png b/res_raw/sprites/belt/forward_16.png new file mode 100644 index 00000000..7b9c9dcf Binary files /dev/null and b/res_raw/sprites/belt/forward_16.png differ diff --git a/res_raw/sprites/belt/forward_17.png b/res_raw/sprites/belt/forward_17.png new file mode 100644 index 00000000..cc37d11a Binary files /dev/null and b/res_raw/sprites/belt/forward_17.png differ diff --git a/res_raw/sprites/belt/forward_18.png b/res_raw/sprites/belt/forward_18.png new file mode 100644 index 00000000..7a6460f3 Binary files /dev/null and b/res_raw/sprites/belt/forward_18.png differ diff --git a/res_raw/sprites/belt/forward_19.png b/res_raw/sprites/belt/forward_19.png new file mode 100644 index 00000000..c18e2773 Binary files /dev/null and b/res_raw/sprites/belt/forward_19.png differ diff --git a/res_raw/sprites/belt/forward_2.png b/res_raw/sprites/belt/forward_2.png index f8620703..5a621fbb 100644 Binary files a/res_raw/sprites/belt/forward_2.png and b/res_raw/sprites/belt/forward_2.png differ diff --git a/res_raw/sprites/belt/forward_20.png b/res_raw/sprites/belt/forward_20.png new file mode 100644 index 00000000..ac3f50db Binary files /dev/null and b/res_raw/sprites/belt/forward_20.png differ diff --git a/res_raw/sprites/belt/forward_21.png b/res_raw/sprites/belt/forward_21.png new file mode 100644 index 00000000..67d63a4a Binary files /dev/null and b/res_raw/sprites/belt/forward_21.png differ diff --git a/res_raw/sprites/belt/forward_22.png b/res_raw/sprites/belt/forward_22.png new file mode 100644 index 00000000..f20ec8d3 Binary files /dev/null and b/res_raw/sprites/belt/forward_22.png differ diff --git a/res_raw/sprites/belt/forward_23.png b/res_raw/sprites/belt/forward_23.png new file mode 100644 index 00000000..daa5d1d8 Binary files /dev/null and b/res_raw/sprites/belt/forward_23.png differ diff --git a/res_raw/sprites/belt/forward_24.png b/res_raw/sprites/belt/forward_24.png new file mode 100644 index 00000000..c21bc67d Binary files /dev/null and b/res_raw/sprites/belt/forward_24.png differ diff --git a/res_raw/sprites/belt/forward_25.png b/res_raw/sprites/belt/forward_25.png new file mode 100644 index 00000000..4e603e43 Binary files /dev/null and b/res_raw/sprites/belt/forward_25.png differ diff --git a/res_raw/sprites/belt/forward_26.png b/res_raw/sprites/belt/forward_26.png new file mode 100644 index 00000000..55ae0c96 Binary files /dev/null and b/res_raw/sprites/belt/forward_26.png differ diff --git a/res_raw/sprites/belt/forward_27.png b/res_raw/sprites/belt/forward_27.png new file mode 100644 index 00000000..816ac1c6 Binary files /dev/null and b/res_raw/sprites/belt/forward_27.png differ diff --git a/res_raw/sprites/belt/forward_3.png b/res_raw/sprites/belt/forward_3.png index 0c0647fa..cf2ef011 100644 Binary files a/res_raw/sprites/belt/forward_3.png and b/res_raw/sprites/belt/forward_3.png differ diff --git a/res_raw/sprites/belt/forward_4.png b/res_raw/sprites/belt/forward_4.png index 5b6f59c0..b06fb99f 100644 Binary files a/res_raw/sprites/belt/forward_4.png and b/res_raw/sprites/belt/forward_4.png differ diff --git a/res_raw/sprites/belt/forward_5.png b/res_raw/sprites/belt/forward_5.png index 850f14a8..79354fbb 100644 Binary files a/res_raw/sprites/belt/forward_5.png and b/res_raw/sprites/belt/forward_5.png differ diff --git a/res_raw/sprites/belt/forward_6.png b/res_raw/sprites/belt/forward_6.png new file mode 100644 index 00000000..3df44015 Binary files /dev/null and b/res_raw/sprites/belt/forward_6.png differ diff --git a/res_raw/sprites/belt/forward_7.png b/res_raw/sprites/belt/forward_7.png new file mode 100644 index 00000000..72251706 Binary files /dev/null and b/res_raw/sprites/belt/forward_7.png differ diff --git a/res_raw/sprites/belt/forward_8.png b/res_raw/sprites/belt/forward_8.png new file mode 100644 index 00000000..ad28047a Binary files /dev/null and b/res_raw/sprites/belt/forward_8.png differ diff --git a/res_raw/sprites/belt/forward_9.png b/res_raw/sprites/belt/forward_9.png new file mode 100644 index 00000000..daae565f Binary files /dev/null and b/res_raw/sprites/belt/forward_9.png differ diff --git a/res_raw/sprites/belt/generate_belt_sprites.js b/res_raw/sprites/belt/generate_belt_sprites.js new file mode 100644 index 00000000..f0bd4aa1 --- /dev/null +++ b/res_raw/sprites/belt/generate_belt_sprites.js @@ -0,0 +1,173 @@ +/** + * + * Run `yarn global add canvas` first + */ + +const { createCanvas, loadImage } = require("canvas"); +const fs = require("fs"); +const path = require("path"); +const { fileURLToPath } = require("url"); + +async function run() { + console.log("Running"); + + const fps = 28; + const dimensions = 126; + const beltBorder = 15.5; + + const borderColor = "#91949e"; + const fillColor = "#d2d4d9"; + const arrowColor = "#c0c2c7"; + + // Generate arrow sprite + + const arrowW = 40; + const arrowH = 20; + /** @type {HTMLCanvasElement} */ + const arrowSprite = createCanvas(arrowW, arrowH); + const arrowContext = arrowSprite.getContext("2d"); + + arrowContext.quality = "best"; + arrowContext.fillStyle = arrowColor; + arrowContext.clearRect(0, 0, arrowW, arrowH); + arrowContext.beginPath(); + arrowContext.moveTo(0, arrowH); + arrowContext.lineTo(arrowW / 2, 0); + arrowContext.lineTo(arrowW, arrowH); + arrowContext.closePath(); + arrowContext.fill(); + + // First, generate the forward belt + for (let i = 0; i < fps; ++i) { + /** @type {HTMLCanvasElement} */ + const canvas = createCanvas(dimensions, dimensions); + const context = canvas.getContext("2d"); + context.quality = "best"; + + const procentual = i / fps; + context.clearRect(0, 0, dimensions, dimensions); + + context.fillStyle = fillColor; + context.strokeStyle = borderColor; + context.lineWidth = 3; + + context.beginPath(); + context.rect(beltBorder, -10, dimensions - 2 * beltBorder, dimensions + 20); + context.fill(); + context.stroke(); + + const spacingBetweenArrows = (dimensions - 3 * arrowH) / 3; + const spacingTotal = spacingBetweenArrows + arrowH; + + for (let k = 0; k < 5; ++k) { + let y = dimensions - arrowH - (k - 1) * spacingTotal - procentual * spacingTotal; + context.drawImage(arrowSprite, dimensions / 2 - arrowW / 2, y); + } + + const out = fs.createWriteStream(path.join(__dirname, "forward_" + i + ".png")); + const stream = canvas.createPNGStream(); + stream.pipe(out); + } + + // Generate left and right side belt + for (let i = 0; i < fps; ++i) { + /** @type {HTMLCanvasElement} */ + const canvas = createCanvas(dimensions, dimensions); + const context = canvas.getContext("2d"); + context.quality = "best"; + + const procentual = i / fps; + const innerRadius = beltBorder; + context.clearRect(0, 0, dimensions, dimensions); + + context.fillStyle = fillColor; + context.strokeStyle = borderColor; + context.lineWidth = 3; + + context.beginPath(); + context.moveTo(beltBorder, dimensions + 10); + context.lineTo(beltBorder, dimensions - innerRadius); + + const steps = 256; + + const outerRadius = dimensions - 2 * beltBorder; + + const originX = dimensions - innerRadius; + const originY = dimensions - innerRadius; + + const sqrt = x => Math.pow(Math.abs(x), 0.975) * Math.sign(x); + + for (let k = 0; k <= steps; ++k) { + const pct = k / steps; + const angleRad = Math.PI + pct * Math.PI * 0.5; + const offX = originX + sqrt(Math.cos(angleRad)) * outerRadius; + const offY = originY + sqrt(Math.sin(angleRad)) * outerRadius; + + context.lineTo(offX, offY); + } + + context.lineTo(dimensions + 10, beltBorder); + context.lineTo(dimensions + 10, dimensions - beltBorder); + context.lineTo(dimensions, dimensions - beltBorder); + + for (let k = 0; k <= steps; ++k) { + const pct = 1 - k / steps; + const angleRad = Math.PI + pct * Math.PI * 0.5; + const offX = dimensions + Math.cos(angleRad) * innerRadius; + const offY = dimensions + Math.sin(angleRad) * innerRadius; + + context.lineTo(offX, offY); + } + + context.lineTo(dimensions - beltBorder, dimensions + 10); + + context.closePath(); + context.fill(); + context.stroke(); + + // Arrows + const rotationalRadius = dimensions / 2 - arrowH / 2 + 0.5; + + const circumfence = (rotationalRadius * Math.PI * 2) / 4; + console.log("Circumfence:", circumfence, "px"); + + const remainingSpace = circumfence - 3 * arrowH + arrowH; + console.log("Remainig:", remainingSpace); + const spacing = remainingSpace / 3 + arrowH; + + console.log("Spacing: ", spacing); + const angleSpacing = ((spacing / circumfence) * Math.PI) / 2; + + for (let i = 0; i < 5; ++i) { + let angleRad = Math.PI + procentual * angleSpacing + (i - 1) * angleSpacing; + const offX = dimensions - arrowH / 2 + Math.cos(angleRad * 0.995) * rotationalRadius; + const offY = dimensions - arrowH / 2 + Math.sin(angleRad * 0.995) * rotationalRadius; + + angleRad = Math.max(Math.PI, Math.min(1.5 * Math.PI, angleRad)); + + context.save(); + context.translate(offX, offY); + context.rotate(angleRad + Math.PI); + context.drawImage(arrowSprite, -arrowW / 2, -arrowH / 2); + context.restore(); + } + + /** @type {HTMLCanvasElement} */ + const flippedCanvas = createCanvas(dimensions, dimensions); + const flippedContext = flippedCanvas.getContext("2d"); + flippedContext.quality = "best"; + flippedContext.clearRect(0, 0, dimensions, dimensions); + flippedContext.scale(-1, 1); + flippedContext.drawImage(canvas, -dimensions, 0, dimensions, dimensions); + + const out = fs.createWriteStream(path.join(__dirname, "right_" + i + ".png")); + const stream = canvas.createPNGStream(); + stream.pipe(out); + + const outLeft = fs.createWriteStream(path.join(__dirname, "left_" + i + ".png")); + const streamLeft = flippedCanvas.createPNGStream(); + streamLeft.pipe(outLeft); + } +} + +run(); diff --git a/res_raw/sprites/belt/left_0.png b/res_raw/sprites/belt/left_0.png index 822d922d..7da4c390 100644 Binary files a/res_raw/sprites/belt/left_0.png and b/res_raw/sprites/belt/left_0.png differ diff --git a/res_raw/sprites/belt/left_1.png b/res_raw/sprites/belt/left_1.png index 24f77c4a..fa446ce4 100644 Binary files a/res_raw/sprites/belt/left_1.png and b/res_raw/sprites/belt/left_1.png differ diff --git a/res_raw/sprites/belt/left_10.png b/res_raw/sprites/belt/left_10.png new file mode 100644 index 00000000..260a4c23 Binary files /dev/null and b/res_raw/sprites/belt/left_10.png differ diff --git a/res_raw/sprites/belt/left_11.png b/res_raw/sprites/belt/left_11.png new file mode 100644 index 00000000..d0d70ab1 Binary files /dev/null and b/res_raw/sprites/belt/left_11.png differ diff --git a/res_raw/sprites/belt/left_12.png b/res_raw/sprites/belt/left_12.png new file mode 100644 index 00000000..3f916501 Binary files /dev/null and b/res_raw/sprites/belt/left_12.png differ diff --git a/res_raw/sprites/belt/left_13.png b/res_raw/sprites/belt/left_13.png new file mode 100644 index 00000000..71d9a634 Binary files /dev/null and b/res_raw/sprites/belt/left_13.png differ diff --git a/res_raw/sprites/belt/left_14.png b/res_raw/sprites/belt/left_14.png new file mode 100644 index 00000000..134b90af Binary files /dev/null and b/res_raw/sprites/belt/left_14.png differ diff --git a/res_raw/sprites/belt/left_15.png b/res_raw/sprites/belt/left_15.png new file mode 100644 index 00000000..623069a1 Binary files /dev/null and b/res_raw/sprites/belt/left_15.png differ diff --git a/res_raw/sprites/belt/left_16.png b/res_raw/sprites/belt/left_16.png new file mode 100644 index 00000000..14b18b45 Binary files /dev/null and b/res_raw/sprites/belt/left_16.png differ diff --git a/res_raw/sprites/belt/left_17.png b/res_raw/sprites/belt/left_17.png new file mode 100644 index 00000000..5aa84e5c Binary files /dev/null and b/res_raw/sprites/belt/left_17.png differ diff --git a/res_raw/sprites/belt/left_18.png b/res_raw/sprites/belt/left_18.png new file mode 100644 index 00000000..0fe1dedd Binary files /dev/null and b/res_raw/sprites/belt/left_18.png differ diff --git a/res_raw/sprites/belt/left_19.png b/res_raw/sprites/belt/left_19.png new file mode 100644 index 00000000..46e1b2b3 Binary files /dev/null and b/res_raw/sprites/belt/left_19.png differ diff --git a/res_raw/sprites/belt/left_2.png b/res_raw/sprites/belt/left_2.png index e8473cc7..9a8d15c0 100644 Binary files a/res_raw/sprites/belt/left_2.png and b/res_raw/sprites/belt/left_2.png differ diff --git a/res_raw/sprites/belt/left_20.png b/res_raw/sprites/belt/left_20.png new file mode 100644 index 00000000..1d6dd020 Binary files /dev/null and b/res_raw/sprites/belt/left_20.png differ diff --git a/res_raw/sprites/belt/left_21.png b/res_raw/sprites/belt/left_21.png new file mode 100644 index 00000000..413afb3c Binary files /dev/null and b/res_raw/sprites/belt/left_21.png differ diff --git a/res_raw/sprites/belt/left_22.png b/res_raw/sprites/belt/left_22.png new file mode 100644 index 00000000..c56c9607 Binary files /dev/null and b/res_raw/sprites/belt/left_22.png differ diff --git a/res_raw/sprites/belt/left_23.png b/res_raw/sprites/belt/left_23.png new file mode 100644 index 00000000..22c7e9d1 Binary files /dev/null and b/res_raw/sprites/belt/left_23.png differ diff --git a/res_raw/sprites/belt/left_24.png b/res_raw/sprites/belt/left_24.png new file mode 100644 index 00000000..1c15838a Binary files /dev/null and b/res_raw/sprites/belt/left_24.png differ diff --git a/res_raw/sprites/belt/left_25.png b/res_raw/sprites/belt/left_25.png new file mode 100644 index 00000000..20120842 Binary files /dev/null and b/res_raw/sprites/belt/left_25.png differ diff --git a/res_raw/sprites/belt/left_26.png b/res_raw/sprites/belt/left_26.png new file mode 100644 index 00000000..1d4de05f Binary files /dev/null and b/res_raw/sprites/belt/left_26.png differ diff --git a/res_raw/sprites/belt/left_27.png b/res_raw/sprites/belt/left_27.png new file mode 100644 index 00000000..ba0d699a Binary files /dev/null and b/res_raw/sprites/belt/left_27.png differ diff --git a/res_raw/sprites/belt/left_3.png b/res_raw/sprites/belt/left_3.png index d0984a31..7fc8c6fc 100644 Binary files a/res_raw/sprites/belt/left_3.png and b/res_raw/sprites/belt/left_3.png differ diff --git a/res_raw/sprites/belt/left_4.png b/res_raw/sprites/belt/left_4.png index 068c2c25..e8da79fd 100644 Binary files a/res_raw/sprites/belt/left_4.png and b/res_raw/sprites/belt/left_4.png differ diff --git a/res_raw/sprites/belt/left_5.png b/res_raw/sprites/belt/left_5.png index 52c53bcb..1a26dc72 100644 Binary files a/res_raw/sprites/belt/left_5.png and b/res_raw/sprites/belt/left_5.png differ diff --git a/res_raw/sprites/belt/left_6.png b/res_raw/sprites/belt/left_6.png new file mode 100644 index 00000000..c2322d45 Binary files /dev/null and b/res_raw/sprites/belt/left_6.png differ diff --git a/res_raw/sprites/belt/left_7.png b/res_raw/sprites/belt/left_7.png new file mode 100644 index 00000000..a85a31fc Binary files /dev/null and b/res_raw/sprites/belt/left_7.png differ diff --git a/res_raw/sprites/belt/left_8.png b/res_raw/sprites/belt/left_8.png new file mode 100644 index 00000000..9ff9945b Binary files /dev/null and b/res_raw/sprites/belt/left_8.png differ diff --git a/res_raw/sprites/belt/left_9.png b/res_raw/sprites/belt/left_9.png new file mode 100644 index 00000000..bfe4360e Binary files /dev/null and b/res_raw/sprites/belt/left_9.png differ diff --git a/res_raw/sprites/belt/package.json b/res_raw/sprites/belt/package.json new file mode 100644 index 00000000..eba97da2 --- /dev/null +++ b/res_raw/sprites/belt/package.json @@ -0,0 +1,12 @@ +{ + "name": "belt", + "version": "1.0.0", + "main": "index.js", + "private": "true", + "devDependencies": { + "canvas": "^2.6.1" + }, + "scripts": { + "generate": "node generate_belt_sprites.js" + } +} diff --git a/res_raw/sprites/belt/right_0.png b/res_raw/sprites/belt/right_0.png index cdebc96f..fca35eab 100644 Binary files a/res_raw/sprites/belt/right_0.png and b/res_raw/sprites/belt/right_0.png differ diff --git a/res_raw/sprites/belt/right_1.png b/res_raw/sprites/belt/right_1.png index 4582b007..101578e9 100644 Binary files a/res_raw/sprites/belt/right_1.png and b/res_raw/sprites/belt/right_1.png differ diff --git a/res_raw/sprites/belt/right_10.png b/res_raw/sprites/belt/right_10.png new file mode 100644 index 00000000..cd733017 Binary files /dev/null and b/res_raw/sprites/belt/right_10.png differ diff --git a/res_raw/sprites/belt/right_11.png b/res_raw/sprites/belt/right_11.png new file mode 100644 index 00000000..5d082ecc Binary files /dev/null and b/res_raw/sprites/belt/right_11.png differ diff --git a/res_raw/sprites/belt/right_12.png b/res_raw/sprites/belt/right_12.png new file mode 100644 index 00000000..3c7f08bb Binary files /dev/null and b/res_raw/sprites/belt/right_12.png differ diff --git a/res_raw/sprites/belt/right_13.png b/res_raw/sprites/belt/right_13.png new file mode 100644 index 00000000..71364d48 Binary files /dev/null and b/res_raw/sprites/belt/right_13.png differ diff --git a/res_raw/sprites/belt/right_14.png b/res_raw/sprites/belt/right_14.png new file mode 100644 index 00000000..cf5df0a4 Binary files /dev/null and b/res_raw/sprites/belt/right_14.png differ diff --git a/res_raw/sprites/belt/right_15.png b/res_raw/sprites/belt/right_15.png new file mode 100644 index 00000000..1292ec67 Binary files /dev/null and b/res_raw/sprites/belt/right_15.png differ diff --git a/res_raw/sprites/belt/right_16.png b/res_raw/sprites/belt/right_16.png new file mode 100644 index 00000000..4dcc2c5f Binary files /dev/null and b/res_raw/sprites/belt/right_16.png differ diff --git a/res_raw/sprites/belt/right_17.png b/res_raw/sprites/belt/right_17.png new file mode 100644 index 00000000..489f0e54 Binary files /dev/null and b/res_raw/sprites/belt/right_17.png differ diff --git a/res_raw/sprites/belt/right_18.png b/res_raw/sprites/belt/right_18.png new file mode 100644 index 00000000..208f402b Binary files /dev/null and b/res_raw/sprites/belt/right_18.png differ diff --git a/res_raw/sprites/belt/right_19.png b/res_raw/sprites/belt/right_19.png new file mode 100644 index 00000000..5e4e376b Binary files /dev/null and b/res_raw/sprites/belt/right_19.png differ diff --git a/res_raw/sprites/belt/right_2.png b/res_raw/sprites/belt/right_2.png index 79b30f46..c9affce1 100644 Binary files a/res_raw/sprites/belt/right_2.png and b/res_raw/sprites/belt/right_2.png differ diff --git a/res_raw/sprites/belt/right_20.png b/res_raw/sprites/belt/right_20.png new file mode 100644 index 00000000..77a4f43b Binary files /dev/null and b/res_raw/sprites/belt/right_20.png differ diff --git a/res_raw/sprites/belt/right_21.png b/res_raw/sprites/belt/right_21.png new file mode 100644 index 00000000..ca1d0f5f Binary files /dev/null and b/res_raw/sprites/belt/right_21.png differ diff --git a/res_raw/sprites/belt/right_22.png b/res_raw/sprites/belt/right_22.png new file mode 100644 index 00000000..d07bf72d Binary files /dev/null and b/res_raw/sprites/belt/right_22.png differ diff --git a/res_raw/sprites/belt/right_23.png b/res_raw/sprites/belt/right_23.png new file mode 100644 index 00000000..babfca3f Binary files /dev/null and b/res_raw/sprites/belt/right_23.png differ diff --git a/res_raw/sprites/belt/right_24.png b/res_raw/sprites/belt/right_24.png new file mode 100644 index 00000000..1c614c85 Binary files /dev/null and b/res_raw/sprites/belt/right_24.png differ diff --git a/res_raw/sprites/belt/right_25.png b/res_raw/sprites/belt/right_25.png new file mode 100644 index 00000000..d72a8615 Binary files /dev/null and b/res_raw/sprites/belt/right_25.png differ diff --git a/res_raw/sprites/belt/right_26.png b/res_raw/sprites/belt/right_26.png new file mode 100644 index 00000000..ed37636f Binary files /dev/null and b/res_raw/sprites/belt/right_26.png differ diff --git a/res_raw/sprites/belt/right_27.png b/res_raw/sprites/belt/right_27.png new file mode 100644 index 00000000..fe9ffc10 Binary files /dev/null and b/res_raw/sprites/belt/right_27.png differ diff --git a/res_raw/sprites/belt/right_3.png b/res_raw/sprites/belt/right_3.png index 7e55e829..feb7101b 100644 Binary files a/res_raw/sprites/belt/right_3.png and b/res_raw/sprites/belt/right_3.png differ diff --git a/res_raw/sprites/belt/right_4.png b/res_raw/sprites/belt/right_4.png index 9862d108..22c885a6 100644 Binary files a/res_raw/sprites/belt/right_4.png and b/res_raw/sprites/belt/right_4.png differ diff --git a/res_raw/sprites/belt/right_5.png b/res_raw/sprites/belt/right_5.png index f735403a..27bb27aa 100644 Binary files a/res_raw/sprites/belt/right_5.png and b/res_raw/sprites/belt/right_5.png differ diff --git a/res_raw/sprites/belt/right_6.png b/res_raw/sprites/belt/right_6.png new file mode 100644 index 00000000..5ca871b7 Binary files /dev/null and b/res_raw/sprites/belt/right_6.png differ diff --git a/res_raw/sprites/belt/right_7.png b/res_raw/sprites/belt/right_7.png new file mode 100644 index 00000000..a9cde450 Binary files /dev/null and b/res_raw/sprites/belt/right_7.png differ diff --git a/res_raw/sprites/belt/right_8.png b/res_raw/sprites/belt/right_8.png new file mode 100644 index 00000000..f09195fe Binary files /dev/null and b/res_raw/sprites/belt/right_8.png differ diff --git a/res_raw/sprites/belt/right_9.png b/res_raw/sprites/belt/right_9.png new file mode 100644 index 00000000..b6ca38c1 Binary files /dev/null and b/res_raw/sprites/belt/right_9.png differ diff --git a/res_raw/sprites/belt/yarn.lock b/res_raw/sprites/belt/yarn.lock new file mode 100644 index 00000000..4011ebc0 --- /dev/null +++ b/res_raw/sprites/belt/yarn.lock @@ -0,0 +1,514 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +canvas@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.6.1.tgz#0d087dd4d60f5a5a9efa202757270abea8bef89e" + integrity sha512-S98rKsPcuhfTcYbtF53UIJhcbgIAK533d1kJKMwsMwAIFgfd58MOyxRud3kktlzWiEkFliaJtvyZCBtud/XVEA== + dependencies: + nan "^2.14.0" + node-pre-gyp "^0.11.0" + simple-get "^3.0.3" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-walk@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nan@^2.14.0: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + +needle@^2.2.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.5.0.tgz#e6fc4b3cc6c25caed7554bd613a5cf0bac8c31c0" + integrity sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + +node-pre-gyp@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054" + integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + +npm-bundled@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-packlist@^1.1.6: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +once@^1.3.0, once@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^2.0.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +safe-buffer@^5.1.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +semver@^5.3.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +signal-exit@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + +simple-get@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" + integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +tar@^4: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yallist@^3.0.0, yallist@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== diff --git a/res_raw/sprites/blueprints/belt_left.png b/res_raw/sprites/blueprints/belt_left.png index 476a17e2..594bb203 100644 Binary files a/res_raw/sprites/blueprints/belt_left.png and b/res_raw/sprites/blueprints/belt_left.png differ diff --git a/res_raw/sprites/blueprints/belt_right.png b/res_raw/sprites/blueprints/belt_right.png index 77ba6a33..9c33404b 100644 Binary files a/res_raw/sprites/blueprints/belt_right.png and b/res_raw/sprites/blueprints/belt_right.png differ diff --git a/res_raw/sprites/blueprints/belt_top.png b/res_raw/sprites/blueprints/belt_top.png index d8532b64..881c443a 100644 Binary files a/res_raw/sprites/blueprints/belt_top.png and b/res_raw/sprites/blueprints/belt_top.png differ diff --git a/res_raw/sprites/blueprints/energy_generator.png b/res_raw/sprites/blueprints/energy_generator.png new file mode 100644 index 00000000..e1534b57 Binary files /dev/null and b/res_raw/sprites/blueprints/energy_generator.png differ diff --git a/res_raw/sprites/buildings/belt_left.png b/res_raw/sprites/buildings/belt_left.png index 822d922d..60bebd29 100644 Binary files a/res_raw/sprites/buildings/belt_left.png and b/res_raw/sprites/buildings/belt_left.png differ diff --git a/res_raw/sprites/buildings/belt_right.png b/res_raw/sprites/buildings/belt_right.png index cdebc96f..547387b4 100644 Binary files a/res_raw/sprites/buildings/belt_right.png and b/res_raw/sprites/buildings/belt_right.png differ diff --git a/res_raw/sprites/buildings/belt_top.png b/res_raw/sprites/buildings/belt_top.png index def37d7d..cf5b20d7 100644 Binary files a/res_raw/sprites/buildings/belt_top.png and b/res_raw/sprites/buildings/belt_top.png differ diff --git a/res_raw/sprites/buildings/energy_generator.png b/res_raw/sprites/buildings/energy_generator.png new file mode 100644 index 00000000..e06b86ea Binary files /dev/null and b/res_raw/sprites/buildings/energy_generator.png differ diff --git a/src/css/icons.scss b/src/css/icons.scss index 2128fde3..bfc67713 100644 --- a/src/css/icons.scss +++ b/src/css/icons.scss @@ -1,4 +1,5 @@ -$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt; +$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, + energy_generator; @each $building in $buildings { [data-icon="building_icons/#{$building}.png"] { @@ -27,8 +28,8 @@ $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, zh-CN, nb, mt-MT, ar, nl, vi, th, - hu, pl, ja, kor, no, pt-PT; +$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 { [data-languageicon="#{$language}"] { diff --git a/src/css/ingame_hud/building_placer.scss b/src/css/ingame_hud/building_placer.scss index e63868ab..8ca53655 100644 --- a/src/css/ingame_hud/building_placer.scss +++ b/src/css/ingame_hud/building_placer.scss @@ -119,6 +119,9 @@ @include S(grid-gap, 5px); .variant { + pointer-events: all; + cursor: pointer; + grid-row: 2 / 3; @include S(border-radius, $globalBorderRadius); background: rgba($ingameHudBg, 0.3); @@ -130,6 +133,13 @@ @include S(padding, 3px); @include S(grid-gap, 10px); + transition: background-color 0.12s ease-in-out; + + &:hover:not(.active) { + background: rgba($colorBlueBright, 0.8); + opacity: 1; + } + &.active { opacity: 1; background-color: rgba($colorBlueBright, 0.8); diff --git a/src/css/ingame_hud/color_blind_helper.scss b/src/css/ingame_hud/color_blind_helper.scss new file mode 100644 index 00000000..027b781b --- /dev/null +++ b/src/css/ingame_hud/color_blind_helper.scss @@ -0,0 +1,18 @@ +#ingame_HUD_ColorBlindBelowTileHelper { + position: absolute; + + @include SuperSmallText; + color: #fff; + background: $ingameHudBg; + @include S(padding, 5px); + @include S(top, 20px); + left: 50%; + transform: translateX(-50%); + text-transform: uppercase; + + &:not(.visible) { + display: none; + } + + @include DarkThemeInvert; +} diff --git a/src/css/ingame_hud/pinned_shapes.scss b/src/css/ingame_hud/pinned_shapes.scss index 68cf7e16..60e9159e 100644 --- a/src/css/ingame_hud/pinned_shapes.scss +++ b/src/css/ingame_hud/pinned_shapes.scss @@ -72,6 +72,24 @@ grid-row: 1 / 2; } + > .infoButton { + @include S(width, 8px); + @include S(height, 8px); + background: uiResource("icons/info_button.png") center center / 95% no-repeat; + position: absolute; + opacity: 0.7; + @include S(top, 13px); + @include S(left, -7px); + @include DarkThemeInvert; + @include IncreasedClickArea(2px); + transition: opacity 0.12s ease-in-out; + z-index: 100; + + &:hover { + opacity: 0.8; + } + } + &.goal, &.blueprint { .amountLabel::after { diff --git a/src/css/ingame_hud/shape_viewer.scss b/src/css/ingame_hud/shape_viewer.scss new file mode 100644 index 00000000..65491a5a --- /dev/null +++ b/src/css/ingame_hud/shape_viewer.scss @@ -0,0 +1,161 @@ +#ingame_HUD_ShapeViewer { + $dims: 170px; + + .content { + display: flex; + @include S(width, $dims); + width: 100%; + flex-direction: column; + overflow-x: hidden; + + &[data-layers="3"], + &[data-layers="4"] { + @include S(width, 2 * $dims); + .renderArea { + display: grid; + grid-template-columns: 1fr 1fr; + @include S(grid-row-gap, 15px); + } + } + + .renderArea { + display: grid; + width: 100%; + @include S(grid-row-gap, 10px); + align-items: center; + justify-items: center; + } + + .infoArea { + align-self: flex-end; + @include S(margin-top, 10px); + display: flex; + flex-direction: column; + overflow: hidden; + + button { + @include S(margin, 0); + @include PlainText; + } + } + + .seperator { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + } + + .layer { + position: relative; + background: #eee; + + @include DarkThemeOverride { + background: rgba(0, 10, 20, 0.2); + } + @include S(width, 150px); + @include S(height, 100px); + display: flex; + align-items: center; + justify-content: center; + + > canvas { + @include S(width, 50px); + @include S(height, 50px); + } + + .quad { + position: absolute; + width: 50%; + height: 50%; + display: flex; + justify-content: center; + align-items: center; + box-sizing: border-box; + + $arrowDims: 23px; + $spacing: 9px; + @include S(padding, 6px); + + .colorLabel { + text-transform: uppercase; + @include SuperSmallText; + @include S(font-size, 9px); + } + + .emptyLabel { + text-transform: uppercase; + @include SuperSmallText; + @include S(font-size, 9px); + } + + &::after { + content: " "; + background: rgba(0, 10, 20, 0.5); + @include S(width, $arrowDims); + @include S(height, 1px); + position: absolute; + transform: rotate(45deg); + transform-origin: 50% 50%; + } + @include DarkThemeOverride { + &::after { + background: rgba(255, 255, 255, 0.5); + } + } + + &.quad-0 { + right: 0; + top: 0; + align-items: flex-start; + justify-content: flex-end; + + &::after { + @include S(left, $spacing); + @include S(bottom, $arrowDims / 2 + $spacing); + transform: rotate(-45deg); + } + } + &.quad-1 { + bottom: 0; + right: 0; + + align-items: flex-end; + justify-content: flex-end; + + &::after { + @include S(left, $spacing); + @include S(top, $arrowDims / 2 + $spacing); + transform: rotate(45deg); + } + } + &.quad-2 { + bottom: 0; + left: 0; + + align-items: flex-end; + justify-content: flex-start; + + &::after { + @include S(right, $spacing); + @include S(top, $arrowDims / 2 + $spacing); + transform: rotate(135deg); + } + } + &.quad-3 { + top: 0; + left: 0; + + align-items: flex-start; + justify-content: flex-start; + + &::after { + @include S(right, $spacing); + @include S(bottom, $arrowDims / 2 + $spacing); + transform: rotate(225deg); + } + } + } + } + } +} diff --git a/src/css/ingame_hud/shop.scss b/src/css/ingame_hud/shop.scss index 26f5d759..d8cc8a86 100644 --- a/src/css/ingame_hud/shop.scss +++ b/src/css/ingame_hud/shop.scss @@ -195,6 +195,25 @@ } } + button.showInfo { + @include S(width, 11px); + @include S(height, 11px); + background: uiResource("icons/info_button.png") center center / 95% no-repeat; + position: absolute; + @include S(top, 17px); + @include S(right, 2.5px); + opacity: 0.5; + cursor: pointer; + pointer-events: all; + @include IncreasedClickArea(5px); + transition: opacity 0.12s ease-in-out; + @include DarkThemeInvert; + + &:hover { + opacity: 0.6; + } + } + canvas { @include S(width, 40px); @include S(height, 40px); @@ -241,7 +260,7 @@ &.complete { background-color: $colorGreenBright; - + @include DarkThemeOverride { background-color: $colorGreenBright; } diff --git a/src/css/main.scss b/src/css/main.scss index 178f398b..6b758e80 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -49,6 +49,8 @@ @import "ingame_hud/blueprint_placer"; @import "ingame_hud/waypoints"; @import "ingame_hud/interactive_tutorial"; +@import "ingame_hud/color_blind_helper"; +@import "ingame_hud/shape_viewer"; // prettier-ignore $elements: @@ -74,6 +76,7 @@ ingame_HUD_buildings_toolbar, ingame_HUD_BlueprintPlacer, ingame_HUD_Waypoints_Hint, ingame_HUD_Watermark, +ingame_HUD_ColorBlindBelowTileHelper, // Overlays ingame_HUD_BetaOverlay, @@ -81,6 +84,7 @@ ingame_HUD_BetaOverlay, // Dialogs ingame_HUD_Shop, ingame_HUD_Statistics, +ingame_HUD_ShapeViewer, ingame_HUD_UnlockNotification, ingame_HUD_SettingsMenu, ingame_HUD_ModalDialogs; diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss index fa9d430c..be3bcce4 100644 --- a/src/css/states/main_menu.scss +++ b/src/css/states/main_menu.scss @@ -224,6 +224,12 @@ width: 100%; box-sizing: border-box; + .buttons { + display: flex; + flex-direction: column; + align-items: center; + } + .browserWarning { @include S(margin-bottom, 10px); background-color: $colorRedBright; @@ -337,33 +343,42 @@ } .footer { - display: flex; + display: grid; flex-grow: 1; justify-content: center; align-items: flex-end; width: 100%; + grid-template-columns: auto auto auto 1fr; + @include S(padding, 10px); + box-sizing: border-box; + @include S(grid-gap, 5px); .author { flex-grow: 1; text-align: right; - @include S(padding-right, 10px); + @include PlainText; + color: #888a8f; + a { + color: #333438; + } } @include S(padding, 15px); - > a { + + > .boxLink { display: grid; align-items: center; grid-template-columns: 1fr auto; justify-content: center; - background: #fafafa; + background: #fdfdfd; @include S(padding, 5px); @include S(padding-left, 10px); @include S(border-radius, $globalBorderRadius); - @include S(margin-left, 10px); @include SuperSmallText(); font-weight: bold; + box-sizing: border-box; text-transform: uppercase; color: #616266; @@ -371,19 +386,11 @@ transition-property: background-color, transform; pointer-events: all; @include S(width, 120px); - @include S(height, 50px); + @include S(height, 60px); + cursor: pointer; &:hover { background-color: #fff; - transform: scale(1.01); - } - - &:not(.boxLink) { - align-self: flex-end; - justify-self: flex-end; - height: unset; - width: unset; - @include S(padding, 3px); } .thirdpartyLogo { @@ -400,6 +407,49 @@ } } } + + > .sidelinks { + display: grid; + align-items: flex-start; + justify-content: flex-start; + grid-template-rows: 1fr 1fr 1fr; + @include S(grid-gap, 2px); + @include S(height, 60px); + + > a { + color: #616266; + background: #fdfdfd; + height: 100%; + + &:hover { + background-color: #fff; + } + @include SuperSmallText; + text-transform: uppercase; + width: 100%; + @include S(padding, 2px, 10px); + display: flex; + align-items: center; + justify-content: flex-start; + + @include S(padding-left, 25px); + box-sizing: border-box; + font-weight: bold; + background-position: #{D(5px)} center; + background-size: #{D(12px)}; + background-repeat: no-repeat; + + &.redditLink { + background-image: uiResource("main_menu/reddit.svg"); + } + &.changelog { + background-image: uiResource("main_menu/changelog.svg"); + } + &.helpTranslate { + background-image: uiResource("main_menu/translate.svg"); + } + } + } } @include DarkThemeOverride { @@ -423,9 +473,14 @@ } .footer { - > a { - background: darken($darkModeGameBackground, 10); + > a, + .sidelinks > a { + background-color: darken($darkModeGameBackground, 10); color: #eee; + + &:hover { + background-color: darken($darkModeGameBackground, 8); + } } .author { diff --git a/src/js/application.js b/src/js/application.js index ee913a3f..f08b467e 100644 --- a/src/js/application.js +++ b/src/js/application.js @@ -33,6 +33,7 @@ import { MainMenuState } from "./states/main_menu"; import { MobileWarningState } from "./states/mobile_warning"; import { PreloadState } from "./states/preload"; import { SettingsState } from "./states/settings"; +import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; const logger = createLogger("application"); @@ -130,8 +131,7 @@ export class Application { this.adProvider = new NoAdProvider(this); this.sound = new SoundImplBrowser(this); this.analytics = new GoogleAnalyticsImpl(this); - // this.gameAnalytics = new ShapezGameAnalytics(this); - this.gameAnalytics = new NoGameAnalytics(this); + this.gameAnalytics = new ShapezGameAnalytics(this); } /** diff --git a/src/js/changelog.js b/src/js/changelog.js index fa41760b..29b5a28d 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -1,4 +1,40 @@ export const CHANGELOG = [ + { + version: "1.1.18", + date: "26.06.2020", + entries: [ + "Huge belt performance improvements - up to 50% increase", + "Preparations for the wires update", + "Update belt placement performance on huge factories (by Phlosioneer)", + "Allow clicking on variants to select them", + "Allow clicking 'Q' over a shape or color patch to automatically select the miner building (by Gerdon262)", + "Add 'copy key' button to shape viewer", + "Fix deconstruct sound being played when right clicking hub", + "Add setting (on by default) to store the last used rotation per building instead of globally storing it (by Magos)", + "Add more FPS to the belt animation", + "Added chinese (traditional) translation", + "Updated translations", + ], + }, + { + version: "1.1.17", + date: "22.06.2020", + entries: [ + "Color blind mode! You can now activate it in the settings and it will show you which color is below your cursor (Either resource or on the belt)", + "Add info buttons to all shapes so you can figure out how they are built! (And also, which colors they have)", + "Allow configuring autosave interval and disabling it in the settings", + "The smart-tunnel placement has been reworked to properly replace belts. Thus the setting has been turned on again by default", + "The soundtrack now has a higher quality on the standalone version than the web version", + "Add setting to disable cut/delete warnings (by hexy)", + "Fix bug where belts in blueprints don't orient correctly (by hexy)", + "Fix camera moving weird after dragging and holding (by hexy)", + "Fix keybinding for pipette showing while pasting blueprints", + "Improve visibility of shape background in dark mode", + "Added sound when destroying a building", + "Added swedish translation", + "Update tutorial image for tier 2 tunnels to explain mix/match (by jimmyshadow1)", + ], + }, { version: "1.1.16", date: "21.06.2020", diff --git a/src/js/core/config.js b/src/js/core/config.js index aad3d245..0018b746 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -9,7 +9,7 @@ export const IS_DEBUG = export const IS_DEMO = queryParamOptions.fullVersion ? false - : (G_IS_PROD && !G_IS_STANDALONE) || + : (!G_IS_DEV && !G_IS_STANDALONE) || (typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0); export const SUPPORT_TOUCH = false; @@ -19,6 +19,7 @@ const smoothCanvas = true; export const THIRDPARTY_URLS = { discord: "https://discord.gg/HN7EVzV", github: "https://github.com/tobspr/shapez.io", + reddit: "https://www.reddit.com/r/shapezio", standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/", }; @@ -50,7 +51,7 @@ export const globalConfig = { // Belt speeds // NOTICE: Update webpack.production.config too! beltSpeedItemsPerSecond: 2, - itemSpacingOnBelts: 0.8, + itemSpacingOnBelts: 0.63, minerSpeedItemsPerSecond: 0, // COMPUTED undergroundBeltMaxTilesByTier: [5, 8], diff --git a/src/js/core/modal_dialog_forms.js b/src/js/core/modal_dialog_forms.js index 4d1c9f97..1ded9a8b 100644 --- a/src/js/core/modal_dialog_forms.js +++ b/src/js/core/modal_dialog_forms.js @@ -19,7 +19,7 @@ export class FormElement { abstract; } - focus(parent) {} + focus() {} isValid() { return true; diff --git a/src/js/core/polyfills.js b/src/js/core/polyfills.js index e5efca1d..145b4c82 100644 --- a/src/js/core/polyfills.js +++ b/src/js/core/polyfills.js @@ -72,6 +72,7 @@ function objectPolyfills() { } if (!Object.entries) { + // @ts-ignore Object.entries = function entries(O) { return reduce( keys(O), diff --git a/src/js/core/rectangle.js b/src/js/core/rectangle.js index bf19a4ab..79136b9f 100644 --- a/src/js/core/rectangle.js +++ b/src/js/core/rectangle.js @@ -46,6 +46,7 @@ export class Rectangle { } /** + * Returns if a intersects b * @param {Rectangle} a * @param {Rectangle} b */ @@ -74,7 +75,21 @@ export class Rectangle { return new Rectangle(minX, minY, maxX - minX, maxY - minY); } - // Ensures the rectangle contains the given square + /** + * Copies this instance + * @returns {Rectangle} + */ + clone() { + return new Rectangle(this.x, this.y, this.w, this.h); + } + + /** + * Ensures the rectangle contains the given square + * @param {number} centerX + * @param {number} centerY + * @param {number} halfWidth + * @param {number} halfHeight + */ extendBySquare(centerX, centerY, halfWidth, halfHeight) { if (this.isEmpty()) { // Just assign values since this rectangle is empty @@ -90,10 +105,19 @@ export class Rectangle { } } + /** + * Returns if this rectangle is empty + * @returns {boolean} + */ isEmpty() { return epsilonCompare(this.w * this.h, 0); } + /** + * Returns if this rectangle is equal to the other while taking an epsilon into account + * @param {Rectangle} other + * @param {number} epsilon + */ equalsEpsilon(other, epsilon) { return ( epsilonCompare(this.x, other.x, epsilon) && @@ -103,71 +127,126 @@ export class Rectangle { ); } + /** + * @returns {number} + */ left() { return this.x; } + /** + * @returns {number} + */ right() { return this.x + this.w; } + /** + * @returns {number} + */ top() { return this.y; } + /** + * @returns {number} + */ bottom() { return this.y + this.h; } + /** + * Returns Top, Right, Bottom, Left + * @returns {[number, number, number, number]} + */ trbl() { return [this.y, this.right(), this.bottom(), this.x]; } + /** + * Returns the center of the rect + * @returns {Vector} + */ getCenter() { return new Vector(this.x + this.w / 2, this.y + this.h / 2); } + /** + * Sets the right side of the rect without moving it + * @param {number} right + */ setRight(right) { this.w = right - this.x; } + /** + * Sets the bottom side of the rect without moving it + * @param {number} bottom + */ setBottom(bottom) { this.h = bottom - this.y; } - // Sets top while keeping bottom + /** + * Sets the top side of the rect without scaling it + * @param {number} top + */ setTop(top) { const bottom = this.bottom(); this.y = top; this.setBottom(bottom); } - // Sets left while keeping right + /** + * Sets the left side of the rect without scaling it + * @param {number} left + */ setLeft(left) { const right = this.right(); this.x = left; this.setRight(right); } + /** + * Returns the top left point + * @returns {Vector} + */ topLeft() { return new Vector(this.x, this.y); } + /** + * Returns the bottom left point + * @returns {Vector} + */ bottomRight() { return new Vector(this.right(), this.bottom()); } + /** + * Moves the rectangle by the given parameters + * @param {number} x + * @param {number} y + */ moveBy(x, y) { this.x += x; this.y += y; } + /** + * Moves the rectangle by the given vector + * @param {Vector} vec + */ moveByVector(vec) { this.x += vec.x; this.y += vec.y; } - // Returns a scaled version which also scales the position of the rectangle + /** + * Scales every parameter (w, h, x, y) by the given factor. Useful to transform from world to + * tile space and vice versa + * @param {number} factor + */ allScaled(factor) { return new Rectangle(this.x * factor, this.y * factor, this.w * factor, this.h * factor); } @@ -177,12 +256,14 @@ export class Rectangle { * @param {number} amount * @returns {Rectangle} new rectangle */ - expandedInAllDirections(amount) { return new Rectangle(this.x - amount, this.y - amount, this.w + 2 * amount, this.h + 2 * amount); } - // Culling helpers + /** + * Helper for computing a culling area. Returns the top left tile + * @returns {Vector} + */ getMinStartTile() { return new Vector(this.x, this.y).snapWorldToTile(); } @@ -201,6 +282,14 @@ export class Rectangle { ); } + /** + * Returns if this rectangle contains the other rectangle specified by the parameters + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @returns {boolean} + */ containsRect4Params(x, y, w, h) { return this.x <= x + w && x <= this.right() && this.y <= y + h && y <= this.bottom(); } @@ -210,6 +299,7 @@ export class Rectangle { * @param {number} x * @param {number} y * @param {number} radius + * @returns {boolean} */ containsCircle(x, y, radius) { return ( @@ -224,6 +314,7 @@ export class Rectangle { * Returns if hte rectangle contains the given point * @param {number} x * @param {number} y + * @returns {boolean} */ containsPoint(x, y) { return x >= this.x && x < this.right() && y >= this.y && y < this.bottom(); @@ -234,7 +325,7 @@ export class Rectangle { * @param {Rectangle} rect * @returns {Rectangle|null} */ - getUnion(rect) { + getIntersection(rect) { const left = Math_max(this.x, rect.x); const top = Math_max(this.y, rect.y); @@ -244,6 +335,30 @@ export class Rectangle { if (right <= left || bottom <= top) { return null; } + + return Rectangle.fromTRBL(top, right, bottom, left); + } + + /** + * Returns the union of this rectangle with another + * @param {Rectangle} rect + */ + getUnion(rect) { + if (this.isEmpty()) { + // If this is rect is empty, return the other one + return rect.clone(); + } + if (rect.isEmpty()) { + // If the other is empty, return this one + return this.clone(); + } + + // Find contained area + const left = Math_min(this.x, rect.x); + const top = Math_min(this.y, rect.y); + const right = Math_max(this.right(), rect.right()); + const bottom = Math_max(this.bottom(), rect.bottom()); + return Rectangle.fromTRBL(top, right, bottom, left); } diff --git a/src/js/core/sprites.js b/src/js/core/sprites.js index 8f9fb4d7..4251bee1 100644 --- a/src/js/core/sprites.js +++ b/src/js/core/sprites.js @@ -170,7 +170,7 @@ export class AtlasSprite extends BaseSprite { if (clipping) { const rect = new Rectangle(destX, destY, destW, destH); - intersection = rect.getUnion(visibleRect); + intersection = rect.getIntersection(visibleRect); if (!intersection) { return; } diff --git a/src/js/core/utils.js b/src/js/core/utils.js index fdf97880..3d4e524c 100644 --- a/src/js/core/utils.js +++ b/src/js/core/utils.js @@ -405,8 +405,6 @@ export function findNiceValue(num) { return Math_round(niceValue * 100) / 100; } -window.fn = findNiceValue; - /** * Finds a nice integer value * @see findNiceValue @@ -769,7 +767,7 @@ export function quantizeFloat(value) { * @param {number} tickRate Interval of the timer */ export function checkTimerExpired(now, lastTick, tickRate) { - if (!G_IS_PROD) { + if (G_IS_DEV) { if (quantizeFloat(now) !== now) { console.error("Got non-quantizied time:" + now + " vs " + quantizeFloat(now)); now = quantizeFloat(now); diff --git a/src/js/game/automatic_save.js b/src/js/game/automatic_save.js index 6c80976f..1b3f13ca 100644 --- a/src/js/game/automatic_save.js +++ b/src/js/game/automatic_save.js @@ -47,10 +47,16 @@ export class AutomaticSave { return; } + const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds(); + if (!saveInterval) { + // Disabled + return; + } + // Check when the last save was, but make sure that if it fails, we don't spam const lastSaveTime = Math_max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate()); - let secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0; + const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0; let shouldSave = false; switch (this.saveImportance) { @@ -61,7 +67,7 @@ export class AutomaticSave { case enumSavePriority.regular: // Could determine if there is a good / bad point here - shouldSave = secondsSinceLastSave > MIN_INTERVAL_SECS; + shouldSave = secondsSinceLastSave > saveInterval; break; default: diff --git a/src/js/game/belt_path.js b/src/js/game/belt_path.js new file mode 100644 index 00000000..71d268ff --- /dev/null +++ b/src/js/game/belt_path.js @@ -0,0 +1,1066 @@ +import { Math_min, Math_max } from "../core/builtins"; +import { globalConfig } from "../core/config"; +import { DrawParameters } from "../core/draw_parameters"; +import { createLogger } from "../core/logging"; +import { epsilonCompare, round4Digits } from "../core/utils"; +import { Vector } from "../core/vector"; +import { BaseItem } from "./base_item"; +import { Entity } from "./entity"; +import { GameRoot } from "./root"; +import { Rectangle } from "../core/rectangle"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +import { gItemRegistry } from "../core/global_registries"; + +const logger = createLogger("belt_path"); + +// Helpers for more semantic access into interleaved arrays +const _nextDistance = 0; +const _item = 1; + +const DEBUG = G_IS_DEV && false; + +/** + * Stores a path of belts, used for optimizing performance + */ +export class BeltPath extends BasicSerializableObject { + static getId() { + return "BeltPath"; + } + + static getSchema() { + return { + entityPath: types.array(types.entity), + items: types.array(types.pair(types.ufloat, types.obj(gItemRegistry))), + spacingToFirstItem: types.ufloat, + }; + } + + /** + * Creates a path from a serialized object + * @param {GameRoot} root + * @param {Object} data + * @returns {BeltPath|string} + */ + static fromSerialized(root, data) { + // Create fake object which looks like a belt path but skips the constructor + const fakeObject = /** @type {BeltPath} */ (Object.create(BeltPath.prototype)); + fakeObject.root = root; + + // Deserialize the data + const errorCodeDeserialize = fakeObject.deserialize(data); + if (errorCodeDeserialize) { + return errorCodeDeserialize; + } + + // Compute other properties + fakeObject.init(false); + + return fakeObject; + } + + /** + * Initializes the path by computing the properties which are not saved + * @param {boolean} computeSpacing Whether to also compute the spacing + */ + init(computeSpacing = true) { + // Find acceptor and ejector + this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector; + this.ejectorSlot = this.ejectorComp.slots[0]; + this.initialBeltComponent = this.entityPath[0].components.Belt; + + this.totalLength = this.computeTotalLength(); + + if (computeSpacing) { + this.spacingToFirstItem = this.totalLength; + } + + /** + * Current bounds of this path + * @type {Rectangle} + */ + this.worldBounds = this.computeBounds(); + + // Connect the belts + for (let i = 0; i < this.entityPath.length; ++i) { + this.entityPath[i].components.Belt.assignedPath = this; + } + } + + /** + * @param {GameRoot} root + * @param {Array} entityPath + */ + constructor(root, entityPath) { + super(); + this.root = root; + + assert(entityPath.length > 0, "invalid entity path"); + this.entityPath = entityPath; + + /** + * Stores the items sorted, and their distance to the previous item (or start) + * Layout: [distanceToNext, item] + * @type {Array<[number, BaseItem]>} + */ + this.items = []; + + /** + * Stores the spacing to the first item + */ + + this.init(); + + this.debug_checkIntegrity("constructor"); + } + + /** + * Returns whether this path can accept a new item + * @returns {boolean} + */ + canAcceptItem() { + return this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts; + } + + /** + * Tries to accept the item + * @param {BaseItem} item + */ + tryAcceptItem(item) { + if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) { + this.items.unshift([this.spacingToFirstItem, item]); + this.spacingToFirstItem = 0; + return true; + } + return false; + } + + /** + * SLOW / Tries to find the item closest to the given tile + * @param {Vector} tile + * @returns {BaseItem|null} + */ + findItemAtTile(tile) { + // TODO: This breaks color blind mode otherwise + return null; + } + + /** + * Computes the tile bounds of the path + * @returns {Rectangle} + */ + computeBounds() { + let bounds = this.entityPath[0].components.StaticMapEntity.getTileSpaceBounds(); + for (let i = 1; i < this.entityPath.length; ++i) { + const staticComp = this.entityPath[i].components.StaticMapEntity; + const otherBounds = staticComp.getTileSpaceBounds(); + bounds = bounds.getUnion(otherBounds); + } + return bounds.allScaled(globalConfig.tileSize); + } + + /** + * Helper to throw an error on mismatch + * @param {string} change + * @param {Array} reason + */ + debug_failIntegrity(change, ...reason) { + throw new Error("belt path invalid (" + change + "): " + reason.map(i => "" + i).join(" ")); + } + + /** + * Checks if this path is valid + */ + debug_checkIntegrity(currentChange = "change") { + if (!G_IS_DEV) { + return; + } + + const fail = (...args) => this.debug_failIntegrity(currentChange, ...args); + + // Check for empty path + if (this.entityPath.length === 0) { + return fail("Belt path is empty"); + } + + // Check for mismatching length + const totalLength = this.computeTotalLength(); + if (!epsilonCompare(this.totalLength, totalLength, 0.01)) { + return this.debug_failIntegrity( + currentChange, + "Total length mismatch, stored =", + this.totalLength, + "but correct is", + totalLength + ); + } + + // Check for misconnected entities + for (let i = 0; i < this.entityPath.length - 1; ++i) { + const entity = this.entityPath[i]; + if (entity.destroyed) { + return fail("Reference to destroyed entity " + entity.uid); + } + + const followUp = this.root.systemMgr.systems.belt.findFollowUpEntity(entity); + if (!followUp) { + return fail( + "Follow up entity for the", + i, + "-th entity (total length", + this.entityPath.length, + ") was null!" + ); + } + if (followUp !== this.entityPath[i + 1]) { + return fail( + "Follow up entity mismatch, stored is", + this.entityPath[i + 1].uid, + "but real one is", + followUp.uid + ); + } + if (entity.components.Belt.assignedPath !== this) { + return fail( + "Entity with uid", + entity.uid, + "doesn't have this path assigned, but this path contains the entity." + ); + } + } + + // Check for right ejector component and slot + if (this.ejectorComp !== this.entityPath[this.entityPath.length - 1].components.ItemEjector) { + return fail("Stale ejectorComp handle"); + } + if (this.ejectorSlot !== this.ejectorComp.slots[0]) { + return fail("Stale ejector slot handle"); + } + if (!this.ejectorComp) { + return fail("Ejector comp not set"); + } + if (!this.ejectorSlot) { + return fail("Ejector slot not set"); + } + if (this.initialBeltComponent !== this.entityPath[0].components.Belt) { + return fail("Stale initial belt component handle"); + } + + // Check spacing + if (this.spacingToFirstItem > this.totalLength + 0.005) { + return fail( + currentChange, + "spacing to first item (", + this.spacingToFirstItem, + ") is greater than total length (", + this.totalLength, + ")" + ); + } + + // Check distance if empty + if (this.items.length === 0 && !epsilonCompare(this.spacingToFirstItem, this.totalLength, 0.01)) { + return fail( + currentChange, + "Path is empty but spacing to first item (", + this.spacingToFirstItem, + ") does not equal total length (", + this.totalLength, + ")" + ); + } + + // Check items etc + let currentPos = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + + if (item[_nextDistance] < 0 || item[_nextDistance] > this.totalLength + 0.02) { + return fail( + "Item has invalid offset to next item: ", + item[_nextDistance], + "(total length:", + this.totalLength, + ")" + ); + } + + currentPos += item[_nextDistance]; + } + + // Check the total sum matches + if (!epsilonCompare(currentPos, this.totalLength, 0.01)) { + return fail( + "total sum (", + currentPos, + ") of first item spacing (", + this.spacingToFirstItem, + ") and items does not match total length (", + this.totalLength, + ") -> items: " + this.items.map(i => i[_nextDistance]).join("|") + ); + } + + // Check bounds + const actualBounds = this.computeBounds(); + if (!actualBounds.equalsEpsilon(this.worldBounds, 0.01)) { + return fail("Bounds are stale"); + } + } + + /** + * Extends the belt path by the given belt + * @param {Entity} entity + */ + extendOnEnd(entity) { + DEBUG && logger.log("Extending belt path by entity at", entity.components.StaticMapEntity.origin); + + const beltComp = entity.components.Belt; + + // If the last belt has something on its ejector, put that into the path first + const pendingItem = this.ejectorComp.takeSlotItem(0); + if (pendingItem) { + // Ok, so we have a pending item + DEBUG && logger.log("Taking pending item and putting it back on the path"); + this.items.push([0, pendingItem]); + } + + // Append the entity + this.entityPath.push(entity); + + // Extend the path length + const additionalLength = beltComp.getEffectiveLengthTiles(); + this.totalLength += additionalLength; + DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength); + + // If we have no item, just update the distance to the first item + if (this.items.length === 0) { + this.spacingToFirstItem = this.totalLength; + DEBUG && logger.log(" Extended spacing to first to", this.totalLength, "(= total length)"); + } else { + // Otherwise, update the next-distance of the last item + const lastItem = this.items[this.items.length - 1]; + DEBUG && + logger.log( + " Extended spacing of last item from", + lastItem[_nextDistance], + "to", + lastItem[_nextDistance] + additionalLength + ); + lastItem[_nextDistance] += additionalLength; + } + + // Update handles + this.ejectorComp = entity.components.ItemEjector; + this.ejectorSlot = this.ejectorComp.slots[0]; + + // Assign reference + beltComp.assignedPath = this; + + // Update bounds + this.worldBounds = this.computeBounds(); + + this.debug_checkIntegrity("extend-on-end"); + } + + /** + * Extends the path with the given entity on the beginning + * @param {Entity} entity + */ + extendOnBeginning(entity) { + const beltComp = entity.components.Belt; + + DEBUG && logger.log("Extending the path on the beginning"); + + // All items on that belt are simply lost (for now) + + const length = beltComp.getEffectiveLengthTiles(); + + // Extend the length of this path + this.totalLength += length; + + // Simply adjust the first item spacing cuz we have no items contained + this.spacingToFirstItem += length; + + // Set handles and append entity + beltComp.assignedPath = this; + this.entityPath.unshift(entity); + this.initialBeltComponent = this.entityPath[0].components.Belt; + + // Update bounds + this.worldBounds = this.computeBounds(); + + this.debug_checkIntegrity("extend-on-begin"); + } + + /** + * Returns if the given entity is the end entity of the path + * @param {Entity} entity + * @returns {boolean} + */ + isEndEntity(entity) { + return this.entityPath[this.entityPath.length - 1] === entity; + } + + /** + * Returns if the given entity is the start entity of the path + * @param {Entity} entity + * @returns {boolean} + */ + isStartEntity(entity) { + return this.entityPath[0] === entity; + } + + /** + * Splits this path at the given entity by removing it, and + * returning the new secondary paht + * @param {Entity} entity + * @returns {BeltPath} + */ + deleteEntityOnPathSplitIntoTwo(entity) { + DEBUG && logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin); + + // First, find where the current path ends + const beltComp = entity.components.Belt; + beltComp.assignedPath = null; + + const entityLength = beltComp.getEffectiveLengthTiles(); + assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split"); + assert(this.entityPath.indexOf(entity) !== 0, "Entity is first"); + assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last"); + + let firstPathEntityCount = 0; + let firstPathLength = 0; + let firstPathEndEntity = null; + + for (let i = 0; i < this.entityPath.length; ++i) { + const otherEntity = this.entityPath[i]; + if (otherEntity === entity) { + DEBUG && logger.log("Found entity at", i, "of length", firstPathLength); + break; + } + + ++firstPathEntityCount; + firstPathEndEntity = otherEntity; + firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(); + } + + DEBUG && + logger.log( + "First path ends at", + firstPathLength, + "and entity", + firstPathEndEntity.components.StaticMapEntity.origin, + "and has", + firstPathEntityCount, + "entities" + ); + + // Compute length of second path + const secondPathLength = this.totalLength - firstPathLength - entityLength; + const secondPathStart = firstPathLength + entityLength; + const secondEntities = this.entityPath.splice(firstPathEntityCount + 1); + DEBUG && + logger.log( + "Second path starts at", + secondPathStart, + "and has a length of ", + secondPathLength, + "with", + secondEntities.length, + "entities" + ); + + // Remove the last item + this.entityPath.pop(); + + DEBUG && logger.log("Splitting", this.items.length, "items"); + DEBUG && + logger.log( + "Old items are", + this.items.map(i => i[_nextDistance]) + ); + + // Create second path + const secondPath = new BeltPath(this.root, secondEntities); + + // Remove all items which are no longer relevant and transfer them to the second path + let itemPos = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + const distanceToNext = item[_nextDistance]; + + DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next"); + + // Check if this item is past the first path + if (itemPos >= firstPathLength) { + // Remove it from the first path + this.items.splice(i, 1); + i -= 1; + DEBUG && + logger.log(" Removed item from first path since its no longer contained @", itemPos); + + // Check if its on the second path (otherwise its on the removed belt and simply lost) + if (itemPos >= secondPathStart) { + // Put item on second path + secondPath.items.push([distanceToNext, item[_item]]); + DEBUG && + logger.log( + " Put item to second path @", + itemPos, + "with distance to next =", + distanceToNext + ); + + // If it was the first item, adjust the distance to the first item + if (secondPath.items.length === 1) { + DEBUG && logger.log(" Sinc it was the first, set sapcing of first to", itemPos); + secondPath.spacingToFirstItem = itemPos - secondPathStart; + } + } else { + DEBUG && logger.log(" Item was on the removed belt, so its gone - forever!"); + } + } else { + // Seems this item is on the first path (so all good), so just make sure it doesn't + // have a nextDistance which is bigger than the total path length + const clampedDistanceToNext = Math_min(itemPos + distanceToNext, firstPathLength) - itemPos; + if (clampedDistanceToNext < distanceToNext) { + DEBUG && + logger.log( + "Correcting next distance (first path) from", + distanceToNext, + "to", + clampedDistanceToNext + ); + item[_nextDistance] = clampedDistanceToNext; + } + } + + // Advance items + itemPos += distanceToNext; + } + + DEBUG && + logger.log( + "New items are", + this.items.map(i => i[_nextDistance]) + ); + + DEBUG && + logger.log( + "And second path items are", + secondPath.items.map(i => i[_nextDistance]) + ); + + // Adjust our total length + this.totalLength = firstPathLength; + + // Make sure that if we are empty, we set our first distance properly + if (this.items.length === 0) { + this.spacingToFirstItem = this.totalLength; + } + + // Set new ejector and acceptor handles + this.ejectorComp = firstPathEndEntity.components.ItemEjector; + this.ejectorSlot = this.ejectorComp.slots[0]; + + // Update bounds + this.worldBounds = this.computeBounds(); + + this.debug_checkIntegrity("split-two-first"); + secondPath.debug_checkIntegrity("split-two-second"); + + return secondPath; + } + + /** + * Deletes the last entity + * @param {Entity} entity + */ + deleteEntityOnEnd(entity) { + assert( + this.entityPath[this.entityPath.length - 1] === entity, + "Not actually the last entity (instead " + this.entityPath.indexOf(entity) + ")" + ); + + // Ok, first remove the entity + const beltComp = entity.components.Belt; + const beltLength = beltComp.getEffectiveLengthTiles(); + + DEBUG && + logger.log( + "Deleting last entity on path with length", + this.entityPath.length, + "(reducing", + this.totalLength, + " by", + beltLength, + ")" + ); + this.totalLength -= beltLength; + this.entityPath.pop(); + + DEBUG && + logger.log( + " New path has length of", + this.totalLength, + "with", + this.entityPath.length, + "entities" + ); + + // This is just for sanity + beltComp.assignedPath = null; + + // Clean up items + if (this.items.length === 0) { + // Simple case with no items, just update the first item spacing + this.spacingToFirstItem = this.totalLength; + } else { + // Ok, make sure we simply drop all items which are no longer contained + let itemOffset = this.spacingToFirstItem; + let lastItemOffset = itemOffset; + + DEBUG && logger.log(" Adjusting", this.items.length, "items"); + + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + + // Get rid of items past this path + if (itemOffset >= this.totalLength) { + DEBUG && logger.log("Dropping item (current index=", i, ")"); + this.items.splice(i, 1); + i -= 1; + continue; + } + + DEBUG && logger.log("Item", i, "is at", itemOffset, "with next offset", item[_nextDistance]); + lastItemOffset = itemOffset; + itemOffset += item[_nextDistance]; + } + + // If we still have an item, make sure the last item matches + if (this.items.length > 0) { + // We can easily compute the next distance since we know where the last item is now + const lastDistance = this.totalLength - lastItemOffset; + assert( + lastDistance >= 0.0, + "Last item distance mismatch: " + + lastDistance + + " -> Total length was " + + this.totalLength + + " and lastItemOffset was " + + lastItemOffset + ); + + DEBUG && + logger.log( + "Adjusted distance of last item: it is at", + lastItemOffset, + "so it has a distance of", + lastDistance, + "to the end (", + this.totalLength, + ")" + ); + this.items[this.items.length - 1][_nextDistance] = lastDistance; + } else { + DEBUG && logger.log(" Removed all items so we'll update spacing to total length"); + + // We removed all items so update our spacing + this.spacingToFirstItem = this.totalLength; + } + } + + // Update handles + this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector; + this.ejectorSlot = this.ejectorComp.slots[0]; + + // Update bounds + this.worldBounds = this.computeBounds(); + + this.debug_checkIntegrity("delete-on-end"); + } + + /** + * Deletes the entity of the start of the path + * @see deleteEntityOnEnd + * @param {Entity} entity + */ + deleteEntityOnStart(entity) { + assert( + entity === this.entityPath[0], + "Not actually the start entity (instead " + this.entityPath.indexOf(entity) + ")" + ); + + // Ok, first remove the entity + const beltComp = entity.components.Belt; + const beltLength = beltComp.getEffectiveLengthTiles(); + + DEBUG && + logger.log( + "Deleting first entity on path with length", + this.entityPath.length, + "(reducing", + this.totalLength, + " by", + beltLength, + ")" + ); + this.totalLength -= beltLength; + this.entityPath.shift(); + + DEBUG && + logger.log( + " New path has length of", + this.totalLength, + "with", + this.entityPath.length, + "entities" + ); + + // This is just for sanity + beltComp.assignedPath = null; + + // Clean up items + if (this.items.length === 0) { + // Simple case with no items, just update the first item spacing + this.spacingToFirstItem = this.totalLength; + } else { + // Simple case, we had no item on the beginning -> all good + if (this.spacingToFirstItem >= beltLength) { + DEBUG && + logger.log( + " No item on the first place, so we can just adjust the spacing (spacing=", + this.spacingToFirstItem, + ") removed =", + beltLength + ); + this.spacingToFirstItem -= beltLength; + } else { + // Welp, okay we need to drop all items which are < beltLength and adjust + // the other item offsets as well + + DEBUG && + logger.log( + " We have at least one item in the beginning, drop those and adjust spacing (first item @", + this.spacingToFirstItem, + ") since we removed", + beltLength, + "length from path" + ); + DEBUG && + logger.log( + " Items:", + this.items.map(i => i[_nextDistance]) + ); + + // Find offset to first item + let itemOffset = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + if (itemOffset <= beltLength) { + DEBUG && + logger.log( + " -> Dropping item with index", + i, + "at", + itemOffset, + "since it was on the removed belt" + ); + // This item must be dropped + this.items.splice(i, 1); + i -= 1; + itemOffset += item[_nextDistance]; + continue; + } else { + // This item can be kept, thus its the first we know + break; + } + } + + if (this.items.length > 0) { + DEBUG && + logger.log( + " Offset of first non-dropped item was at:", + itemOffset, + "-> setting spacing to it (total length=", + this.totalLength, + ")" + ); + + this.spacingToFirstItem = itemOffset - beltLength; + assert( + this.spacingToFirstItem >= 0.0, + "Invalid spacing after delete on start: " + this.spacingToFirstItem + ); + } else { + DEBUG && logger.log(" We dropped all items, simply set spacing to total length"); + // We dropped all items, simple one + this.spacingToFirstItem = this.totalLength; + } + } + } + + // Update handles + this.initialBeltComponent = this.entityPath[0].components.Belt; + + // Update bounds + this.worldBounds = this.computeBounds(); + + this.debug_checkIntegrity("delete-on-start"); + } + + /** + * Extends the path by the given other path + * @param {BeltPath} otherPath + */ + extendByPath(otherPath) { + assert(otherPath !== this, "Circular path dependency"); + + const entities = otherPath.entityPath; + DEBUG && logger.log("Extending path by other path, starting to add entities"); + + const oldLength = this.totalLength; + + DEBUG && logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength); + + // First, append entities + for (let i = 0; i < entities.length; ++i) { + const entity = entities[i]; + const beltComp = entity.components.Belt; + + // Add to path and update references + this.entityPath.push(entity); + beltComp.assignedPath = this; + + // Update our length + const additionalLength = beltComp.getEffectiveLengthTiles(); + this.totalLength += additionalLength; + } + + DEBUG && + logger.log( + " Path is now", + this.entityPath.length, + "entities and has a length of", + this.totalLength + ); + + // Update handles + this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector; + this.ejectorSlot = this.ejectorComp.slots[0]; + + // Now, update the distance of our last item + if (this.items.length !== 0) { + const lastItem = this.items[this.items.length - 1]; + lastItem[_nextDistance] += otherPath.spacingToFirstItem; + DEBUG && + logger.log(" Add distance to last item, effectively being", lastItem[_nextDistance], "now"); + } else { + // Seems we have no items, update our first item distance + this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem; + DEBUG && + logger.log( + " We had no items, so our new spacing to first is old length (", + oldLength, + ") plus others spacing to first (", + otherPath.spacingToFirstItem, + ") =", + this.spacingToFirstItem + ); + } + + DEBUG && logger.log(" Pushing", otherPath.items.length, "items from other path"); + + // Aaand push the other paths items + for (let i = 0; i < otherPath.items.length; ++i) { + const item = otherPath.items[i]; + this.items.push([item[_nextDistance], item[_item]]); + } + + // Update bounds + this.worldBounds = this.computeBounds(); + + this.debug_checkIntegrity("extend-by-path"); + } + + /** + * Computes the total length of the path + * @returns {number} + */ + computeTotalLength() { + let length = 0; + for (let i = 0; i < this.entityPath.length; ++i) { + length += this.entityPath[i].components.Belt.getEffectiveLengthTiles(); + } + return length; + } + + /** + * Performs one tick + */ + update() { + this.debug_checkIntegrity("pre-update"); + + // Divide by item spacing on belts since we use throughput and not speed + let beltSpeed = + this.root.hubGoals.getBeltBaseSpeed() * + this.root.dynamicTickrate.deltaSeconds * + globalConfig.itemSpacingOnBelts; + + if (G_IS_DEV && globalConfig.debug.instantBelts) { + beltSpeed *= 100; + } + + let minimumDistance = this.ejectorSlot.item ? globalConfig.itemSpacingOnBelts : 0; + + // Try to reduce spacing + let remainingAmount = beltSpeed; + for (let i = this.items.length - 1; i >= 0; --i) { + const nextDistanceAndItem = this.items[i]; + const minimumSpacing = minimumDistance; + + const takeAway = Math_max( + 0, + Math_min(remainingAmount, nextDistanceAndItem[_nextDistance] - minimumSpacing) + ); + + remainingAmount -= takeAway; + nextDistanceAndItem[_nextDistance] -= takeAway; + + this.spacingToFirstItem += takeAway; + if (remainingAmount < 0.01) { + break; + } + + minimumDistance = globalConfig.itemSpacingOnBelts; + } + + const lastItem = this.items[this.items.length - 1]; + if (lastItem && lastItem[_nextDistance] === 0) { + // Take over + if (this.ejectorComp.tryEject(0, lastItem[_item])) { + this.items.pop(); + } + } + + this.debug_checkIntegrity("post-update"); + } + + /** + * Computes a world space position from the given progress + * @param {number} progress + * @returns {Vector} + */ + computePositionFromProgress(progress) { + let currentLength = 0; + + // floating point issuses .. + assert(progress <= this.totalLength + 0.02, "Progress too big: " + progress); + + for (let i = 0; i < this.entityPath.length; ++i) { + const beltComp = this.entityPath[i].components.Belt; + const localLength = beltComp.getEffectiveLengthTiles(); + + if (currentLength + localLength >= progress || i === this.entityPath.length - 1) { + // Min required here due to floating point issues + const localProgress = Math_min(1.0, progress - currentLength); + + assert(localProgress >= 0.0, "Invalid local progress: " + localProgress); + const localSpace = beltComp.transformBeltToLocalSpace(localProgress); + return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace); + } + currentLength += localLength; + } + + assert(false, "invalid progress: " + progress + " (max: " + this.totalLength + ")"); + } + + /** + * + * @param {DrawParameters} parameters + */ + drawDebug(parameters) { + if (!parameters.visibleRect.containsRect(this.worldBounds)) { + return; + } + + parameters.context.fillStyle = "#d79a25"; + parameters.context.strokeStyle = "#d79a25"; + parameters.context.beginPath(); + + for (let i = 0; i < this.entityPath.length; ++i) { + const entity = this.entityPath[i]; + const pos = entity.components.StaticMapEntity; + const worldPos = pos.origin.toWorldSpaceCenterOfTile(); + + if (i === 0) { + parameters.context.moveTo(worldPos.x, worldPos.y); + } else { + parameters.context.lineTo(worldPos.x, worldPos.y); + } + } + parameters.context.stroke(); + + // Items + let progress = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const nextDistanceAndItem = this.items[i]; + const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); + parameters.context.fillStyle = "#268e4d"; + parameters.context.beginRoundedRect(worldPos.x - 5, worldPos.y - 5, 10, 10, 3); + parameters.context.fill(); + parameters.context.font = "6px GameFont"; + parameters.context.fillStyle = "#111"; + parameters.context.fillText( + "" + round4Digits(nextDistanceAndItem[_nextDistance]), + worldPos.x + 5, + worldPos.y + 2 + ); + progress += nextDistanceAndItem[_nextDistance]; + nextDistanceAndItem[_item].draw(worldPos.x, worldPos.y, parameters, 10); + } + + for (let i = 0; i < this.entityPath.length; ++i) { + const entity = this.entityPath[i]; + parameters.context.fillStyle = "#d79a25"; + const pos = entity.components.StaticMapEntity; + const worldPos = pos.origin.toWorldSpaceCenterOfTile(); + parameters.context.beginCircle(worldPos.x, worldPos.y, i === 0 ? 5 : 3); + parameters.context.fill(); + } + + for (let progress = 0; progress <= this.totalLength + 0.01; progress += 0.2) { + const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); + parameters.context.fillStyle = "red"; + parameters.context.beginCircle(worldPos.x, worldPos.y, 1); + parameters.context.fill(); + } + + const firstItemIndicator = this.computePositionFromProgress( + this.spacingToFirstItem + ).toWorldSpaceCenterOfTile(); + parameters.context.fillStyle = "purple"; + parameters.context.fillRect(firstItemIndicator.x - 3, firstItemIndicator.y - 1, 6, 2); + } + + /** + * Draws the path + * @param {DrawParameters} parameters + */ + draw(parameters) { + if (!parameters.visibleRect.containsRect(this.worldBounds)) { + return; + } + + let progress = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const nextDistanceAndItem = this.items[i]; + const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); + if (parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, 10)) { + nextDistanceAndItem[_item].draw(worldPos.x, worldPos.y, parameters); + } + progress += nextDistanceAndItem[_nextDistance]; + } + } +} diff --git a/src/js/game/hud/parts/blueprint.js b/src/js/game/blueprint.js similarity index 92% rename from src/js/game/hud/parts/blueprint.js rename to src/js/game/blueprint.js index 6dcd4c43..d923b2e1 100644 --- a/src/js/game/hud/parts/blueprint.js +++ b/src/js/game/blueprint.js @@ -1,13 +1,13 @@ -import { DrawParameters } from "../../../core/draw_parameters"; -import { Loader } from "../../../core/loader"; -import { createLogger } from "../../../core/logging"; -import { Vector } from "../../../core/vector"; -import { Entity } from "../../entity"; -import { GameRoot } from "../../root"; -import { findNiceIntegerValue } from "../../../core/utils"; -import { Math_pow } from "../../../core/builtins"; -import { blueprintShape } from "../../upgrades"; -import { globalConfig } from "../../../core/config"; +import { DrawParameters } from "../core/draw_parameters"; +import { Loader } from "../core/loader"; +import { createLogger } from "../core/logging"; +import { Vector } from "../core/vector"; +import { Entity } from "./entity"; +import { GameRoot } from "./root"; +import { findNiceIntegerValue } from "../core/utils"; +import { Math_pow } from "../core/builtins"; +import { blueprintShape } from "./upgrades"; +import { globalConfig } from "../core/config"; const logger = createLogger("blueprint"); @@ -202,10 +202,10 @@ export class Blueprint { "Can not delete entity for blueprint" ); if (!root.logic.tryDeleteBuilding(contents)) { - logger.error( + assertAlways( + false, "Building has replaceable component but is also unremovable in blueprint" ); - return false; } } } @@ -215,6 +215,7 @@ export class Blueprint { clone.components.StaticMapEntity.origin.addInplace(tile); root.map.placeStaticEntity(clone); + root.entityMgr.registerEntity(clone); anyPlaced = true; } diff --git a/src/js/game/buildings/energy_generator.js b/src/js/game/buildings/energy_generator.js new file mode 100644 index 00000000..47502ce6 --- /dev/null +++ b/src/js/game/buildings/energy_generator.js @@ -0,0 +1,107 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; +import { EnergyGeneratorComponent } from "../components/energy_generator"; +import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; + +export class MetaEnergyGenerator extends MetaBuilding { + constructor() { + super("energy_generator"); + } + + isRotateable(variant) { + return false; + } + + getSilhouetteColor() { + return "#c425d7"; + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + // TODO + return []; + } + + getDimensions(variant) { + return new Vector(2, 2); + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new ItemAcceptorComponent({ + slots: [ + { + pos: new Vector(0, 0), + directions: [enumDirection.top], + filter: enumItemAcceptorItemFilter.shape, + }, + + { + pos: new Vector(1, 0), + directions: [enumDirection.top], + filter: enumItemAcceptorItemFilter.shape, + }, + { + pos: new Vector(0, 1), + directions: [enumDirection.bottom], + filter: enumItemAcceptorItemFilter.shape, + }, + { + pos: new Vector(1, 1), + directions: [enumDirection.bottom], + filter: enumItemAcceptorItemFilter.shape, + }, + ], + }) + ); + + entity.addComponent( + new EnergyGeneratorComponent({ + // Set by the energy generator system later + requiredKey: null, + }) + ); + + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + type: enumPinSlotType.energyEjector, + }, + { + pos: new Vector(1, 0), + type: enumPinSlotType.energyEjector, + }, + { + pos: new Vector(0, 1), + type: enumPinSlotType.energyEjector, + }, + { + pos: new Vector(1, 1), + type: enumPinSlotType.energyEjector, + }, + ], + }) + ); + } +} diff --git a/src/js/game/camera.js b/src/js/game/camera.js index 709f3ac7..d2c468c9 100644 --- a/src/js/game/camera.js +++ b/src/js/game/camera.js @@ -28,6 +28,7 @@ const velocitySmoothing = 0.5; const velocityFade = 0.98; const velocityStrength = 0.4; const velocityMax = 20; +const ticksBeforeErasingVelocity = 10; /** * @enum {string} @@ -58,6 +59,8 @@ export class Camera extends BasicSerializableObject { // Input handling this.currentlyMoving = false; this.lastMovingPosition = null; + this.lastMovingPositionLastTick = null; + this.numTicksStandingStill = null; this.cameraUpdateTimeBucket = 0.0; this.didMoveSinceTouchStart = false; this.currentlyPinching = false; @@ -667,6 +670,8 @@ export class Camera extends BasicSerializableObject { this.touchPostMoveVelocity = new Vector(0, 0); this.currentlyMoving = true; this.lastMovingPosition = pos; + this.lastMovingPositionLastTick = null; + this.numTicksStandingStill = 0; this.didMoveSinceTouchStart = false; } @@ -716,6 +721,8 @@ export class Camera extends BasicSerializableObject { this.currentlyMoving = false; this.currentlyPinching = false; this.lastMovingPosition = null; + this.lastMovingPositionLastTick = null; + this.numTicksStandingStill = 0; this.lastPinchPositions = null; this.userInteraction.dispatch(USER_INTERACT_TOUCHEND); this.didMoveSinceTouchStart = false; @@ -813,6 +820,23 @@ export class Camera extends BasicSerializableObject { this.touchPostMoveVelocity = this.touchPostMoveVelocity.multiplyScalar(velocityFade); + // Check if the camera is being dragged but standing still: if not, zero out `touchPostMoveVelocity`. + if (this.currentlyMoving && this.desiredCenter === null) { + if ( + this.lastMovingPositionLastTick !== null && + this.lastMovingPositionLastTick.equalsEpsilon(this.lastMovingPosition) + ) { + this.numTicksStandingStill++; + } else { + this.numTicksStandingStill = 0; + } + this.lastMovingPositionLastTick = this.lastMovingPosition.copy(); + + if (this.numTicksStandingStill >= ticksBeforeErasingVelocity) { + this.touchPostMoveVelocity.x = 0; + this.touchPostMoveVelocity.y = 0; + } + } // Check influence of past points if (!this.currentlyMoving && !this.currentlyPinching) { const len = this.touchPostMoveVelocity.length(); diff --git a/src/js/game/component_registry.js b/src/js/game/component_registry.js index 76458d43..c0077a5a 100644 --- a/src/js/game/component_registry.js +++ b/src/js/game/component_registry.js @@ -10,6 +10,8 @@ import { UndergroundBeltComponent } from "./components/underground_belt"; import { UnremovableComponent } from "./components/unremovable"; import { HubComponent } from "./components/hub"; import { StorageComponent } from "./components/storage"; +import { EnergyGeneratorComponent } from "./components/energy_generator"; +import { WiredPinsComponent } from "./components/wired_pins"; export function initComponentRegistry() { gComponentRegistry.register(StaticMapEntityComponent); @@ -23,6 +25,8 @@ export function initComponentRegistry() { gComponentRegistry.register(UnremovableComponent); gComponentRegistry.register(HubComponent); gComponentRegistry.register(StorageComponent); + gComponentRegistry.register(EnergyGeneratorComponent); + gComponentRegistry.register(WiredPinsComponent); // IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS diff --git a/src/js/game/components/belt.js b/src/js/game/components/belt.js index d98db49a..75ba27d5 100644 --- a/src/js/game/components/belt.js +++ b/src/js/game/components/belt.js @@ -1,10 +1,11 @@ -import { Component } from "../component"; +import { Math_cos, Math_PI, Math_sin } from "../../core/builtins"; +import { enumDirection, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; -import { BaseItem } from "../base_item"; -import { Vector, enumDirection } from "../../core/vector"; -import { Math_PI, Math_sin, Math_cos } from "../../core/builtins"; -import { globalConfig } from "../../core/config"; +import { BeltPath } from "../belt_path"; +import { Component } from "../component"; +import { Entity } from "../entity"; + +export const curvedBeltLength = /* Math_PI / 4 */ 0.78; export class BeltComponent extends Component { static getId() { @@ -12,9 +13,9 @@ export class BeltComponent extends Component { } static getSchema() { + // The followUpCache field is not serialized. return { direction: types.string, - sortedItems: types.array(types.pair(types.float, types.obj(gItemRegistry))), }; } @@ -32,8 +33,22 @@ export class BeltComponent extends Component { this.direction = direction; - /** @type {Array<[number, BaseItem]>} */ - this.sortedItems = []; + /** @type {Entity} */ + this.followUpCache = null; + + /** + * The path this belt is contained in, not serialized + * @type {BeltPath} + */ + this.assignedPath = null; + } + + /** + * Returns the effective length of this belt in tile space + * @returns {number} + */ + getEffectiveLengthTiles() { + return this.direction === enumDirection.top ? 1.0 : curvedBeltLength; } /** @@ -45,14 +60,17 @@ export class BeltComponent extends Component { transformBeltToLocalSpace(progress) { switch (this.direction) { case enumDirection.top: + assert(progress <= 1.02, "Invalid progress: " + progress); return new Vector(0, 0.5 - progress); case enumDirection.right: { - const arcProgress = progress * 0.5 * Math_PI; + assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress); + const arcProgress = (progress / curvedBeltLength) * 0.5 * Math_PI; return new Vector(0.5 - 0.5 * Math_cos(arcProgress), 0.5 - 0.5 * Math_sin(arcProgress)); } case enumDirection.left: { - const arcProgress = progress * 0.5 * Math_PI; + assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress); + const arcProgress = (progress / curvedBeltLength) * 0.5 * Math_PI; return new Vector(-0.5 + 0.5 * Math_cos(arcProgress), 0.5 - 0.5 * Math_sin(arcProgress)); } default: @@ -60,46 +78,4 @@ export class BeltComponent extends Component { return new Vector(0, 0); } } - - /** - * Returns if the belt can currently accept an item from the given direction - */ - canAcceptItem() { - const firstItem = this.sortedItems[0]; - if (!firstItem) { - return true; - } - - return firstItem[0] > globalConfig.itemSpacingOnBelts; - } - - /** - * Pushes a new item to the belt - * @param {BaseItem} item - */ - takeItem(item, leftoverProgress = 0.0) { - if (G_IS_DEV) { - assert( - this.sortedItems.length === 0 || - leftoverProgress <= this.sortedItems[0][0] - globalConfig.itemSpacingOnBelts + 0.001, - "Invalid leftover: " + - leftoverProgress + - " items are " + - this.sortedItems.map(item => item[0]) - ); - assert(leftoverProgress < 1.0, "Invalid leftover: " + leftoverProgress); - } - this.sortedItems.unshift([leftoverProgress, item]); - } - - /** - * Returns how much space there is to the first item - */ - getDistanceToFirstItemCenter() { - const firstItem = this.sortedItems[0]; - if (!firstItem) { - return 1; - } - return firstItem[0]; - } } diff --git a/src/js/game/components/energy_generator.js b/src/js/game/components/energy_generator.js new file mode 100644 index 00000000..37e5dd6a --- /dev/null +++ b/src/js/game/components/energy_generator.js @@ -0,0 +1,59 @@ +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; +import { ShapeItem } from "../items/shape_item"; + +const maxQueueSize = 10; + +export class EnergyGeneratorComponent extends Component { + static getId() { + return "EnergyGenerator"; + } + + static getSchema() { + return { + requiredKey: types.string, + }; + } + + /** + * + * @param {object} param0 + * @param {string} param0.requiredKey Which shape this generator needs, can be null if not computed yet + */ + constructor({ requiredKey }) { + super(); + this.requiredKey = requiredKey; + + /** + * Stores how many items are ready to be converted to energy + * @type {number} + */ + this.itemsInQueue = 0; + } + + /** + * + * @param {BaseItem} item + */ + tryTakeItem(item) { + if (!(item instanceof ShapeItem)) { + // Not a shape + return false; + } + + if (item.definition.getHash() !== this.requiredKey) { + // Not our shape + return false; + } + + if (this.itemsInQueue >= maxQueueSize) { + // Queue is full + return false; + } + + // Take item and put it into the queue + ++this.itemsInQueue; + return true; + } +} diff --git a/src/js/game/components/item_ejector.js b/src/js/game/components/item_ejector.js index 5a40870b..7ae97724 100644 --- a/src/js/game/components/item_ejector.js +++ b/src/js/game/components/item_ejector.js @@ -3,13 +3,16 @@ import { BaseItem } from "../base_item"; import { Component } from "../component"; import { types } from "../../savegame/serialization"; import { gItemRegistry } from "../../core/global_registries"; +import { Entity } from "../entity"; /** * @typedef {{ * pos: Vector, * direction: enumDirection, * item: BaseItem, - * progress: number? + * progress: number?, + * cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot, + * cachedTargetEntity?: Entity * }} ItemEjectorSlot */ @@ -19,6 +22,8 @@ export class ItemEjectorComponent extends Component { } static getSchema() { + // The cachedDestSlot, cachedTargetEntity, and cachedConnectedSlots fields + // are not serialized. return { instantEject: types.bool, slots: types.array( @@ -61,6 +66,9 @@ export class ItemEjectorComponent extends Component { this.instantEject = instantEject; this.setSlots(slots); + + /** @type {ItemEjectorSlot[]} */ + this.cachedConnectedSlots = null; } /** @@ -76,6 +84,8 @@ export class ItemEjectorComponent extends Component { direction: slot.direction, item: null, progress: 0, + cachedDestSlot: null, + cachedTargetEntity: null, }); } } @@ -184,4 +194,17 @@ export class ItemEjectorComponent extends Component { this.slots[slotIndex].progress = this.instantEject ? 1 : 0; return true; } + + /** + * Clears the given slot and returns the item it had + * @param {number} slotIndex + * @returns {BaseItem|null} + */ + takeSlotItem(slotIndex) { + const slot = this.slots[slotIndex]; + const item = slot.item; + slot.item = null; + slot.progress = 0.0; + return item; + } } diff --git a/src/js/game/components/wired_pins.js b/src/js/game/components/wired_pins.js new file mode 100644 index 00000000..8157de5a --- /dev/null +++ b/src/js/game/components/wired_pins.js @@ -0,0 +1,65 @@ +import { Component } from "../component"; +import { Vector } from "../../core/vector"; +import { types } from "../../savegame/serialization"; + +/** @enum {string} */ +export const enumPinSlotType = { + energyEjector: "energyEjector", +}; + +/** @typedef {{ + * pos: Vector, + * type: enumPinSlotType + * }} WirePinSlotDefinition */ + +/** @typedef {{ + * pos: Vector, + * type: enumPinSlotType, + * value: number + * }} WirePinSlot */ + +export class WiredPinsComponent extends Component { + static getId() { + return "WiredPins"; + } + + static getSchema() { + return { + slots: types.array( + types.structured({ + pos: types.vector, + type: types.enum(enumPinSlotType), + value: types.float, + }) + ), + }; + } + + /** + * + * @param {object} param0 + * @param {Array} param0.slots + */ + constructor({ slots }) { + super(); + this.setSlots(slots); + } + + /** + * Sets the slots of this building + * @param {Array} slots + */ + setSlots(slots) { + /** @type {Array} */ + this.slots = []; + + for (let i = 0; i < slots.length; ++i) { + const slotData = slots[i]; + this.slots.push({ + pos: slotData.pos, + type: slotData.type, + value: 0.0, + }); + } + } +} diff --git a/src/js/game/core.js b/src/js/game/core.js index 3fc02397..e16a57a8 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -24,7 +24,7 @@ import { GameHUD } from "./hud/hud"; import { KeyActionMapper } from "./key_action_mapper"; import { GameLogic } from "./logic"; import { MapView } from "./map_view"; -import { GameRoot } from "./root"; +import { GameRoot, enumEditMode } from "./root"; import { ShapeDefinitionManager } from "./shape_definition_manager"; import { SoundProxy } from "./sound_proxy"; import { GameTime } from "./time/game_time"; @@ -403,13 +403,25 @@ export class GameCore { root.map.drawForeground(params); if (!this.root.camera.getIsMapOverlayActive()) { systems.hub.draw(params); + systems.energyGenerator.draw(params); systems.storage.draw(params); } + // WIRES LAYER + root.hud.parts.wiresOverlay.draw(params); + + if (this.root.editMode === enumEditMode.wires) { + systems.wiredPins.drawWiresLayer(params); + } + if (G_IS_DEV) { root.map.drawStaticEntityDebugOverlays(params); } + if (G_IS_DEV && globalConfig.debug.renderBeltPaths) { + systems.belt.drawBeltPathDebug(params); + } + // END OF GAME CONTENT // ----- diff --git a/src/js/game/entity_components.js b/src/js/game/entity_components.js index bcc6e9d0..fc29ce80 100644 --- a/src/js/game/entity_components.js +++ b/src/js/game/entity_components.js @@ -10,6 +10,8 @@ import { UndergroundBeltComponent } from "./components/underground_belt"; import { UnremovableComponent } from "./components/unremovable"; import { HubComponent } from "./components/hub"; import { StorageComponent } from "./components/storage"; +import { EnergyGeneratorComponent } from "./components/energy_generator"; +import { WiredPinsComponent } from "./components/wired_pins"; /* typehints:end */ /** @@ -56,6 +58,12 @@ export class EntityComponentStorage { /** @type {StorageComponent} */ this.Storage; + /** @type {EnergyGeneratorComponent} */ + this.EnergyGenerator; + + /** @type {WiredPinsComponent} */ + this.WiredPins; + /* typehints:end */ } } diff --git a/src/js/game/game_system_manager.js b/src/js/game/game_system_manager.js index 20d74dda..144380b2 100644 --- a/src/js/game/game_system_manager.js +++ b/src/js/game/game_system_manager.js @@ -13,6 +13,8 @@ import { HubSystem } from "./systems/hub"; import { StaticMapEntitySystem } from "./systems/static_map_entity"; import { ItemAcceptorSystem } from "./systems/item_acceptor"; import { StorageSystem } from "./systems/storage"; +import { EnergyGeneratorSystem } from "./systems/energy_generator"; +import { WiredPinsSystem } from "./systems/wired_pins"; const logger = createLogger("game_system_manager"); @@ -56,6 +58,12 @@ export class GameSystemManager { /** @type {StorageSystem} */ storage: null, + /** @type {EnergyGeneratorSystem} */ + energyGenerator: null, + + /** @type {WiredPinsSystem} */ + wiredPins: null, + /* typehints:end */ }; this.systemUpdateOrder = []; @@ -90,8 +98,12 @@ export class GameSystemManager { add("hub", HubSystem); + add("energyGenerator", EnergyGeneratorSystem); + add("staticMapEntities", StaticMapEntitySystem); + add("wiredPins", WiredPinsSystem); + // IMPORTANT: Must be after belt system since belt system can change the // orientation of an entity after it is placed -> the item acceptor cache // then would be invalid diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js index ef7797a9..9f65dc4c 100644 --- a/src/js/game/hub_goals.js +++ b/src/js/game/hub_goals.js @@ -275,7 +275,7 @@ export class HubGoals extends BasicSerializableObject { * @param {string} upgradeId * @returns {boolean} */ - tryUnlockUgprade(upgradeId) { + tryUnlockUpgrade(upgradeId) { if (!this.canUnlockUpgrade(upgradeId)) { return false; } diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js index c322c707..d7c2de51 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -34,7 +34,10 @@ 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"; +import { HUDColorBlindHelper } from "./parts/color_blind_helper"; +import { HUDShapeViewer } from "./parts/shape_viewer"; +import { HUDWiresOverlay } from "./parts/wires_overlay"; +import { HUDChangesDebugger } from "./parts/debug_changes"; export class GameHUD { /** @@ -68,6 +71,14 @@ export class GameHUD { debugInfo: new HUDDebugInfo(this.root), dialogs: new HUDModalDialogs(this.root), screenshotExporter: new HUDScreenshotExporter(this.root), + shapeViewer: new HUDShapeViewer(this.root), + wiresOverlay: new HUDWiresOverlay(this.root), + + // Typing hints + /* typehints:start */ + /** @type {HUDChangesDebugger} */ + changesDebugger: null, + /* typehints:end */ }; this.signals = { @@ -76,7 +87,8 @@ export class GameHUD { shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()), notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()), buildingsSelectedForCopy: /** @type {TypedSignal<[Array]>} */ (new Signal()), - pasteBlueprintRequested: new Signal(), + pasteBlueprintRequested: /** @type {TypedSignal<[]>} */ (new Signal()), + viewShapeDetailsRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), }; if (!IS_MOBILE) { @@ -91,6 +103,10 @@ export class GameHUD { this.parts.watermark = new HUDWatermark(this.root); } + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.parts.changesDebugger = new HUDChangesDebugger(this.root); + } + if (this.root.app.settings.getAllSettings().offerHints) { this.parts.tutorialHints = new HUDPartTutorialHints(this.root); this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root); @@ -100,6 +116,10 @@ export class GameHUD { this.parts.vignetteOverlay = new HUDVignetteOverlay(this.root); } + if (this.root.app.settings.getAllSettings().enableColorBlindHelper) { + this.parts.colorBlindHelper = new HUDColorBlindHelper(this.root); + } + const frag = document.createDocumentFragment(); for (const key in this.parts) { this.parts[key].createElements(frag); @@ -208,7 +228,14 @@ export class GameHUD { * @param {DrawParameters} parameters */ draw(parameters) { - const partsOrder = ["waypoints", "massSelector", "buildingPlacer", "blueprintPlacer"]; + const partsOrder = [ + "waypoints", + "massSelector", + "buildingPlacer", + "blueprintPlacer", + "colorBlindHelper", + "changesDebugger", + ]; for (let i = 0; i < partsOrder.length; ++i) { if (this.parts[partsOrder[i]]) { diff --git a/src/js/game/hud/parts/base_toolbar.js b/src/js/game/hud/parts/base_toolbar.js new file mode 100644 index 00000000..c5abf8a3 --- /dev/null +++ b/src/js/game/hud/parts/base_toolbar.js @@ -0,0 +1,172 @@ +import { gMetaBuildingRegistry } from "../../../core/global_registries"; +import { Signal } from "../../../core/signal"; +import { TrackedState } from "../../../core/tracked_state"; +import { makeDiv } from "../../../core/utils"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { MetaBuilding } from "../../meta_building"; +import { BaseHUDPart } from "../base_hud_part"; +import { GameRoot } from "../../root"; + +export class HUDBaseToolbar extends BaseHUDPart { + /** + * @param {GameRoot} root + * @param {Array} supportedBuildings + * @param {function} visibilityCondition + */ + constructor(root, supportedBuildings, visibilityCondition) { + super(root); + + this.supportedBuildings = supportedBuildings; + this.visibilityCondition = visibilityCondition; + + /** @type {Object.} */ + this.buildingHandles = {}; + + this.sigBuildingSelected = new Signal(); + this.trackedIsVisisible = new TrackedState(this.onVisibilityChanged, this); + } + + /** + * Called when the visibility of the toolbar changed + * @param {boolean} visible + */ + onVisibilityChanged(visible) { + this.element.classList.toggle("visible", visible); + } + + /** + * Should create all require elements + * @param {HTMLElement} parent + */ + createElements(parent) { + this.element = makeDiv(parent, "ingame_HUD_buildings_toolbar", ["ingame_buildingsToolbar"], ""); + } + + initialize() { + const actionMapper = this.root.keyMapper; + + const items = makeDiv(this.element, null, ["buildings"]); + + for (let i = 0; i < this.supportedBuildings.length; ++i) { + const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[i]); + const binding = actionMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]); + + const itemContainer = makeDiv(items, null, ["building"]); + itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png"); + + binding.add(() => this.selectBuildingForPlacement(metaBuilding)); + + this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), { + clickSound: null, + }); + + this.buildingHandles[metaBuilding.id] = { + metaBuilding, + element: itemContainer, + unlocked: false, + selected: false, + index: i, + }; + } + + this.root.hud.signals.selectedPlacementBuildingChanged.add( + this.onSelectedPlacementBuildingChanged, + this + ); + + this.lastSelectedIndex = 0; + actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this); + } + + /** + * Updates the toolbar + */ + update() { + this.trackedIsVisisible.set(this.visibilityCondition()); + + if (!this.trackedIsVisisible.get()) { + // Currently not active + } else { + for (const buildingId in this.buildingHandles) { + const handle = this.buildingHandles[buildingId]; + const newStatus = handle.metaBuilding.getIsUnlocked(this.root); + if (handle.unlocked !== newStatus) { + handle.unlocked = newStatus; + handle.element.classList.toggle("unlocked", newStatus); + } + } + } + } + + /** + * Cycles through all buildings + */ + cycleBuildings() { + let newIndex = this.lastSelectedIndex; + for (let i = 0; i < this.supportedBuildings.length; ++i, ++newIndex) { + newIndex %= this.supportedBuildings.length; + const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[newIndex]); + const handle = this.buildingHandles[metaBuilding.id]; + if (!handle.selected && handle.unlocked) { + break; + } + } + const metaBuildingClass = this.supportedBuildings[newIndex]; + const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); + this.selectBuildingForPlacement(metaBuilding); + } + + /** + * Called when the selected building got changed + * @param {MetaBuilding} metaBuilding + */ + onSelectedPlacementBuildingChanged(metaBuilding) { + for (const buildingId in this.buildingHandles) { + const handle = this.buildingHandles[buildingId]; + const newStatus = handle.metaBuilding === metaBuilding; + if (handle.selected !== newStatus) { + handle.selected = newStatus; + handle.element.classList.toggle("selected", newStatus); + } + if (handle.selected) { + this.lastSelectedIndex = handle.index; + } + } + + this.element.classList.toggle("buildingSelected", !!metaBuilding); + } + + /** + * @param {MetaBuilding} metaBuilding + */ + selectBuildingForPlacement(metaBuilding) { + if (!this.visibilityCondition()) { + // Not active + return; + } + + if (!metaBuilding.getIsUnlocked(this.root)) { + this.root.soundProxy.playUiError(); + return STOP_PROPAGATION; + } + + // Allow clicking an item again to deselect it + for (const buildingId in this.buildingHandles) { + const handle = this.buildingHandles[buildingId]; + if (handle.selected && handle.metaBuilding === metaBuilding) { + metaBuilding = null; + break; + } + } + + this.root.soundProxy.playUiClick(); + this.sigBuildingSelected.dispatch(metaBuilding); + this.onSelectedPlacementBuildingChanged(metaBuilding); + } +} diff --git a/src/js/game/hud/parts/blueprint_placer.js b/src/js/game/hud/parts/blueprint_placer.js index ef46f101..6b2af42e 100644 --- a/src/js/game/hud/parts/blueprint_placer.js +++ b/src/js/game/hud/parts/blueprint_placer.js @@ -9,7 +9,8 @@ import { KEYMAPPINGS } from "../../key_action_mapper"; import { blueprintShape } from "../../upgrades"; import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { Blueprint } from "./blueprint"; +import { Blueprint } from "../../blueprint"; +import { SOUNDS } from "../../../platform/sound"; export class HUDBlueprintPlacer extends BaseHUDPart { createElements(parent) { @@ -103,7 +104,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart { if (blueprint.tryPlace(this.root, tile)) { const cost = blueprint.getCost(); this.root.hubGoals.takeShapeByKey(blueprintShape, cost); - + this.root.soundProxy.playUi(SOUNDS.placeBuilding); // This actually feels weird // if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).pressed) { // this.currentBlueprint.set(null); diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index 5faec6ab..0e9752ef 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -16,6 +16,7 @@ import { defaultBuildingVariant } from "../../meta_building"; import { THEME } from "../../theme"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { HUDBuildingPlacerLogic } from "./building_placer_logic"; +import { ClickDetector } from "../../../core/click_detector"; export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { /** @@ -56,6 +57,12 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { this.currentInterpolatedCornerTile = new Vector(); this.lockIndicatorSprite = Loader.getSprite("sprites/misc/lock_direction_indicator.png"); + + /** + * Stores the click detectors for the variants so we can clean them up later + * @type {Array} + */ + this.variantClickDetectors = []; } /** @@ -98,6 +105,22 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { } } + cleanup() { + super.cleanup(); + this.cleanupVariantClickDetectors(); + } + + /** + * Cleans up all variant click detectors + */ + cleanupVariantClickDetectors() { + for (let i = 0; i < this.variantClickDetectors.length; ++i) { + const detector = this.variantClickDetectors[i]; + detector.cleanup(); + } + this.variantClickDetectors = []; + } + /** * Rerenders the variants displayed */ @@ -107,6 +130,9 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { const metaBuilding = this.currentMetaBuilding.get(); + // First, clear up all click detectors + this.cleanupVariantClickDetectors(); + if (!metaBuilding) { return; } @@ -147,6 +173,12 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { spriteWrapper.setAttribute("data-tile-h", dimensions.y); spriteWrapper.innerHTML = sprite.getAsHTML(iconSize * dimensions.x, iconSize * dimensions.y); + + const detector = new ClickDetector(element, { + consumeEvents: true, + targetOnly: true, + }); + detector.click.add(() => this.currentVariant.set(variant)); } } @@ -340,7 +372,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { size: 12, offsetY: -globalConfig.halfTileSize - - clamp((this.root.time.now() * 1.5) % 1.0, 0, 1) * 1 * globalConfig.tileSize + + clamp((this.root.time.realtimeNow() * 1.5) % 1.0, 0, 1) * 1 * globalConfig.tileSize + globalConfig.halfTileSize, }); } diff --git a/src/js/game/hud/parts/building_placer_logic.js b/src/js/game/hud/parts/building_placer_logic.js index 918ef5f1..0f7c7347 100644 --- a/src/js/game/hud/parts/building_placer_logic.js +++ b/src/js/game/hud/parts/building_placer_logic.js @@ -10,6 +10,10 @@ import { Entity } from "../../entity"; import { KEYMAPPINGS } from "../../key_action_mapper"; import { defaultBuildingVariant, MetaBuilding } from "../../meta_building"; import { BaseHUDPart } from "../base_hud_part"; +import { SOUNDS } from "../../../platform/sound"; +import { MetaMinerBuilding, enumMinerVariants } from "../../buildings/miner"; +import { enumHubGoalRewards } from "../../tutorial_goals"; +import { enumEditMode } from "../../root"; /** * Contains all logic for the building placer - this doesn't include the rendering @@ -44,7 +48,13 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { * The current rotation * @type {number} */ - this.currentBaseRotation = 0; + this.currentBaseRotationGeneral = 0; + + /** + * The current rotation preference for each building. + * @type{Object.} + */ + this.preferredBaseRotations = {}; /** * Whether we are currently dragging @@ -106,6 +116,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this); this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch()); this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch()); + this.root.signals.editModeChanged.add(this.onEditModeChanged, this); // MOUSE BINDINGS this.root.camera.downPreHandler.add(this.onMouseDown, this); @@ -113,6 +124,53 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { this.root.camera.upPostHandler.add(this.onMouseUp, this); } + /** + * Called when the edit mode got changed + * @param {enumEditMode} editMode + */ + onEditModeChanged(editMode) { + const metaBuilding = this.currentMetaBuilding.get(); + if (metaBuilding) { + if (metaBuilding.getEditLayer() !== editMode) { + // This layer doesn't fit the edit mode anymore + this.currentMetaBuilding.set(null); + } + } + } + + /** + * Returns the current base rotation for the current meta-building. + * @returns {number} + */ + get currentBaseRotation() { + if (!this.root.app.settings.getAllSettings().rotationByBuilding) { + return this.currentBaseRotationGeneral; + } + const metaBuilding = this.currentMetaBuilding.get(); + if (metaBuilding && this.preferredBaseRotations.hasOwnProperty(metaBuilding.getId())) { + return this.preferredBaseRotations[metaBuilding.getId()]; + } else { + return this.currentBaseRotationGeneral; + } + } + + /** + * Sets the base rotation for the current meta-building. + * @param {number} rotation The new rotation/angle. + */ + set currentBaseRotation(rotation) { + if (!this.root.app.settings.getAllSettings().rotationByBuilding) { + this.currentBaseRotationGeneral = rotation; + } else { + const metaBuilding = this.currentMetaBuilding.get(); + if (metaBuilding) { + this.preferredBaseRotations[metaBuilding.getId()] = rotation; + } else { + this.currentBaseRotationGeneral = rotation; + } + } + } + /** * Returns if the direction lock is currently active * @returns {boolean} @@ -183,6 +241,13 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { if (mousePos) { this.onMouseMove(mousePos); } + + // Make sure we have nothing selected while in overview mode + if (this.root.camera.getIsMapOverlayActive()) { + if (this.currentMetaBuilding.get()) { + this.currentMetaBuilding.set(null); + } + } } /** @@ -214,7 +279,9 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { const tile = worldPos.toTileSpace(); const contents = this.root.map.getTileContent(tile); if (contents) { - this.root.logic.tryDeleteBuilding(contents); + if (this.root.logic.tryDeleteBuilding(contents)) { + this.root.soundProxy.playUi(SOUNDS.destroyBuilding); + } } } @@ -235,10 +302,22 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { const worldPos = this.root.camera.screenToWorld(mousePosition); const tile = worldPos.toTileSpace(); - const contents = this.root.map.getTileContent(tile); + const contents = this.root.map.getTileContent(tile); if (!contents) { - this.currentMetaBuilding.set(null); + const tileBelow = this.root.map.getLowerLayerContentXY(tile.x, tile.y); + + // Check if there's a shape or color item below, if so select the miner + if (tileBelow) { + this.currentMetaBuilding.set(gMetaBuildingRegistry.findByClass(MetaMinerBuilding)); + + // Select chained miner if available, since thats always desired once unlocked + if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { + this.currentVariant.set(enumMinerVariants.chainable); + } + } else { + this.currentMetaBuilding.set(null); + } return; } @@ -437,15 +516,32 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { * releasing the mouse */ executeDirectionLockedPlacement() { + const metaBuilding = this.currentMetaBuilding.get(); + if (!metaBuilding) { + // No active building + return; + } + + // Get path to place const path = this.computeDirectionLockPath(); + + // Store if we placed anything + let anythingPlaced = false; + + // Perform this in bulk to avoid recalculations this.root.logic.performBulkOperation(() => { for (let i = 0; i < path.length; ++i) { const { rotation, tile } = path[i]; - this.currentBaseRotation = rotation; - this.tryPlaceCurrentBuildingAt(tile); + if (this.tryPlaceCurrentBuildingAt(tile)) { + anythingPlaced = true; + } } }); + + if (anythingPlaced) { + this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); + } } /** @@ -568,7 +664,9 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { // Place initial building, but only if direction lock is not active if (!this.isDirectionLockActive) { - this.tryPlaceCurrentBuildingAt(this.lastDragTile); + if (this.tryPlaceCurrentBuildingAt(this.lastDragTile)) { + this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); + } } return STOP_PROPAGATION; } @@ -651,15 +749,25 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { var sy = y0 < y1 ? 1 : -1; var err = dx - dy; + let anythingPlaced = false; + let anythingDeleted = false; + while (this.currentlyDeleting || this.currentMetaBuilding.get()) { if (this.currentlyDeleting) { + // Deletion const contents = this.root.map.getTileContentXY(x0, y0); if (contents && !contents.queuedForDestroy && !contents.destroyed) { - this.root.logic.tryDeleteBuilding(contents); + if (this.root.logic.tryDeleteBuilding(contents)) { + anythingDeleted = true; + } } } else { - this.tryPlaceCurrentBuildingAt(new Vector(x0, y0)); + // Placement + if (this.tryPlaceCurrentBuildingAt(new Vector(x0, y0))) { + anythingPlaced = true; + } } + if (x0 === x1 && y0 === y1) break; var e2 = 2 * err; if (e2 > -dy) { @@ -671,6 +779,13 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { y0 += sy; } } + + if (anythingPlaced) { + this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); + } + if (anythingDeleted) { + this.root.soundProxy.playUi(SOUNDS.destroyBuilding); + } } this.lastDragTile = newPos; diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js index 305d3eee..d8b56943 100644 --- a/src/js/game/hud/parts/buildings_toolbar.js +++ b/src/js/game/hud/parts/buildings_toolbar.js @@ -1,9 +1,6 @@ -import { gMetaBuildingRegistry } from "../../../core/global_registries"; -import { Signal } from "../../../core/signal"; -import { TrackedState } from "../../../core/tracked_state"; -import { makeDiv } from "../../../core/utils"; import { MetaBeltBaseBuilding } from "../../buildings/belt_base"; import { MetaCutterBuilding } from "../../buildings/cutter"; +import { MetaEnergyGenerator } from "../../buildings/energy_generator"; import { MetaMinerBuilding } from "../../buildings/miner"; import { MetaMixerBuilding } from "../../buildings/mixer"; import { MetaPainterBuilding } from "../../buildings/painter"; @@ -12,9 +9,8 @@ import { MetaSplitterBuilding } from "../../buildings/splitter"; import { MetaStackerBuilding } from "../../buildings/stacker"; import { MetaTrashBuilding } from "../../buildings/trash"; import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; -import { MetaBuilding } from "../../meta_building"; -import { BaseHUDPart } from "../base_hud_part"; -import { KEYMAPPINGS } from "../../key_action_mapper"; +import { enumEditMode } from "../../root"; +import { HUDBaseToolbar } from "./base_toolbar"; const toolbarBuildings = [ MetaBeltBaseBuilding, @@ -27,146 +23,15 @@ const toolbarBuildings = [ MetaMixerBuilding, MetaPainterBuilding, MetaTrashBuilding, + MetaEnergyGenerator, ]; -export class HUDBuildingsToolbar extends BaseHUDPart { +export class HUDBuildingsToolbar extends HUDBaseToolbar { constructor(root) { - super(root); - - /** @type {Object.} */ - this.buildingHandles = {}; - - this.sigBuildingSelected = new Signal(); - - this.trackedIsVisisible = new TrackedState(this.onVisibilityChanged, this); - } - - onVisibilityChanged(visible) { - this.element.classList.toggle("visible", visible); - } - - /** - * Should create all require elements - * @param {HTMLElement} parent - */ - createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_buildings_toolbar", [], ""); - } - - initialize() { - const actionMapper = this.root.keyMapper; - - const items = makeDiv(this.element, null, ["buildings"]); - - for (let i = 0; i < toolbarBuildings.length; ++i) { - const metaBuilding = gMetaBuildingRegistry.findByClass(toolbarBuildings[i]); - const binding = actionMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]); - - const itemContainer = makeDiv(items, null, ["building"]); - itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png"); - - binding.add(() => this.selectBuildingForPlacement(metaBuilding)); - - this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), { - clickSound: null, - }); - - this.buildingHandles[metaBuilding.id] = { - metaBuilding, - element: itemContainer, - unlocked: false, - selected: false, - index: i, - }; - } - - this.root.hud.signals.selectedPlacementBuildingChanged.add( - this.onSelectedPlacementBuildingChanged, - this + super( + root, + toolbarBuildings, + () => !this.root.camera.getIsMapOverlayActive() && this.root.editMode === enumEditMode.regular ); - - this.lastSelectedIndex = 0; - actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this); - } - - update() { - this.trackedIsVisisible.set(!this.root.camera.getIsMapOverlayActive()); - - for (const buildingId in this.buildingHandles) { - const handle = this.buildingHandles[buildingId]; - const newStatus = handle.metaBuilding.getIsUnlocked(this.root); - if (handle.unlocked !== newStatus) { - handle.unlocked = newStatus; - handle.element.classList.toggle("unlocked", newStatus); - } - } - } - - cycleBuildings() { - let newIndex = this.lastSelectedIndex; - for (let i = 0; i < toolbarBuildings.length; ++i, ++newIndex) { - newIndex %= toolbarBuildings.length; - const metaBuilding = gMetaBuildingRegistry.findByClass(toolbarBuildings[newIndex]); - const handle = this.buildingHandles[metaBuilding.id]; - if (!handle.selected && handle.unlocked) { - break; - } - } - const metaBuildingClass = toolbarBuildings[newIndex]; - const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); - this.selectBuildingForPlacement(metaBuilding); - } - - /** - * @param {MetaBuilding} metaBuilding - */ - onSelectedPlacementBuildingChanged(metaBuilding) { - for (const buildingId in this.buildingHandles) { - const handle = this.buildingHandles[buildingId]; - const newStatus = handle.metaBuilding === metaBuilding; - if (handle.selected !== newStatus) { - handle.selected = newStatus; - handle.element.classList.toggle("selected", newStatus); - } - if (handle.selected) { - this.lastSelectedIndex = handle.index; - } - } - - this.element.classList.toggle("buildingSelected", !!metaBuilding); - } - - /** - * @param {MetaBuilding} metaBuilding - */ - selectBuildingForPlacement(metaBuilding) { - if (!metaBuilding.getIsUnlocked(this.root)) { - this.root.soundProxy.playUiError(); - return; - } - - if (this.root.camera.getIsMapOverlayActive()) { - this.root.soundProxy.playUiError(); - return; - } - - // Allow clicking an item again to deselect it - for (const buildingId in this.buildingHandles) { - const handle = this.buildingHandles[buildingId]; - if (handle.selected && handle.metaBuilding === metaBuilding) { - metaBuilding = null; - break; - } - } - - this.root.soundProxy.playUiClick(); - this.sigBuildingSelected.dispatch(metaBuilding); - this.onSelectedPlacementBuildingChanged(metaBuilding); } } diff --git a/src/js/game/hud/parts/color_blind_helper.js b/src/js/game/hud/parts/color_blind_helper.js new file mode 100644 index 00000000..7e79fa1e --- /dev/null +++ b/src/js/game/hud/parts/color_blind_helper.js @@ -0,0 +1,106 @@ +import { BaseHUDPart } from "../base_hud_part"; +import { makeDiv } from "../../../core/utils"; +import { TrackedState } from "../../../core/tracked_state"; +import { enumColors } from "../../colors"; +import { ColorItem } from "../../items/color_item"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { THEME } from "../../theme"; +import { globalConfig } from "../../../core/config"; +import { T } from "../../../translations"; + +export class HUDColorBlindHelper extends BaseHUDPart { + createElements(parent) { + this.belowTileIndicator = makeDiv(parent, "ingame_HUD_ColorBlindBelowTileHelper", []); + } + + initialize() { + this.trackedColorBelowTile = new TrackedState(this.onColorBelowTileChanged, this); + } + + /** + * Called when the color below the current tile changed + * @param {enumColors|null} color + */ + onColorBelowTileChanged(color) { + this.belowTileIndicator.classList.toggle("visible", !!color); + if (color) { + this.belowTileIndicator.innerText = T.ingame.colors[color]; + } + } + + /** + * Computes the color below the current tile + * @returns {enumColors} + */ + computeColorBelowTile() { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return null; + } + + const worldPos = this.root.camera.screenToWorld(mousePosition); + const tile = worldPos.toTileSpace(); + const contents = this.root.map.getTileContent(tile); + + if (contents && !contents.components.Miner) { + const beltComp = contents.components.Belt; + + // Check if the belt has a color item + if (beltComp) { + const item = beltComp.assignedPath.findItemAtTile(tile); + if (item && item instanceof ColorItem) { + return item.color; + } + } + + // Check if we are ejecting an item, if so use that color + const ejectorComp = contents.components.ItemEjector; + if (ejectorComp) { + for (let i = 0; i < ejectorComp.slots.length; ++i) { + const slot = ejectorComp.slots[i]; + if (slot.item && slot.item instanceof ColorItem) { + return slot.item.color; + } + } + } + } else { + // We hovered a lower layer, show the color there + const lowerLayer = this.root.map.getLowerLayerContentXY(tile.x, tile.y); + if (lowerLayer && lowerLayer instanceof ColorItem) { + return lowerLayer.color; + } + } + + return null; + } + + update() { + this.trackedColorBelowTile.set(this.computeColorBelowTile()); + } + + /** + * Draws the currently selected tile + * @param {DrawParameters} parameters + */ + draw(parameters) { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return null; + } + + const below = this.computeColorBelowTile(); + if (below) { + // We have something below our tile + const worldPos = this.root.camera.screenToWorld(mousePosition); + const tile = worldPos.toTileSpace().toWorldSpace(); + + parameters.context.strokeStyle = THEME.map.colorBlindPickerTile; + parameters.context.lineWidth = 1; + parameters.context.beginPath(); + parameters.context.rect(tile.x, tile.y, globalConfig.tileSize, globalConfig.tileSize); + parameters.context.stroke(); + } + } +} diff --git a/src/js/game/hud/parts/debug_changes.js b/src/js/game/hud/parts/debug_changes.js new file mode 100644 index 00000000..1502afa2 --- /dev/null +++ b/src/js/game/hud/parts/debug_changes.js @@ -0,0 +1,78 @@ +import { globalConfig } from "../../../core/config"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { Rectangle } from "../../../core/rectangle"; +import { BaseHUDPart } from "../base_hud_part"; + +/** + * @typedef {{ + * label: string, + * area: Rectangle, + * hideAt: number, + * fillColor: string + * }} DebugChange + */ + +export class HUDChangesDebugger extends BaseHUDPart { + createElements(parent) {} + + initialize() { + /** @type {Array} */ + this.changes = []; + } + + /** + * Renders a new change + * @param {string} label Text to display + * @param {Rectangle} area Affected area world space + * @param {string} fillColor Color to display (Hex) + * @param {number=} timeToDisplay How long to display the change + */ + renderChange(label, area, fillColor, timeToDisplay = 0.3) { + this.changes.push({ + label, + area: area.clone(), + fillColor, + hideAt: this.root.time.realtimeNow() + timeToDisplay, + }); + } + + update() { + const now = this.root.time.realtimeNow(); + // Detect outdated changes + for (let i = 0; i < this.changes.length; ++i) { + const change = this.changes[i]; + if (change.hideAt <= now) { + this.changes.splice(i, 1); + i -= 1; + continue; + } + } + } + + /** + * + * @param {DrawParameters} parameters + */ + draw(parameters) { + for (let i = 0; i < this.changes.length; ++i) { + const change = this.changes[i]; + parameters.context.fillStyle = change.fillColor; + parameters.context.globalAlpha = 0.5; + parameters.context.fillRect( + change.area.x * globalConfig.tileSize, + change.area.y * globalConfig.tileSize, + change.area.w * globalConfig.tileSize, + change.area.h * globalConfig.tileSize + ); + + parameters.context.fillStyle = "#222"; + parameters.context.globalAlpha = 1; + parameters.context.font = "bold 8px GameFont"; + parameters.context.fillText( + change.label, + change.area.x * globalConfig.tileSize + 2, + change.area.y * globalConfig.tileSize + 12 + ); + } + } +} diff --git a/src/js/game/hud/parts/keybinding_overlay.js b/src/js/game/hud/parts/keybinding_overlay.js index 5b7f4a9d..995fc5d9 100644 --- a/src/js/game/hud/parts/keybinding_overlay.js +++ b/src/js/game/hud/parts/keybinding_overlay.js @@ -168,7 +168,7 @@ export class HUDKeybindingOverlay extends BaseHUDPart { // Pipette label: T.ingame.keybindingsOverlay.pipette, keys: [k.placement.pipette], - condition: () => !this.mapOverviewActive, + condition: () => !this.mapOverviewActive && !this.blueprintPlacementActive, }, { @@ -254,6 +254,13 @@ export class HUDKeybindingOverlay extends BaseHUDPart { keys: [k.massSelect.massSelectCopy], condition: () => this.anythingSelectedOnMap, }, + + { + // Switch layers + label: T.ingame.keybindingsOverlay.switchLayers, + keys: [k.ingame.switchLayers], + condition: () => true, + }, ]; if (!this.root.app.settings.getAllSettings().alwaysMultiplace) { diff --git a/src/js/game/hud/parts/mass_selector.js b/src/js/game/hud/parts/mass_selector.js index 7e6710c0..a3505e2d 100644 --- a/src/js/game/hud/parts/mass_selector.js +++ b/src/js/game/hud/parts/mass_selector.js @@ -70,14 +70,17 @@ export class HUDMassSelector extends BaseHUDPart { } confirmDelete() { - if (this.selectedUids.size > 100) { + if ( + !this.root.app.settings.getAllSettings().disableCutDeleteWarnings && + this.selectedUids.size > 100 + ) { const { ok } = this.root.hud.parts.dialogs.showWarning( T.dialogs.massDeleteConfirm.title, T.dialogs.massDeleteConfirm.desc.replace( "", "" + formatBigNumberFull(this.selectedUids.size) ), - ["cancel:good", "ok:bad"] + ["cancel:good:escape", "ok:bad:enter"] ); ok.add(() => this.doDelete()); } else { @@ -120,14 +123,17 @@ export class HUDMassSelector extends BaseHUDPart { T.dialogs.blueprintsNotUnlocked.title, T.dialogs.blueprintsNotUnlocked.desc ); - } else if (this.selectedUids.size > 100) { + } else if ( + !this.root.app.settings.getAllSettings().disableCutDeleteWarnings && + this.selectedUids.size > 100 + ) { const { ok } = this.root.hud.parts.dialogs.showWarning( T.dialogs.massCutConfirm.title, T.dialogs.massCutConfirm.desc.replace( "", "" + formatBigNumberFull(this.selectedUids.size) ), - ["cancel:good", "ok:bad"] + ["cancel:good:escape", "ok:bad:enter"] ); ok.add(() => this.doCut()); } else { diff --git a/src/js/game/hud/parts/pinned_shapes.js b/src/js/game/hud/parts/pinned_shapes.js index 62afff25..3f935a0b 100644 --- a/src/js/game/hud/parts/pinned_shapes.js +++ b/src/js/game/hud/parts/pinned_shapes.js @@ -26,7 +26,8 @@ export class HUDPinnedShapes extends BaseHUDPart { * amountLabel: HTMLElement, * lastRenderedValue: string, * element: HTMLElement, - * detector?: ClickDetector + * detector?: ClickDetector, + * infoDetector?: ClickDetector * }>} */ this.handles = []; @@ -155,6 +156,10 @@ export class HUDPinnedShapes extends BaseHUDPart { if (detector) { detector.cleanup(); } + const infoDetector = this.handles[i].infoDetector; + if (infoDetector) { + infoDetector.cleanup(); + } } this.handles = []; @@ -198,12 +203,24 @@ export class HUDPinnedShapes extends BaseHUDPart { detector = new ClickDetector(element, { consumeEvents: true, preventDefault: true, + targetOnly: true, }); detector.click.add(() => this.unpinShape(key)); } else { element.classList.add("marked"); } + // Show small info icon + const infoButton = document.createElement("button"); + infoButton.classList.add("infoButton"); + element.appendChild(infoButton); + const infoDetector = new ClickDetector(infoButton, { + consumeEvents: true, + preventDefault: true, + targetOnly: true, + }); + infoDetector.click.add(() => this.root.hud.signals.viewShapeDetailsRequested.dispatch(definition)); + const amountLabel = makeDiv(element, null, ["amountLabel"], ""); const goal = this.findGoalValueForShape(key); @@ -216,6 +233,8 @@ export class HUDPinnedShapes extends BaseHUDPart { element, amountLabel, lastRenderedValue: "", + detector, + infoDetector, }); } diff --git a/src/js/game/hud/parts/shape_viewer.js b/src/js/game/hud/parts/shape_viewer.js new file mode 100644 index 00000000..55feb976 --- /dev/null +++ b/src/js/game/hud/parts/shape_viewer.js @@ -0,0 +1,133 @@ +import { InputReceiver } from "../../../core/input_receiver"; +import { makeDiv, removeAllChildren } from "../../../core/utils"; +import { T } from "../../../translations"; +import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; +import { ShapeDefinition } from "../../shape_definition"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const copy = require("clipboard-copy"); + +export class HUDShapeViewer extends BaseHUDPart { + createElements(parent) { + this.background = makeDiv(parent, "ingame_HUD_ShapeViewer", ["ingameDialog"]); + + // DIALOG Inner / Wrapper + this.dialogInner = makeDiv(this.background, null, ["dialogInner"]); + this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.shapeViewer.title); + this.closeButton = makeDiv(this.title, null, ["closeButton"]); + this.trackClicks(this.closeButton, this.close); + this.contentDiv = makeDiv(this.dialogInner, null, ["content"]); + + this.renderArea = makeDiv(this.contentDiv, null, ["renderArea"]); + this.infoArea = makeDiv(this.contentDiv, null, ["infoArea"]); + + // Create button to copy the shape area + this.copyButton = document.createElement("button"); + this.copyButton.classList.add("styledButton", "copyKey"); + this.copyButton.innerText = T.ingame.shapeViewer.copyKey; + this.infoArea.appendChild(this.copyButton); + } + + initialize() { + this.root.hud.signals.viewShapeDetailsRequested.add(this.renderForShape, this); + + this.domAttach = new DynamicDomAttach(this.root, this.background, { + attachClass: "visible", + }); + + this.currentShapeKey = null; + + this.inputReciever = new InputReceiver("shape_viewer"); + this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); + + this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); + + this.trackClicks(this.copyButton, this.onCopyKeyRequested); + + this.close(); + } + + /** + * Called when the copying of a key was requested + */ + onCopyKeyRequested() { + if (this.currentShapeKey) { + copy(this.currentShapeKey); + this.close(); + } + } + + /** + * Closes the dialog + */ + close() { + this.visible = false; + document.body.classList.remove("ingameDialogOpen"); + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + this.update(); + } + + /** + * Shows the viewer for a given definition + * @param {ShapeDefinition} definition + */ + renderForShape(definition) { + this.visible = true; + document.body.classList.add("ingameDialogOpen"); + this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); + + removeAllChildren(this.renderArea); + + this.currentShapeKey = definition.getHash(); + + const layers = definition.layers; + this.contentDiv.setAttribute("data-layers", layers.length); + + for (let i = 0; i < layers.length; ++i) { + const layerElem = makeDiv(this.renderArea, null, ["layer", "layer-" + i]); + + let fakeLayers = []; + for (let k = 0; k < i; ++k) { + fakeLayers.push([null, null, null, null]); + } + fakeLayers.push(layers[i]); + + const thisLayerOnly = new ShapeDefinition({ layers: fakeLayers }); + const thisLayerCanvas = thisLayerOnly.generateAsCanvas(160); + layerElem.appendChild(thisLayerCanvas); + + for (let quad = 0; quad < 4; ++quad) { + const quadElem = makeDiv(layerElem, null, ["quad", "quad-" + quad]); + + const contents = layers[i][quad]; + if (contents) { + const colorLabelElem = makeDiv( + quadElem, + null, + ["colorLabel"], + T.ingame.colors[contents.color] + ); + } else { + const emptyLabelElem = makeDiv( + quadElem, + null, + ["emptyLabel"], + T.ingame.shapeViewer.empty + ); + } + } + } + } + + /** + * Cleans up everything + */ + cleanup() { + document.body.classList.remove("ingameDialogOpen"); + } + + update() { + this.domAttach.update(this.visible); + } +} diff --git a/src/js/game/hud/parts/shop.js b/src/js/game/hud/parts/shop.js index 912fb3f1..f83cb89b 100644 --- a/src/js/game/hud/parts/shop.js +++ b/src/js/game/hud/parts/shop.js @@ -79,6 +79,7 @@ export class HUDShop extends BaseHUDPart { const requiredHandle = handle.requireIndexToElement[i]; requiredHandle.container.remove(); requiredHandle.pinDetector.cleanup(); + requiredHandle.infoDetector.cleanup(); } // Cleanup @@ -122,6 +123,10 @@ export class HUDShop extends BaseHUDPart { pinButton.classList.add("pin"); container.appendChild(pinButton); + const viewInfoButton = document.createElement("button"); + viewInfoButton.classList.add("showInfo"); + container.appendChild(viewInfoButton); + const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash(); if (shape === currentGoalShape) { pinButton.classList.add("isGoal"); @@ -145,6 +150,14 @@ export class HUDShop extends BaseHUDPart { } }); + const infoDetector = new ClickDetector(viewInfoButton, { + consumeEvents: true, + preventDefault: true, + }); + infoDetector.click.add(() => + this.root.hud.signals.viewShapeDetailsRequested.dispatch(shapeDef) + ); + handle.requireIndexToElement.push({ container, progressLabel, @@ -152,6 +165,7 @@ export class HUDShop extends BaseHUDPart { definition: shapeDef, required: amount, pinDetector, + infoDetector, }); }); } @@ -202,6 +216,7 @@ export class HUDShop extends BaseHUDPart { const requiredHandle = handle.requireIndexToElement[i]; requiredHandle.container.remove(); requiredHandle.pinDetector.cleanup(); + requiredHandle.infoDetector.cleanup(); } handle.requireIndexToElement = []; } @@ -231,6 +246,6 @@ export class HUDShop extends BaseHUDPart { tryUnlockNextTier(upgradeId) { // Nothing - this.root.hubGoals.tryUnlockUgprade(upgradeId); + this.root.hubGoals.tryUnlockUpgrade(upgradeId); } } diff --git a/src/js/game/hud/parts/wires_overlay.js b/src/js/game/hud/parts/wires_overlay.js new file mode 100644 index 00000000..0d228509 --- /dev/null +++ b/src/js/game/hud/parts/wires_overlay.js @@ -0,0 +1,83 @@ +import { makeOffscreenBuffer } from "../../../core/buffer_utils"; +import { globalConfig } from "../../../core/config"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { enumEditMode } from "../../root"; +import { THEME } from "../../theme"; +import { BaseHUDPart } from "../base_hud_part"; + +const wiresBackgroundDpi = 3; + +export class HUDWiresOverlay extends BaseHUDPart { + createElements(parent) {} + + initialize() { + // Probably not the best location, but the one which makes most sense + this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.switchLayers).add(this.switchLayers, this); + + this.generateTilePattern(); + } + + /** + * Switches between layers + */ + switchLayers() { + if (this.root.editMode === enumEditMode.regular) { + this.root.editMode = enumEditMode.wires; + } else { + this.root.editMode = enumEditMode.regular; + } + this.root.signals.editModeChanged.dispatch(this.root.editMode); + } + + /** + * Generates the background pattern for the wires overlay + */ + generateTilePattern() { + const dims = globalConfig.tileSize * wiresBackgroundDpi; + const [canvas, context] = makeOffscreenBuffer(dims, dims, { + smooth: false, + reusable: false, + label: "wires-tile-pattern", + }); + + context.scale(wiresBackgroundDpi, wiresBackgroundDpi); + context.fillStyle = THEME.map.wires.overlay; + context.fillRect(0, 0, globalConfig.tileSize, globalConfig.tileSize); + + const lineWidth = 1; + + context.fillRect(0, 0, globalConfig.tileSize, lineWidth); + context.fillRect(0, lineWidth, lineWidth, globalConfig.tileSize); + + this.tilePatternCanvas = canvas; + } + + /** + * + * @param {DrawParameters} parameters + */ + draw(parameters) { + if (this.root.editMode !== enumEditMode.wires) { + return; + } + + if (!this.cachedPatternBackground) { + this.cachedPatternBackground = parameters.context.createPattern(this.tilePatternCanvas, "repeat"); + } + + const bounds = parameters.visibleRect; + + const scaleFactor = 1 / wiresBackgroundDpi; + + parameters.context.scale(scaleFactor, scaleFactor); + parameters.context.fillStyle = this.cachedPatternBackground; + parameters.context.fillRect( + bounds.x / scaleFactor, + bounds.y / scaleFactor, + bounds.w / scaleFactor, + bounds.h / scaleFactor + ); + parameters.context.scale(1 / scaleFactor, 1 / scaleFactor); + } +} diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index c514446d..45949ae3 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -26,6 +26,8 @@ export const KEYMAPPINGS = { toggleHud: { keyCode: 113 }, // F2 exportScreenshot: { keyCode: 114 }, // F3PS toggleFPSInfo: { keyCode: 115 }, // F4 + + switchLayers: { keyCode: key("Y") }, }, navigation: { @@ -53,6 +55,7 @@ export const KEYMAPPINGS = { mixer: { keyCode: key("8") }, painter: { keyCode: key("9") }, trash: { keyCode: key("0") }, + energy_generator: { keyCode: key("O") }, }, placement: { diff --git a/src/js/game/logic.js b/src/js/game/logic.js index 408bf89d..79caf38b 100644 --- a/src/js/game/logic.js +++ b/src/js/game/logic.js @@ -186,7 +186,6 @@ export class GameLogic { variant, }); - this.root.soundProxy.playUi(building.getPlacementSound()); return entity; } return null; @@ -197,7 +196,7 @@ export class GameLogic { * @param {function} operation */ performBulkOperation(operation) { - logger.log("Running bulk operation ..."); + logger.warn("Running bulk operation ..."); assert(!this.root.bulkOperationRunning, "Can not run two bulk operations twice"); this.root.bulkOperationRunning = true; const now = performanceNow(); @@ -228,6 +227,7 @@ export class GameLogic { } this.root.map.removeStaticEntity(building); this.root.entityMgr.destroyEntity(building); + this.root.entityMgr.processDestroyList(); return true; } diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js index 11da28f3..798e4d4c 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -1,10 +1,10 @@ -import { Vector, enumDirection, enumAngleToDirection } from "../core/vector"; import { Loader } from "../core/loader"; -import { GameRoot } from "./root"; import { AtlasSprite } from "../core/sprites"; -import { Entity } from "./entity"; -import { StaticMapEntityComponent } from "./components/static_map_entity"; +import { Vector } from "../core/vector"; import { SOUNDS } from "../platform/sound"; +import { StaticMapEntityComponent } from "./components/static_map_entity"; +import { Entity } from "./entity"; +import { enumEditMode, GameRoot } from "./root"; export const defaultBuildingVariant = "default"; @@ -24,6 +24,14 @@ export class MetaBuilding { return this.id; } + /** + * Returns the edit layer of the building + * @returns {enumEditMode} + */ + getEditLayer() { + return enumEditMode.regular; + } + /** * Should return the dimensions of the building */ diff --git a/src/js/game/meta_building_registry.js b/src/js/game/meta_building_registry.js index 450a9743..0f37762d 100644 --- a/src/js/game/meta_building_registry.js +++ b/src/js/game/meta_building_registry.js @@ -10,6 +10,7 @@ import { MetaStackerBuilding } from "./buildings/stacker"; import { MetaTrashBuilding } from "./buildings/trash"; import { MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; import { MetaHubBuilding } from "./buildings/hub"; +import { MetaEnergyGenerator } from "./buildings/energy_generator"; export function initMetaBuildingRegistry() { gMetaBuildingRegistry.register(MetaSplitterBuilding); @@ -23,4 +24,5 @@ export function initMetaBuildingRegistry() { gMetaBuildingRegistry.register(MetaBeltBaseBuilding); gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding); gMetaBuildingRegistry.register(MetaHubBuilding); + gMetaBuildingRegistry.register(MetaEnergyGenerator); } diff --git a/src/js/game/root.js b/src/js/game/root.js index 0456952c..e8808317 100644 --- a/src/js/game/root.js +++ b/src/js/game/root.js @@ -31,6 +31,12 @@ import { KeyActionMapper } from "./key_action_mapper"; const logger = createLogger("game/root"); +/** @enum {string} */ +export const enumEditMode = { + regular: "regular", + wires: "wires", +}; + /** * The game root is basically the whole game state at a given point, * combining all important classes. We don't have globals, but this @@ -124,6 +130,9 @@ export class GameRoot { /** @type {DynamicTickrate} */ this.dynamicTickrate = null; + /** @type {enumEditMode} */ + this.editMode = enumEditMode.regular; + this.signals = { // Entities entityManuallyPlaced: /** @type {TypedSignal<[Entity]>} */ (new Signal()), @@ -155,6 +164,8 @@ export class GameRoot { itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()), bulkOperationFinished: /** @type {TypedSignal<[]>} */ (new Signal()), + + editModeChanged: /** @type {TypedSignal<[enumEditMode]>} */ (new Signal()), }; // RNG's diff --git a/src/js/game/shape_definition.js b/src/js/game/shape_definition.js index d785f6ab..8644e353 100644 --- a/src/js/game/shape_definition.js +++ b/src/js/game/shape_definition.js @@ -333,7 +333,7 @@ export class ShapeDefinition extends BasicSerializableObject { const quadrantSize = 10; const quadrantHalfSize = quadrantSize / 2; - context.fillStyle = "rgba(40, 50, 65, 0.1)"; + context.fillStyle = THEME.items.circleBackground; context.beginCircle(0, 0, quadrantSize * 1.15); context.fill(); diff --git a/src/js/game/sound_proxy.js b/src/js/game/sound_proxy.js index 91fb15af..162f0bc0 100644 --- a/src/js/game/sound_proxy.js +++ b/src/js/game/sound_proxy.js @@ -5,10 +5,9 @@ import { GameRoot } from "./root"; import { Vector } from "../core/vector"; import { SOUNDS } from "../platform/sound"; -const avgSoundDurationSeconds = 0.25; +const avgSoundDurationSeconds = 0.1; const maxOngoingSounds = 2; - -const maxOngoingUiSounds = 2; +const maxOngoingUiSounds = 5; // Proxy to the application sound instance export class SoundProxy { diff --git a/src/js/game/systems/belt.js b/src/js/game/systems/belt.js index 5fa5a265..638351f5 100644 --- a/src/js/game/systems/belt.js +++ b/src/js/game/systems/belt.js @@ -1,26 +1,21 @@ -import { Math_radians, Math_min, Math_max, Math_sqrt } from "../../core/builtins"; +import { Math_sqrt } from "../../core/builtins"; import { globalConfig } from "../../core/config"; import { DrawParameters } from "../../core/draw_parameters"; import { Loader } from "../../core/loader"; +import { createLogger } from "../../core/logging"; import { AtlasSprite } from "../../core/sprites"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections } from "../../core/vector"; +import { BeltPath } from "../belt_path"; import { BeltComponent } from "../components/belt"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { enumDirection, enumDirectionToVector, Vector, enumInvertedDirections } from "../../core/vector"; import { MapChunkView } from "../map_chunk_view"; -import { gMetaBuildingRegistry } from "../../core/global_registries"; -import { MetaBeltBaseBuilding } from "../buildings/belt_base"; -import { defaultBuildingVariant } from "../meta_building"; -import { GameRoot } from "../root"; -import { createLogger } from "../../core/logging"; +import { fastArrayDeleteValue } from "../../core/utils"; -const BELT_ANIM_COUNT = 6; -const SQRT_2 = Math_sqrt(2); +export const BELT_ANIM_COUNT = 28; const logger = createLogger("belt"); -/** @typedef {Array<{ entity: Entity, followUp: Entity }>} BeltCache */ - export class BeltSystem extends GameSystemWithFilter { constructor(root) { super(root, [BeltComponent]); @@ -32,43 +27,75 @@ export class BeltSystem extends GameSystemWithFilter { [enumDirection.left]: Loader.getSprite("sprites/belt/left_0.png"), [enumDirection.right]: Loader.getSprite("sprites/belt/right_0.png"), }; - /**b + + /** * @type {Object.>} */ this.beltAnimations = { - [enumDirection.top]: [ - Loader.getSprite("sprites/belt/forward_0.png"), - Loader.getSprite("sprites/belt/forward_1.png"), - Loader.getSprite("sprites/belt/forward_2.png"), - Loader.getSprite("sprites/belt/forward_3.png"), - Loader.getSprite("sprites/belt/forward_4.png"), - Loader.getSprite("sprites/belt/forward_5.png"), - ], - [enumDirection.left]: [ - Loader.getSprite("sprites/belt/left_0.png"), - Loader.getSprite("sprites/belt/left_1.png"), - Loader.getSprite("sprites/belt/left_2.png"), - Loader.getSprite("sprites/belt/left_3.png"), - Loader.getSprite("sprites/belt/left_4.png"), - Loader.getSprite("sprites/belt/left_5.png"), - ], - [enumDirection.right]: [ - Loader.getSprite("sprites/belt/right_0.png"), - Loader.getSprite("sprites/belt/right_1.png"), - Loader.getSprite("sprites/belt/right_2.png"), - Loader.getSprite("sprites/belt/right_3.png"), - Loader.getSprite("sprites/belt/right_4.png"), - Loader.getSprite("sprites/belt/right_5.png"), - ], + [enumDirection.top]: [], + [enumDirection.left]: [], + [enumDirection.right]: [], }; + for (let i = 0; i < BELT_ANIM_COUNT; ++i) { + this.beltAnimations[enumDirection.top].push( + Loader.getSprite("sprites/belt/forward_" + i + ".png") + ); + this.beltAnimations[enumDirection.left].push(Loader.getSprite("sprites/belt/left_" + i + ".png")); + this.beltAnimations[enumDirection.right].push( + Loader.getSprite("sprites/belt/right_" + i + ".png") + ); + } + this.root.signals.entityAdded.add(this.updateSurroundingBeltPlacement, this); this.root.signals.entityDestroyed.add(this.updateSurroundingBeltPlacement, this); + this.root.signals.entityDestroyed.add(this.onEntityDestroyed, this); + this.root.signals.entityAdded.add(this.onEntityAdded, this); - this.cacheNeedsUpdate = true; + // /** @type {Rectangle} */ + // this.areaToRecompute = null; - /** @type {BeltCache} */ - this.beltCache = []; + /** @type {Array} */ + this.beltPaths = []; + } + + /** + * Serializes all belt paths + */ + serializePaths() { + let data = []; + for (let i = 0; i < this.beltPaths.length; ++i) { + data.push(this.beltPaths[i].serialize()); + } + return data; + } + + /** + * Deserializes all belt paths + * @param {Array} data + */ + deserializePaths(data) { + if (!Array.isArray(data)) { + return "Belt paths are not an array: " + typeof data; + } + + for (let i = 0; i < data.length; ++i) { + const path = BeltPath.fromSerialized(this.root, data[i]); + if (!(path instanceof BeltPath)) { + return "Failed to create path from belt data: " + path; + } + + this.beltPaths.push(path); + } + + if (this.beltPaths.length === 0) { + logger.warn("Recomputing belt paths (most likely the savegame is old)"); + this.recomputeAllBeltPaths(); + } else { + logger.warn("Restored", this.beltPaths.length, "belt paths"); + } + + this.verifyBeltPaths(); } /** @@ -85,15 +112,18 @@ export class BeltSystem extends GameSystemWithFilter { return; } - if (entity.components.Belt) { - this.cacheNeedsUpdate = true; - } - + /* const metaBelt = gMetaBuildingRegistry.findByClass(MetaBeltBaseBuilding); // Compute affected area const originalRect = staticComp.getTileSpaceBounds(); const affectedArea = originalRect.expandedInAllDirections(1); + + // Store if anything got changed, if so we need to queue a recompute + let anythingChanged = false; + + anythingChanged = true; // TODO / FIXME + for (let x = affectedArea.x; x < affectedArea.right(); ++x) { for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { if (!originalRect.containsPoint(x, y)) { @@ -113,16 +143,150 @@ export class BeltSystem extends GameSystemWithFilter { ); targetStaticComp.rotation = rotation; metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); - this.cacheNeedsUpdate = true; + anythingChanged = true; } } } } } + + if (anythingChanged) { + if (this.areaToRecompute) { + this.areaToRecompute = this.areaToRecompute.getUnion(affectedArea); + } else { + this.areaToRecompute = affectedArea.clone(); + } + if (G_IS_DEV) { + logger.log("Queuing recompute:", this.areaToRecompute); + } + } + + // FIXME + this.areaToRecompute = new Rectangle(-1000, -1000, 2000, 2000); + */ + } + + /** + * Called when an entity got destroyed + * @param {Entity} entity + */ + onEntityDestroyed(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (!entity.components.Belt) { + return; + } + + const assignedPath = entity.components.Belt.assignedPath; + assert(assignedPath, "Entity has no belt path assigned"); + this.deleteEntityFromPath(assignedPath, entity); + this.verifyBeltPaths(); + } + + /** + * Attempts to delete the belt from its current path + * @param {BeltPath} path + * @param {Entity} entity + */ + deleteEntityFromPath(path, entity) { + if (path.entityPath.length === 1) { + // This is a single entity path, easy to do, simply erase whole path + fastArrayDeleteValue(this.beltPaths, path); + return; + } + + // Notice: Since there might be circular references, it is important to check + // which role the entity has + if (path.isStartEntity(entity)) { + // We tried to delete the start + path.deleteEntityOnStart(entity); + } else if (path.isEndEntity(entity)) { + // We tried to delete the end + path.deleteEntityOnEnd(entity); + } else { + // We tried to delete something inbetween + const newPath = path.deleteEntityOnPathSplitIntoTwo(entity); + this.beltPaths.push(newPath); + } + } + + /** + * Called when an entity got added + * @param {Entity} entity + */ + onEntityAdded(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (!entity.components.Belt) { + return; + } + + const fromEntity = this.findSupplyingEntity(entity); + const toEntity = this.findFollowUpEntity(entity); + + // Check if we can add the entity to the previous path + if (fromEntity) { + const fromPath = fromEntity.components.Belt.assignedPath; + fromPath.extendOnEnd(entity); + + // Check if we now can extend the current path by the next path + if (toEntity) { + const toPath = toEntity.components.Belt.assignedPath; + + if (fromPath === toPath) { + // This is a circular dependency -> Ignore + } else { + fromPath.extendByPath(toPath); + + // Delete now obsolete path + fastArrayDeleteValue(this.beltPaths, toPath); + } + } + } else { + if (toEntity) { + // Prepend it to the other path + const toPath = toEntity.components.Belt.assignedPath; + toPath.extendOnBeginning(entity); + } else { + // This is an empty belt path + const path = new BeltPath(this.root, [entity]); + this.beltPaths.push(path); + } + } + + this.verifyBeltPaths(); } draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntityItems.bind(this)); + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].draw(parameters); + } + } + + /** + * Verifies all belt paths + */ + verifyBeltPaths() { + if (G_IS_DEV && true) { + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].debug_checkIntegrity("general-verify"); + } + + const belts = this.root.entityMgr.getAllWithComponent(BeltComponent); + for (let i = 0; i < belts.length; ++i) { + const path = belts[i].components.Belt.assignedPath; + if (!path) { + throw new Error("Belt has no path: " + belts[i].uid); + } + if (this.beltPaths.indexOf(path) < 0) { + throw new Error("Path of entity not contained: " + belts[i].uid); + } + } + } } /** @@ -164,150 +328,102 @@ export class BeltSystem extends GameSystemWithFilter { } /** - * Adds a single entity to the cache + * Finds the supplying belt for a given belt. Used for building the dependencies * @param {Entity} entity - * @param {BeltCache} cache - * @param {Set} visited */ - computeSingleBeltCache(entity, cache, visited) { - // Check for double visit - if (visited.has(entity.uid)) { - return; - } - visited.add(entity.uid); + findSupplyingEntity(entity) { + const staticComp = entity.components.StaticMapEntity; - const followUp = this.findFollowUpEntity(entity); - if (followUp) { - // Process followup first - this.computeSingleBeltCache(followUp, cache, visited); + const supplyDirection = staticComp.localDirectionToWorld(enumDirection.bottom); + const supplyVector = enumDirectionToVector[supplyDirection]; + + const supplyTile = staticComp.origin.add(supplyVector); + const supplyEntity = this.root.map.getTileContent(supplyTile); + + // Check if theres a belt at the tile we point to + if (supplyEntity) { + const supplyBeltComp = supplyEntity.components.Belt; + if (supplyBeltComp) { + const supplyStatic = supplyEntity.components.StaticMapEntity; + const supplyEjector = supplyEntity.components.ItemEjector; + + // Check if the belt accepts items from our direction + const ejectorSlots = supplyEjector.slots; + for (let i = 0; i < ejectorSlots.length; ++i) { + const slot = ejectorSlots[i]; + const localDirection = supplyStatic.localDirectionToWorld(slot.direction); + if (enumInvertedDirections[localDirection] === supplyDirection) { + return supplyEntity; + } + } + } } - cache.push({ entity, followUp }); + return null; } - computeBeltCache() { - logger.log("Updating belt cache"); + /** + * Computes the belt path network + */ + recomputeAllBeltPaths() { + logger.warn("Recomputing all belt paths"); + const visitedUids = new Set(); + + const result = []; - let cache = []; - let visited = new Set(); for (let i = 0; i < this.allEntities.length; ++i) { - this.computeSingleBeltCache(this.allEntities[i], cache, visited); - } - assert( - cache.length === this.allEntities.length, - "Belt cache mismatch: Has " + cache.length + " entries but should have " + this.allEntities.length - ); - - this.beltCache = cache; - } - - update() { - if (this.cacheNeedsUpdate) { - this.cacheNeedsUpdate = false; - this.computeBeltCache(); - } - - // Divide by item spacing on belts since we use throughput and not speed - let beltSpeed = - this.root.hubGoals.getBeltBaseSpeed() * - this.root.dynamicTickrate.deltaSeconds * - globalConfig.itemSpacingOnBelts; - - if (G_IS_DEV && globalConfig.debug.instantBelts) { - beltSpeed *= 100; - } - - for (let i = 0; i < this.beltCache.length; ++i) { - const { entity, followUp } = this.beltCache[i]; - - const beltComp = entity.components.Belt; - const items = beltComp.sortedItems; - - if (items.length === 0) { - // Fast out for performance + const entity = this.allEntities[i]; + if (visitedUids.has(entity.uid)) { continue; } - const ejectorComp = entity.components.ItemEjector; - let maxProgress = 1; + // Mark entity as visited + visitedUids.add(entity.uid); - /* PERFORMANCE OPTIMIZATION */ - // Original: - // const isCurrentlyEjecting = ejectorComp.isAnySlotEjecting(); - // Replaced (Since belts always have just one slot): - const ejectorSlot = ejectorComp.slots[0]; - const isCurrentlyEjecting = ejectorSlot.item; + // Compute path, start with entity and find precedors / successors + const path = [entity]; - // When ejecting, we can not go further than the item spacing since it - // will be on the corner - if (isCurrentlyEjecting) { - maxProgress = 1 - globalConfig.itemSpacingOnBelts; - } else { - // Otherwise our progress depends on the follow up - if (followUp) { - const spacingOnBelt = followUp.components.Belt.getDistanceToFirstItemCenter(); - maxProgress = Math.min(2, 1 - globalConfig.itemSpacingOnBelts + spacingOnBelt); + let maxIter = 9999; - // Useful check, but hurts performance - // assert(maxProgress >= 0.0, "max progress < 0 (I)"); + // Find precedors + let prevEntity = this.findSupplyingEntity(entity); + while (prevEntity && --maxIter > 0) { + if (visitedUids.has(prevEntity.uid)) { + break; } + path.unshift(prevEntity); + visitedUids.add(prevEntity.uid); + prevEntity = this.findSupplyingEntity(prevEntity); } - let speedMultiplier = 1; - if (beltComp.direction !== enumDirection.top) { - // Curved belts are shorter, thus being quicker (Looks weird otherwise) - speedMultiplier = SQRT_2; - } - - // Not really nice. haven't found the reason for this yet. - if (items.length > 2 / globalConfig.itemSpacingOnBelts) { - beltComp.sortedItems = []; - } - - for (let itemIndex = items.length - 1; itemIndex >= 0; --itemIndex) { - const progressAndItem = items[itemIndex]; - - progressAndItem[0] = Math.min(maxProgress, progressAndItem[0] + speedMultiplier * beltSpeed); - - if (progressAndItem[0] >= 1.0) { - if (followUp) { - const followUpBelt = followUp.components.Belt; - if (followUpBelt.canAcceptItem()) { - followUpBelt.takeItem(progressAndItem[1], progressAndItem[0] - 1.0); - items.splice(itemIndex, 1); - } else { - // Well, we couldn't really take it to a follow up belt, keep it at - // max progress - progressAndItem[0] = 1.0; - maxProgress = 1 - globalConfig.itemSpacingOnBelts; - } - } else { - // Try to give this item to a new belt - - /* PERFORMANCE OPTIMIZATION */ - // Original: - // const freeSlot = ejectorComp.getFirstFreeSlot(); - // Replaced - if (ejectorSlot.item) { - // So, we don't have a free slot - damned! - progressAndItem[0] = 1.0; - maxProgress = 1 - globalConfig.itemSpacingOnBelts; - } else { - // We got a free slot, remove this item and keep it on the ejector slot - if (!ejectorComp.tryEject(0, progressAndItem[1])) { - assert(false, "Ejection failed"); - } - items.splice(itemIndex, 1); - - // NOTICE: Do not override max progress here at all, this leads to issues - } - } - } else { - // We just moved this item forward, so determine the maximum progress of other items - maxProgress = Math.max(0, progressAndItem[0] - globalConfig.itemSpacingOnBelts); + // Find succedors + let nextEntity = this.findFollowUpEntity(entity); + while (nextEntity && --maxIter > 0) { + if (visitedUids.has(nextEntity.uid)) { + break; } + + path.push(nextEntity); + visitedUids.add(nextEntity.uid); + nextEntity = this.findFollowUpEntity(nextEntity); } + + assert(maxIter > 1, "Ran out of iterations"); + result.push(new BeltPath(this.root, path)); } + + logger.log("Found", this.beltPaths.length, "belt paths"); + this.beltPaths = result; + } + + update() { + this.verifyBeltPaths(); + + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].update(); + } + + this.verifyBeltPaths(); } /** @@ -350,38 +466,12 @@ export class BeltSystem extends GameSystemWithFilter { } /** + * Draws the belt parameters * @param {DrawParameters} parameters - * @param {Entity} entity */ - drawEntityItems(parameters, entity) { - const beltComp = entity.components.Belt; - const staticComp = entity.components.StaticMapEntity; - - const items = beltComp.sortedItems; - - if (items.length === 0) { - // Fast out for performance - return; - } - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - for (let i = 0; i < items.length; ++i) { - const itemAndProgress = items[i]; - - // Nice would be const [pos, item] = itemAndPos; but that gets polyfilled and is super slow then - const progress = itemAndProgress[0]; - const item = itemAndProgress[1]; - - const position = staticComp.applyRotationToVector(beltComp.transformBeltToLocalSpace(progress)); - - item.draw( - (staticComp.origin.x + position.x + 0.5) * globalConfig.tileSize, - (staticComp.origin.y + position.y + 0.5) * globalConfig.tileSize, - parameters - ); + drawBeltPathDebug(parameters) { + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].drawDebug(parameters); } } } diff --git a/src/js/game/systems/energy_generator.js b/src/js/game/systems/energy_generator.js new file mode 100644 index 00000000..733ea90a --- /dev/null +++ b/src/js/game/systems/energy_generator.js @@ -0,0 +1,76 @@ +import { DrawParameters } from "../../core/draw_parameters"; +import { T } from "../../translations"; +import { EnergyGeneratorComponent } from "../components/energy_generator"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { ShapeDefinition } from "../shape_definition"; + +export class EnergyGeneratorSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [EnergyGeneratorComponent]); + } + + draw(parameters) { + this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); + } + + /** + * Returns which shape is required for a given generator + * @param {Entity} entity + */ + getShapeRequiredForGenerator(entity) { + return "CuCuCuCu"; + } + + update() { + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const energyGenComp = entity.components.EnergyGenerator; + + if (!energyGenComp.requiredKey) { + // Compute required key for this generator + energyGenComp.requiredKey = this.getShapeRequiredForGenerator(entity); + } + } + } + + /** + * @param {DrawParameters} parameters + * @param {Entity} entity + */ + drawEntity(parameters, entity) { + const context = parameters.context; + const staticComp = entity.components.StaticMapEntity; + + if (!staticComp.shouldBeDrawn(parameters)) { + return; + } + + const energyGenComp = entity.components.EnergyGenerator; + if (!energyGenComp.requiredKey) { + // Not initialized yet + return; + } + + const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); + + // TESTING + const definition = ShapeDefinition.fromShortKey(energyGenComp.requiredKey); + definition.draw(pos.x, pos.y, parameters, 30); + + const energyGenerated = 5; + + // deliver: Deliver + // toGenerateEnergy: For energy + context.font = "bold 7px GameFont"; + context.fillStyle = "#64666e"; + context.textAlign = "left"; + context.fillText(T.buildings.energy_generator.deliver.toUpperCase(), pos.x - 25, pos.y - 18); + + context.fillText( + T.buildings.energy_generator.toGenerateEnergy.replace("", "" + energyGenerated).toUpperCase(), + pos.x - 25, + pos.y + 28 + ); + } +} diff --git a/src/js/game/systems/item_acceptor.js b/src/js/game/systems/item_acceptor.js index 69209ca9..f583f116 100644 --- a/src/js/game/systems/item_acceptor.js +++ b/src/js/game/systems/item_acceptor.js @@ -7,19 +7,17 @@ import { ItemAcceptorComponent } from "../components/item_acceptor"; import { Loader } from "../../core/loader"; import { drawRotatedSprite } from "../../core/draw_utils"; import { Math_radians } from "../../core/builtins"; +import { BELT_ANIM_COUNT } from "./belt"; export class ItemAcceptorSystem extends GameSystemWithFilter { constructor(root) { super(root, [ItemAcceptorComponent]); - this.underlayBeltSprites = [ - Loader.getSprite("sprites/belt/forward_0.png"), - Loader.getSprite("sprites/belt/forward_1.png"), - Loader.getSprite("sprites/belt/forward_2.png"), - Loader.getSprite("sprites/belt/forward_3.png"), - Loader.getSprite("sprites/belt/forward_4.png"), - Loader.getSprite("sprites/belt/forward_5.png"), - ]; + this.underlayBeltSprites = []; + + for (let i = 0; i < BELT_ANIM_COUNT; ++i) { + this.underlayBeltSprites.push(Loader.getSprite("sprites/belt/forward_" + i + ".png")); + } } update() { diff --git a/src/js/game/systems/item_ejector.js b/src/js/game/systems/item_ejector.js index 2f327725..b5da836a 100644 --- a/src/js/game/systems/item_ejector.js +++ b/src/js/game/systems/item_ejector.js @@ -1,12 +1,13 @@ +import { Math_min } from "../../core/builtins"; import { globalConfig } from "../../core/config"; import { DrawParameters } from "../../core/draw_parameters"; +import { createLogger } from "../../core/logging"; +import { Rectangle } from "../../core/rectangle"; import { enumDirectionToVector, Vector } from "../../core/vector"; import { BaseItem } from "../base_item"; import { ItemEjectorComponent } from "../components/item_ejector"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { Math_min } from "../../core/builtins"; -import { createLogger } from "../../core/logging"; const logger = createLogger("systems/ejector"); @@ -14,89 +15,162 @@ export class ItemEjectorSystem extends GameSystemWithFilter { constructor(root) { super(root, [ItemEjectorComponent]); + this.root.signals.entityAdded.add(this.checkForCacheInvalidation, this); + this.root.signals.entityDestroyed.add(this.checkForCacheInvalidation, this); + this.root.signals.postLoadHook.add(this.recomputeCache, this); + /** - * @type {Array<{ - * targetEntity: Entity, - * sourceSlot: import("../components/item_ejector").ItemEjectorSlot, - * destSlot: import("../components/item_acceptor").ItemAcceptorLocatedSlot - * }>} + * @type {Rectangle} */ - this.cache = []; - - this.cacheNeedsUpdate = true; - - this.root.signals.entityAdded.add(this.invalidateCache, this); - this.root.signals.entityDestroyed.add(this.invalidateCache, this); + this.areaToRecompute = null; } - invalidateCache() { - this.cacheNeedsUpdate = true; + /** + * + * @param {Entity} entity + */ + checkForCacheInvalidation(entity) { + if (!this.root.gameInitialized) { + return; + } + if (!entity.components.StaticMapEntity) { + return; + } + + // Optimize for the common case: adding or removing one building at a time. Clicking + // and dragging can cause up to 4 add/remove signals. + const staticComp = entity.components.StaticMapEntity; + const bounds = staticComp.getTileSpaceBounds(); + const expandedBounds = bounds.expandedInAllDirections(2); + + if (this.areaToRecompute) { + this.areaToRecompute = this.areaToRecompute.getUnion(expandedBounds); + } else { + this.areaToRecompute = expandedBounds; + } } /** * Precomputes the cache, which makes up for a huge performance improvement */ recomputeCache() { - logger.log("Recomputing cache"); - - const cache = []; - - // Try to find acceptors for every ejector - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const ejectorComp = entity.components.ItemEjector; - const staticComp = entity.components.StaticMapEntity; - - // For every ejector slot, try to find an acceptor - for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) { - const ejectorSlot = ejectorComp.slots[ejectorSlotIndex]; - - // Figure out where and into which direction we eject items - const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos); - const ejectSlotWsDirection = staticComp.localDirectionToWorld(ejectorSlot.direction); - const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection]; - const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector); - - // Try to find the given acceptor component to take the item - const targetEntity = this.root.map.getTileContent(ejectSlotTargetWsTile); - if (!targetEntity) { - // No consumer for item - continue; - } - - const targetAcceptorComp = targetEntity.components.ItemAcceptor; - const targetStaticComp = targetEntity.components.StaticMapEntity; - if (!targetAcceptorComp) { - // Entity doesn't accept items - continue; - } - - const matchingSlot = targetAcceptorComp.findMatchingSlot( - targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), - targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection) + if (this.areaToRecompute) { + logger.log("Recomputing cache using rectangle"); + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.root.hud.parts.changesDebugger.renderChange( + "ejector-area", + this.areaToRecompute, + "#fe50a6" ); + } + this.recomputeAreaCache(this.areaToRecompute); + this.areaToRecompute = null; + } else { + logger.log("Full cache recompute"); + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.root.hud.parts.changesDebugger.renderChange( + "ejector-full", + new Rectangle(-1000, -1000, 2000, 2000), + "#fe50a6" + ); + } - if (!matchingSlot) { - // No matching slot found - continue; - } - - // Ok we found a connection - cache.push({ - targetEntity, - sourceSlot: ejectorSlot, - destSlot: matchingSlot, - }); + // Try to find acceptors for every ejector + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + this.recomputeSingleEntityCache(entity); } } + } - this.cache = cache; - logger.log("Found", cache.length, "entries to update"); + /** + * + * @param {Rectangle} area + */ + recomputeAreaCache(area) { + let entryCount = 0; + + logger.log("Recomputing area:", area.x, area.y, "/", area.w, area.h); + + // Store the entities we already recomputed, so we don't do work twice + const recomputedEntities = new Set(); + + for (let x = area.x; x < area.right(); ++x) { + for (let y = area.y; y < area.bottom(); ++y) { + const entity = this.root.map.getTileContentXY(x, y); + if (entity) { + // Recompute the entity in case its relevant for this system and it + // hasn't already been computed + if (!recomputedEntities.has(entity.uid) && entity.components.ItemEjector) { + recomputedEntities.add(entity.uid); + this.recomputeSingleEntityCache(entity); + } + } + } + } + return entryCount; + } + + /** + * @param {Entity} entity + */ + recomputeSingleEntityCache(entity) { + const ejectorComp = entity.components.ItemEjector; + const staticComp = entity.components.StaticMapEntity; + + // Clear the old cache. + ejectorComp.cachedConnectedSlots = null; + + for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) { + const ejectorSlot = ejectorComp.slots[ejectorSlotIndex]; + + // Clear the old cache. + ejectorSlot.cachedDestSlot = null; + ejectorSlot.cachedTargetEntity = null; + + // Figure out where and into which direction we eject items + const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos); + const ejectSlotWsDirection = staticComp.localDirectionToWorld(ejectorSlot.direction); + const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection]; + const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector); + + // Try to find the given acceptor component to take the item + const targetEntity = this.root.map.getTileContent(ejectSlotTargetWsTile); + if (!targetEntity) { + // No consumer for item + continue; + } + + const targetAcceptorComp = targetEntity.components.ItemAcceptor; + const targetStaticComp = targetEntity.components.StaticMapEntity; + if (!targetAcceptorComp) { + // Entity doesn't accept items + continue; + } + + const matchingSlot = targetAcceptorComp.findMatchingSlot( + targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), + targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection) + ); + + if (!matchingSlot) { + // No matching slot found + continue; + } + + // Ok we found a connection + if (ejectorComp.cachedConnectedSlots) { + ejectorComp.cachedConnectedSlots.push(ejectorSlot); + } else { + ejectorComp.cachedConnectedSlots = [ejectorSlot]; + } + ejectorSlot.cachedTargetEntity = targetEntity; + ejectorSlot.cachedDestSlot = matchingSlot; + } } update() { - if (this.cacheNeedsUpdate) { - this.cacheNeedsUpdate = false; + if (this.areaToRecompute) { this.recomputeCache(); } @@ -109,35 +183,45 @@ export class ItemEjectorSystem extends GameSystemWithFilter { } // Go over all cache entries - for (let i = 0; i < this.cache.length; ++i) { - const { sourceSlot, destSlot, targetEntity } = this.cache[i]; - const item = sourceSlot.item; - - if (!item) { - // No item available to be ejected + for (let i = 0; i < this.allEntities.length; ++i) { + const sourceEntity = this.allEntities[i]; + const sourceEjectorComp = sourceEntity.components.ItemEjector; + if (!sourceEjectorComp.cachedConnectedSlots) { continue; } + for (let j = 0; j < sourceEjectorComp.cachedConnectedSlots.length; j++) { + const sourceSlot = sourceEjectorComp.cachedConnectedSlots[j]; + const destSlot = sourceSlot.cachedDestSlot; + const targetEntity = sourceSlot.cachedTargetEntity; - // Advance items on the slot - sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth); + const item = sourceSlot.item; - // Check if we are still in the process of ejecting, can't proceed then - if (sourceSlot.progress < 1.0) { - continue; - } + if (!item) { + // No item available to be ejected + continue; + } - // Check if the target acceptor can actually accept this item - const targetAcceptorComp = targetEntity.components.ItemAcceptor; - if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) { - continue; - } + // Advance items on the slot + sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth); - // Try to hand over the item - if (this.tryPassOverItem(item, targetEntity, destSlot.index)) { - // Handover successful, clear slot - targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item); - sourceSlot.item = null; - continue; + // Check if we are still in the process of ejecting, can't proceed then + if (sourceSlot.progress < 1.0) { + continue; + } + + // Check if the target acceptor can actually accept this item + const targetAcceptorComp = targetEntity.components.ItemAcceptor; + if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) { + continue; + } + + // Try to hand over the item + if (this.tryPassOverItem(item, targetEntity, destSlot.index)) { + // Handover successful, clear slot + targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item); + sourceSlot.item = null; + continue; + } } } } @@ -155,9 +239,9 @@ export class ItemEjectorSystem extends GameSystemWithFilter { const beltComp = receiver.components.Belt; if (beltComp) { - // Ayy, its a belt! - if (beltComp.canAcceptItem()) { - beltComp.takeItem(item); + const path = beltComp.assignedPath; + assert(path, "belt has no path"); + if (path.tryAcceptItem(item)) { return true; } } @@ -192,6 +276,14 @@ export class ItemEjectorSystem extends GameSystemWithFilter { } } + const energyGeneratorComp = receiver.components.EnergyGenerator; + if (energyGeneratorComp) { + if (energyGeneratorComp.tryTakeItem(item)) { + // Passed it over + return true; + } + } + return false; } diff --git a/src/js/game/systems/underground_belt.js b/src/js/game/systems/underground_belt.js index 5b308e25..0456638a 100644 --- a/src/js/game/systems/underground_belt.js +++ b/src/js/game/systems/underground_belt.js @@ -77,6 +77,7 @@ export class UndergroundBeltSystem extends GameSystemWithFilter { const tier = undergroundComp.tier; const range = globalConfig.undergroundBeltMaxTilesByTier[tier]; + // FIND ENTRANCE // Search for the entrance which is furthes apart (this is why we can't reuse logic here) let matchingEntrance = null; for (let i = 0; i < range; ++i) { @@ -104,31 +105,49 @@ export class UndergroundBeltSystem extends GameSystemWithFilter { return; } - // Remove any belts between entrance and exit which have the same direction + // DETECT OBSOLETE BELTS BETWEEN + // Remove any belts between entrance and exit which have the same direction, + // but only if they *all* have the right direction currentPos = tile.copy(); + let allBeltsMatch = true; for (let i = 0; i < matchingEntrance.range; ++i) { currentPos.addInplace(offset); const contents = this.root.map.getTileContent(currentPos); if (!contents) { - continue; + allBeltsMatch = false; + break; } const contentsStaticComp = contents.components.StaticMapEntity; const contentsBeltComp = contents.components.Belt; + if (!contentsBeltComp) { + allBeltsMatch = false; + break; + } - if (contentsBeltComp) { - // It's a belt - if ( - contentsBeltComp.direction === enumDirection.top && - enumAngleToDirection[contentsStaticComp.rotation] === direction - ) { - // It's same rotation, drop it - this.root.logic.tryDeleteBuilding(contents); - } + // It's a belt + if ( + contentsBeltComp.direction !== enumDirection.top || + enumAngleToDirection[contentsStaticComp.rotation] !== direction + ) { + allBeltsMatch = false; + break; } } + currentPos = tile.copy(); + if (allBeltsMatch) { + // All belts between this are obsolete, so drop them + for (let i = 0; i < matchingEntrance.range; ++i) { + currentPos.addInplace(offset); + const contents = this.root.map.getTileContent(currentPos); + assert(contents, "Invalid smart underground belt logic"); + this.root.logic.tryDeleteBuilding(contents); + } + } + + // REMOVE OBSOLETE TUNNELS // Remove any double tunnels, by checking the tile plus the tile above currentPos = tile.copy().add(offset); for (let i = 0; i < matchingEntrance.range - 1; ++i) { diff --git a/src/js/game/systems/wired_pins.js b/src/js/game/systems/wired_pins.js new file mode 100644 index 00000000..44e062b0 --- /dev/null +++ b/src/js/game/systems/wired_pins.js @@ -0,0 +1,51 @@ +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { WiredPinsComponent } from "../components/wired_pins"; +import { DrawParameters } from "../../core/draw_parameters"; +import { Entity } from "../entity"; +import { THEME } from "../theme"; + +export class WiredPinsSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [WiredPinsComponent]); + } + + update() { + // TODO + } + + drawWiresLayer(parameters) { + this.forEachMatchingEntityOnScreen(parameters, this.drawEntityPins.bind(this)); + } + + /** + * + * @param {DrawParameters} parameters + * @param {Entity} entity + */ + drawEntityPins(parameters, entity) { + const staticComp = entity.components.StaticMapEntity; + + if (!staticComp.shouldBeDrawn(parameters)) { + return; + } + + const pinsComp = entity.components.WiredPins; + + const slots = pinsComp.slots; + + for (let i = 0; i < slots.length; ++i) { + const slot = slots[i]; + const tile = staticComp.localTileToWorld(slot.pos); + + const worldPos = tile.toWorldSpaceCenterOfTile(); + + parameters.context.fillStyle = THEME.map.wires.pins[slot.type]; + parameters.context.beginCircle(worldPos.x, worldPos.y, 5); + parameters.context.fill(); + + parameters.context.lineWidth = 2; + parameters.context.fillStyle = "rgba(0, 0, 0, 0.1)"; + parameters.context.stroke(); + } + } +} diff --git a/src/js/game/themes/dark.json b/src/js/game/themes/dark.json index ef707663..231e4bcd 100644 --- a/src/js/game/themes/dark.json +++ b/src/js/game/themes/dark.json @@ -12,6 +12,8 @@ "directionLock": "rgb(74, 237, 134)", "directionLockTrack": "rgba(74, 237, 134, 0.2)", + "colorBlindPickerTile": "rgba(255, 255, 255, 0.5)", + "resources": { "shape": "#3d3f4a", "red": "#4a3d3f", @@ -21,11 +23,19 @@ "chunkOverview": { "empty": "#444856", "filled": "#646b7d" + }, + + "wires": { + "overlay": "rgba(52, 150, 128, 0.5)", + "pins": { + "energyEjector": "#c425d7" + } } }, "items": { "outline": "#111418", - "outlineWidth": 0.75 + "outlineWidth": 0.75, + "circleBackground": "rgba(20, 30, 40, 0.3)" } } diff --git a/src/js/game/themes/light.json b/src/js/game/themes/light.json index c5eead32..1356a2b6 100644 --- a/src/js/game/themes/light.json +++ b/src/js/game/themes/light.json @@ -12,6 +12,8 @@ "directionLock": "rgb(74, 237, 134)", "directionLockTrack": "rgba(74, 237, 134, 0.2)", + "colorBlindPickerTile": "rgba(50, 50, 50, 0.4)", + "resources": { "shape": "#eaebec", "red": "#ffbfc1", @@ -22,11 +24,19 @@ "chunkOverview": { "empty": "#a6afbb", "filled": "#c5ccd6" + }, + + "wires": { + "overlay": "rgba(52, 150, 128, 0.8)", + "pins": { + "energyEjector": "#c425d7" + } } }, "items": { "outline": "#55575a", - "outlineWidth": 0.75 + "outlineWidth": 0.75, + "circleBackground": "rgba(40, 50, 65, 0.1)" } } diff --git a/src/js/game/tutorial_goals.js b/src/js/game/tutorial_goals.js index c7fa581b..67ca17d7 100644 --- a/src/js/game/tutorial_goals.js +++ b/src/js/game/tutorial_goals.js @@ -23,6 +23,8 @@ export const enumHubGoalRewards = { reward_painter_quad: "reward_painter_quad", reward_storage: "reward_storage", + reward_wires: "reward_wires", + reward_blueprints: "reward_blueprints", reward_freeplay: "reward_freeplay", @@ -163,6 +165,13 @@ export const tutorialGoals = [ { shape: finalGameShape, required: 250000, + reward: enumHubGoalRewards.reward_wires, + }, + + // 19 + { + shape: finalGameShape, + required: 1, reward: enumHubGoalRewards.reward_freeplay, }, ]; diff --git a/src/js/globals.d.ts b/src/js/globals.d.ts index dc2246d0..bc99d55e 100644 --- a/src/js/globals.d.ts +++ b/src/js/globals.d.ts @@ -1,7 +1,6 @@ // Globals defined by webpack declare const G_IS_DEV: boolean; -declare const G_IS_PROD: boolean; declare function assert(condition: boolean | object | string, ...errorMessage: string[]): void; declare function assertAlways(condition: boolean | object | string, ...errorMessage: string[]): void; diff --git a/src/js/languages.js b/src/js/languages.js index 2d40037b..cac22bcf 100644 --- a/src/js/languages.js +++ b/src/js/languages.js @@ -51,10 +51,10 @@ export const LANGUAGES = { region: "", }, "es-419": { - name: "Español (Latinoamérica)", + name: "Español", data: require("./built-temp/base-es.json"), code: "es", - region: "419", + region: "", }, "pl": { name: "Polski", @@ -80,10 +80,27 @@ export const LANGUAGES = { code: "no", region: "", }, + "zh-CN": { - name: "简体中文", + // simplified + name: "中文简体", data: require("./built-temp/base-zh-CN.json"), code: "zh", region: "CN", }, + + "zh-TW": { + // traditional + name: "中文繁體", + data: require("./built-temp/base-zh-TW.json"), + code: "zh", + region: "TW", + }, + + "sv": { + name: "Svenska", + data: require("./built-temp/base-sv.json"), + code: "sv", + region: "", + }, }; diff --git a/src/js/platform/browser/game_analytics.js b/src/js/platform/browser/game_analytics.js index be1a8940..73da3696 100644 --- a/src/js/platform/browser/game_analytics.js +++ b/src/js/platform/browser/game_analytics.js @@ -1,11 +1,12 @@ -import { GameAnalyticsInterface } from "../game_analytics"; -import { createLogger } from "../../core/logging"; -import { ShapeDefinition } from "../../game/shape_definition"; -import { Savegame } from "../../savegame/savegame"; -import { FILE_NOT_FOUND } from "../storage"; import { globalConfig } from "../../core/config"; -import { InGameState } from "../../states/ingame"; +import { createLogger } from "../../core/logging"; import { GameRoot } from "../../game/root"; +import { InGameState } from "../../states/ingame"; +import { GameAnalyticsInterface } from "../game_analytics"; +import { FILE_NOT_FOUND } from "../storage"; +import { blueprintShape, UPGRADES } from "../../game/upgrades"; +import { tutorialGoals } from "../../game/tutorial_goals"; +import { BeltComponent } from "../../game/components/belt"; import { StaticMapEntityComponent } from "../../game/components/static_map_entity"; const logger = createLogger("game_analytics"); @@ -14,16 +15,32 @@ const analyticsUrl = G_IS_DEV ? "http://localhost:8001" : "https://analytics.sha // Be sure to increment the ID whenever it changes to make sure all // users are tracked -const analyticsLocalFile = "analytics_token.3.bin"; +const analyticsLocalFile = "shapez_token_123.bin"; export class ShapezGameAnalytics extends GameAnalyticsInterface { + get environment() { + if (G_IS_DEV) { + return "dev"; + } + + if (G_IS_STANDALONE) { + return "steam"; + } + + if (G_IS_RELEASE) { + return "prod"; + } + + return "beta"; + } + /** * @returns {Promise} */ initialize() { this.syncKey = null; - setInterval(() => this.sendTimePoints(), 120 * 1000); + setInterval(() => this.sendTimePoints(), 60 * 1000); // Retrieve sync key from player return this.app.storage.readFileAsync(analyticsLocalFile).then( @@ -38,7 +55,7 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { // Perform call to get a new key from the API this.sendToApi("/v1/register", { - environment: G_APP_ENVIRONMENT, + environment: this.environment, }) .then(res => { // Try to read and parse the key from the api @@ -135,10 +152,12 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { playerKey: this.syncKey, gameKey: savegameId, ingameTime: root.time.now(), + environment: this.environment, category, value, version: G_BUILD_VERSION, - gameDump: this.generateGameDump(root, category === "sync"), + level: root.hubGoals.level, + gameDump: this.generateGameDump(root), }); } @@ -151,52 +170,58 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { } /** - * Generates a game dump - * @param {GameRoot} root - * @param {boolean=} metaOnly + * Returns true if the shape is interesting + * @param {string} key */ - generateGameDump(root, metaOnly = false) { - let staticEntities = []; + isInterestingShape(key) { + if (key === blueprintShape) { + return true; + } - const entities = root.entityMgr.getAllWithComponent(StaticMapEntityComponent); - - // Limit the entities - if (!metaOnly && entities.length < 500) { - for (let i = 0; i < entities.length; ++i) { - const entity = entities[i]; - const staticComp = entity.components.StaticMapEntity; - const payload = {}; - payload.origin = staticComp.origin; - payload.tileSize = staticComp.tileSize; - payload.rotation = staticComp.rotation; - - if (entity.components.Belt) { - payload.type = "belt"; - } else if (entity.components.UndergroundBelt) { - payload.type = "tunnel"; - } else if (entity.components.ItemProcessor) { - payload.type = entity.components.ItemProcessor.type; - } else if (entity.components.Miner) { - payload.type = "extractor"; - } else { - logger.warn("Unkown entity type", entity); - } - staticEntities.push(payload); + // Check if its a story goal + for (let i = 0; i < tutorialGoals.length; ++i) { + if (key === tutorialGoals[i].shape) { + return true; } } - return { - storedShapes: root.hubGoals.storedShapes, - gainedRewards: root.hubGoals.gainedRewards, - upgradeLevels: root.hubGoals.upgradeLevels, - staticEntities, - }; + // Check if its required to unlock an upgrade + for (const upgradeKey in UPGRADES) { + const handle = UPGRADES[upgradeKey]; + const tiers = handle.tiers; + for (let i = 0; i < tiers.length; ++i) { + const tier = tiers[i]; + const required = tier.required; + for (let k = 0; k < required.length; ++k) { + if (required[k].shape === key) { + return true; + } + } + } + } + + return false; } /** - * @param {ShapeDefinition} definition + * Generates a game dump + * @param {GameRoot} root */ - handleShapeDelivered(definition) {} + generateGameDump(root) { + const shapeIds = Object.keys(root.hubGoals.storedShapes).filter(this.isInterestingShape.bind(this)); + let shapes = {}; + for (let i = 0; i < shapeIds.length; ++i) { + shapes[shapeIds[i]] = root.hubGoals.storedShapes[shapeIds[i]]; + } + return { + shapes, + upgrades: root.hubGoals.upgradeLevels, + belts: root.entityMgr.getAllWithComponent(BeltComponent).length, + buildings: + root.entityMgr.getAllWithComponent(StaticMapEntityComponent).length - + root.entityMgr.getAllWithComponent(BeltComponent).length, + }; + } /** */ @@ -204,6 +229,12 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { this.sendGameEvent("game_start", ""); } + /** + */ + handleGameResumed() { + this.sendTimePoints(); + } + /** * Handles the given level completed * @param {number} level diff --git a/src/js/platform/game_analytics.js b/src/js/platform/game_analytics.js index c3e2fa64..ea6aa293 100644 --- a/src/js/platform/game_analytics.js +++ b/src/js/platform/game_analytics.js @@ -25,9 +25,9 @@ export class GameAnalyticsInterface { handleGameStarted() {} /** - * @param {ShapeDefinition} definition + * Handles a resumed game */ - handleShapeDelivered(definition) {} + handleGameResumed() {} /** * Handles the given level completed diff --git a/src/js/platform/sound.js b/src/js/platform/sound.js index dc6b073f..60d472f8 100644 --- a/src/js/platform/sound.js +++ b/src/js/platform/sound.js @@ -22,6 +22,7 @@ export const SOUNDS = { levelComplete: "level_complete", + destroyBuilding: "destroy_building", placeBuilding: "place_building", placeBelt: "place_belt", }; diff --git a/src/js/profile/application_settings.js b/src/js/profile/application_settings.js index 796337fe..7f80cd89 100644 --- a/src/js/profile/application_settings.js +++ b/src/js/profile/application_settings.js @@ -89,6 +89,33 @@ export const movementSpeeds = [ }, ]; +export const autosaveIntervals = [ + { + id: "one_minute", + seconds: 60, + }, + { + id: "two_minutes", + seconds: 120, + }, + { + id: "five_minutes", + seconds: 5 * 60, + }, + { + id: "ten_minutes", + seconds: 10 * 60, + }, + { + id: "twenty_minutes", + seconds: 20 * 60, + }, + { + id: "disabled", + seconds: null, + }, +]; + /** @type {Array} */ export const allApplicationSettings = [ new EnumSetting("language", { @@ -145,6 +172,15 @@ export const allApplicationSettings = [ (app, value) => app.sound.setMusicMuted(value) ), + new BoolSetting( + "enableColorBlindHelper", + categoryApp, + /** + * @param {Application} app + */ + (app, value) => null + ), + // GAME new BoolSetting("offerHints", categoryGame, (app, value) => {}), @@ -165,8 +201,21 @@ export const allApplicationSettings = [ enabled: !IS_DEMO, }), + new EnumSetting("autosaveInterval", { + options: autosaveIntervals, + valueGetter: interval => interval.id, + textGetter: interval => T.settings.labels.autosaveInterval.intervals[interval.id], + category: categoryGame, + restartRequired: false, + changeCb: + /** + * @param {Application} app + */ + (app, id) => null, + }), + new EnumSetting("refreshRate", { - options: ["60", "100", "144", "165", "250", "500"], + options: ["60", "100", "144", "165", "250", G_IS_DEV ? "10" : "500"], valueGetter: rate => rate, textGetter: rate => rate + " Hz", category: categoryGame, @@ -201,6 +250,8 @@ export const allApplicationSettings = [ new BoolSetting("enableTunnelSmartplace", categoryGame, (app, value) => {}), new BoolSetting("vignette", categoryGame, (app, value) => {}), new BoolSetting("compactBuildingInfo", categoryGame, (app, value) => {}), + new BoolSetting("disableCutDeleteWarnings", categoryGame, (app, value) => {}), + new BoolSetting("rotationByBuilding", categoryGame, (app, value) => {}), new BoolSetting("abortPlacementOnDeletion", categoryGame, (app, value) => {}), ]; @@ -220,12 +271,16 @@ class SettingsStorage { this.scrollWheelSensitivity = "regular"; this.movementSpeed = "regular"; this.language = "auto-detect"; + this.autosaveInterval = "two_minutes"; this.alwaysMultiplace = false; this.offerHints = true; this.enableTunnelSmartplace = true; this.vignette = true; this.compactBuildingInfo = false; + this.disableCutDeleteWarnings = false; + this.rotationByBuilding = true; + this.enableColorBlindHelper = false; this.abortPlacementOnDeletion = true; /** @@ -321,6 +376,17 @@ export class ApplicationSettings extends ReadWriteProxy { return 1; } + getAutosaveIntervalSeconds() { + const id = this.getAllSettings().autosaveInterval; + for (let i = 0; i < autosaveIntervals.length; ++i) { + if (autosaveIntervals[i].id === id) { + return autosaveIntervals[i].seconds; + } + } + logger.error("Unknown autosave interval id:", id); + return 120; + } + getIsFullScreen() { return this.getAllSettings().fullscreen; } @@ -416,7 +482,7 @@ export class ApplicationSettings extends ReadWriteProxy { } getCurrentVersion() { - return 14; + return 19; } /** @param {{settings: SettingsStorage, version: number}} data */ @@ -469,10 +535,36 @@ export class ApplicationSettings extends ReadWriteProxy { } if (data.version < 14) { - data.settings.abortPlacementOnDeletion = true; + data.settings.disableCutDeleteWarnings = false; data.version = 14; } + if (data.version < 15) { + data.settings.autosaveInterval = "two_minutes"; + data.version = 15; + } + + if (data.version < 16) { + // RE-ENABLE this setting, it already existed + data.settings.enableTunnelSmartplace = true; + data.version = 16; + } + + if (data.version < 17) { + data.settings.enableColorBlindHelper = false; + data.version = 17; + } + + if (data.version < 18) { + data.settings.rotationByBuilding = true; + data.version = 18; + } + + if (data.version < 19) { + data.settings.abortPlacementOnDeletion = true; + data.version = 19; + } + return ExplainedResult.good(); } } diff --git a/src/js/savegame/savegame.js b/src/js/savegame/savegame.js index 359a48b5..d5395dce 100644 --- a/src/js/savegame/savegame.js +++ b/src/js/savegame/savegame.js @@ -14,6 +14,7 @@ import { SavegameInterface_V1001 } from "./schemas/1001"; import { SavegameInterface_V1002 } from "./schemas/1002"; import { SavegameInterface_V1003 } from "./schemas/1003"; import { SavegameInterface_V1004 } from "./schemas/1004"; +import { SavegameInterface_V1005 } from "./schemas/1005"; const logger = createLogger("savegame"); @@ -45,7 +46,7 @@ export class Savegame extends ReadWriteProxy { * @returns {number} */ static getCurrentVersion() { - return 1004; + return 1005; } /** @@ -104,6 +105,11 @@ export class Savegame extends ReadWriteProxy { data.version = 1004; } + if (data.version === 1004) { + SavegameInterface_V1005.migrate1004to1005(data); + data.version = 1005; + } + return ExplainedResult.good(); } diff --git a/src/js/savegame/savegame_interface_registry.js b/src/js/savegame/savegame_interface_registry.js index 6144ca62..fb1df52f 100644 --- a/src/js/savegame/savegame_interface_registry.js +++ b/src/js/savegame/savegame_interface_registry.js @@ -5,6 +5,7 @@ import { SavegameInterface_V1001 } from "./schemas/1001"; import { SavegameInterface_V1002 } from "./schemas/1002"; import { SavegameInterface_V1003 } from "./schemas/1003"; import { SavegameInterface_V1004 } from "./schemas/1004"; +import { SavegameInterface_V1005 } from "./schemas/1005"; /** @type {Object.} */ export const savegameInterfaces = { @@ -13,6 +14,7 @@ export const savegameInterfaces = { 1002: SavegameInterface_V1002, 1003: SavegameInterface_V1003, 1004: SavegameInterface_V1004, + 1005: SavegameInterface_V1005, }; const logger = createLogger("savegame_interface_registry"); diff --git a/src/js/savegame/savegame_serializer.js b/src/js/savegame/savegame_serializer.js index 52a59528..59675668 100644 --- a/src/js/savegame/savegame_serializer.js +++ b/src/js/savegame/savegame_serializer.js @@ -40,6 +40,7 @@ export class SavegameSerializer { hubGoals: root.hubGoals.serialize(), pinnedShapes: root.hud.parts.pinnedShapes.serialize(), waypoints: root.hud.parts.waypoints.serialize(), + beltPaths: root.systemMgr.systems.belt.serializePaths(), }; data.entities = this.internal.serializeEntityArray(root.entityMgr.entities); @@ -140,6 +141,7 @@ export class SavegameSerializer { errorReason = errorReason || root.hud.parts.pinnedShapes.deserialize(savegame.pinnedShapes); errorReason = errorReason || root.hud.parts.waypoints.deserialize(savegame.waypoints); errorReason = errorReason || this.internal.deserializeEntityArray(root, savegame.entities); + errorReason = errorReason || root.systemMgr.systems.belt.deserializePaths(savegame.beltPaths); // Check for errors if (errorReason) { diff --git a/src/js/savegame/savegame_typedefs.js b/src/js/savegame/savegame_typedefs.js index 6211150f..642865cd 100644 --- a/src/js/savegame/savegame_typedefs.js +++ b/src/js/savegame/savegame_typedefs.js @@ -5,6 +5,10 @@ import { Entity } from "../game/entity"; * }} SavegameStats */ +/** + * + */ + /** * @typedef {{ * camera: any, @@ -14,7 +18,8 @@ import { Entity } from "../game/entity"; * hubGoals: any, * pinnedShapes: any, * waypoints: any, - * entities: Array + * entities: Array, + * beltPaths: Array * }} SerializedGame */ diff --git a/src/js/savegame/schemas/1005.js b/src/js/savegame/schemas/1005.js new file mode 100644 index 00000000..f86a280d --- /dev/null +++ b/src/js/savegame/schemas/1005.js @@ -0,0 +1,29 @@ +import { createLogger } from "../../core/logging.js"; +import { SavegameInterface_V1004 } from "./1004.js"; + +const schema = require("./1005.json"); +const logger = createLogger("savegame_interface/1005"); + +export class SavegameInterface_V1005 extends SavegameInterface_V1004 { + getVersion() { + return 1005; + } + + getSchemaUncached() { + return schema; + } + + /** + * @param {import("../savegame_typedefs.js").SavegameData} data + */ + static migrate1004to1005(data) { + logger.log("Migrating 1004 to 1005"); + const dump = data.dump; + if (!dump) { + return true; + } + + // just reset belt paths for now + dump.beltPaths = []; + } +} diff --git a/src/js/savegame/schemas/1005.json b/src/js/savegame/schemas/1005.json new file mode 100644 index 00000000..6682f615 --- /dev/null +++ b/src/js/savegame/schemas/1005.json @@ -0,0 +1,5 @@ +{ + "type": "object", + "required": [], + "additionalProperties": true +} diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js index a5901a3d..33d7e15b 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -217,7 +217,6 @@ export class InGameState extends GameState { this.core.initializeRoot(this, this.savegame); if (this.savegame.hasGameDump()) { - this.app.gameAnalytics.handleGameStarted(); this.stage4bResumeGame(); } else { this.app.gameAnalytics.handleGameStarted(); @@ -245,6 +244,7 @@ export class InGameState extends GameState { this.onInitializationFailure("Savegame is corrupt and can not be restored."); return; } + this.app.gameAnalytics.handleGameResumed(); this.stage5FirstUpdate(); } } diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index 8665b80e..8f7d4a93 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -9,6 +9,7 @@ import { waitNextFrame, isSupportedBrowser, makeButton, + removeAllChildren, } from "../core/utils"; import { ReadWriteProxy } from "../core/read_write_proxy"; import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; @@ -72,6 +73,7 @@ export class MainMenuState extends GameState { ? "" : `
${T.mainMenu.browserWarning}
` } +
@@ -89,10 +91,14 @@ export class MainMenuState extends GameState { - ${T.changelog.title} - - ${T.mainMenu.helpTranslate} + +
${T.mainMenu.madeBy.replace( "", 'Tobias Springer' @@ -148,6 +154,7 @@ export class MainMenuState extends GameState { T.dialogs.importSavegameSuccess.text ); + this.renderMainMenu(); this.renderSavegames(); }, err => { @@ -212,6 +219,7 @@ export class MainMenuState extends GameState { this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked); this.trackClicks(qs(".changelog"), this.onChangelogClicked); + this.trackClicks(qs(".redditLink"), this.onRedditClicked); this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked); this.trackClicks(qs(".helpTranslate"), this.onTranslationHelpLinkClicked); @@ -255,6 +263,10 @@ export class MainMenuState extends GameState { } renderMainMenu() { + const buttonContainer = this.htmlElement.querySelector(".mainContainer .buttons"); + removeAllChildren(buttonContainer); + + // Import button const importButtonElement = makeButtonElement( ["importButton", "styledButton"], T.mainMenu.importSavegame @@ -262,14 +274,15 @@ export class MainMenuState extends GameState { this.trackClicks(importButtonElement, this.requestImportSavegame); if (this.savedGames.length > 0) { + // Continue game const continueButton = makeButton( - this.htmlElement.querySelector(".mainContainer"), + buttonContainer, ["continueButton", "styledButton"], T.mainMenu.continue ); this.trackClicks(continueButton, this.onContinueButtonClicked); - const outerDiv = makeDiv(this.htmlElement.querySelector(".mainContainer"), null, ["outer"], null); + const outerDiv = makeDiv(buttonContainer, null, ["outer"], null); outerDiv.appendChild(importButtonElement); const newGameButton = makeButton( this.htmlElement.querySelector(".mainContainer .outer"), @@ -277,24 +290,11 @@ export class MainMenuState extends GameState { T.mainMenu.newGame ); this.trackClicks(newGameButton, this.onPlayButtonClicked); - - const oldPlayButton = this.htmlElement.querySelector(".mainContainer .playButton"); - if (oldPlayButton) oldPlayButton.remove(); } else { - const playBtn = makeButton( - this.htmlElement.querySelector(".mainContainer"), - ["playButton", "styledButton"], - T.mainMenu.play - ); + // New game + const playBtn = makeButton(buttonContainer, ["playButton", "styledButton"], T.mainMenu.play); this.trackClicks(playBtn, this.onPlayButtonClicked); - - this.htmlElement.querySelector(".mainContainer").appendChild(importButtonElement); - - const outerDiv = this.htmlElement.querySelector(".mainContainer .outer"); - if (outerDiv) { - outerDiv.remove(); - this.htmlElement.querySelector(".mainContainer .continueButton").remove(); - } + buttonContainer.appendChild(importButtonElement); } } @@ -312,6 +312,11 @@ export class MainMenuState extends GameState { this.moveToState("ChangelogState"); } + onRedditClicked() { + this.app.analytics.trackUiClick("main_menu_reddit_link"); + this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.reddit); + } + onContestClicked() { this.app.analytics.trackUiClick("contest_click"); diff --git a/sync-translations.js b/sync-translations.js index afe78cfe..4815704d 100644 --- a/sync-translations.js +++ b/sync-translations.js @@ -21,7 +21,7 @@ const placeholderRegexp = /<([a-zA-Z_0-9]+)>/gi; function match(originalObj, translatedObj, path = "/") { for (const key in originalObj) { - if (!translatedObj[key]) { + if (!translatedObj.hasOwnProperty(key)) { console.warn(" | Missing key", path + key); translatedObj[key] = originalObj[key]; continue; @@ -60,7 +60,7 @@ function match(originalObj, translatedObj, path = "/") { } for (const key in translatedObj) { - if (!originalObj[key]) { + if (!originalObj.hasOwnProperty(key)) { console.warn(" | Obsolete key", path + key); delete translatedObj[key]; } diff --git a/translations/README.md b/translations/README.md index e799926c..6e46a6fe 100644 --- a/translations/README.md +++ b/translations/README.md @@ -27,6 +27,7 @@ The base translation is `base-en.yaml`. It will always contain the latest phrase - [Arabic](base-ar.yaml) - [Norwegian](base-no.yaml) - [Kroatian](base-hr.yaml) +- [Danish](base-da.yaml) (If you want to translate into a new language, see below!) diff --git a/translations/base-ar.yaml b/translations/base-ar.yaml index 90ea23a9..9e10dd65 100644 --- a/translations/base-ar.yaml +++ b/translations/base-ar.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,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 @@ -398,6 +398,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -518,7 +531,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -686,6 +699,42 @@ settings: description: >- Enables the vignette which darkens the screen corners and makes text easier to read. + + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -731,7 +780,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -751,7 +799,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: About this Game diff --git a/translations/base-cz.yaml b/translations/base-cz.yaml index 5771bc9c..dd34958c 100644 --- a/translations/base-cz.yaml +++ b/translations/base-cz.yaml @@ -134,9 +134,10 @@ mainMenu: showInfo: Zobrazit contestOver: Tato soutěž skončila - Připojte se na Discord a získejte informace o nových soutěžích! - continue: Continue - newGame: New Game - madeBy: Made by + continue: Pokračovat + newGame: Nová hra + madeBy: Vytvořil + subreddit: Reddit dialogs: buttons: @@ -266,8 +267,12 @@ ingame: createMarker: Vytvořit značku delete: Zničit pasteLastBlueprint: Vložit poslední plán - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + lockBeltDirection: Zamknout směr pásu + plannerSwitchSide: Otočit strany plánovače + cutSelection: Vyjmout + copySelection: Kopířovat + clearSelection: Zrušit výběr + pipette: Kapátko # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -303,11 +308,6 @@ ingame: newUpgrade: Nová aktualizace je k dispozici! gameSaved: Hra byla uložena. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Stiskni pro vyjmutí, pro kopírování a pro zbourání. ruší výběr. - # The "Upgrades" window shop: title: Vylepšení @@ -379,6 +379,19 @@ ingame: 1_3_expand: >- Toto NENÍ hra o čekání! Sestavte další extraktory a pásy, abyste dosáhli cíle rychleji.

Tip: Chcete-li umístit více extraktorů, podržte SHIFT. Pomocí R je můžete otočit. + colors: + red: Červená + green: Zelená + blue: Modrá + yellow: Žlutá + purple: Fialová + cyan: Tyrkysová + white: Bílá + uncolored: Bez barvy + shapeViewer: + title: Vrstvy + empty: Prázdné + # All shop upgrades shopUpgrades: belt: @@ -499,7 +512,7 @@ storyRewards: reward_painter: title: Barvení desc: >- - Barvič byl právě odemčen - vytěžte nějakou barvu (stejně jako těžíte tvary) a skombinujte ji v barviči s tvarem pro obarvení!

PS: Pokud jste barvoslepí, nebojte, již pracuju na řešení.! + 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, there is a color blind mode in the settings! reward_mixer: title: Míchání barev @@ -583,7 +596,7 @@ settings: labels: uiScale: - title: Škála UI + title: Škálování UI description: >- Změní velikost uživatelského rozhraní. Rozhraní se bude stále přizpůsobovoat rozlišení vaší obrazovky, toto nastavení pouze mění jeho škálu. scales: @@ -659,15 +672,48 @@ settings: super_fast: Hodně Rychlá extremely_fast: Extrémně Rychlá enableTunnelSmartplace: - title: Smart Tunnels + title: Chytré tunely description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + Pokládání tunelů po zapnutí bude samo odstraňovat nepotřebné pásy. + Umožňuje také potahování tunelů a nadbytečné tunely budou odstraněny. vignette: - title: Vignette + title: Viněta description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Zapne vinětu, která ztmaví rohy obrazovky, což umožňuje lepší čtení textu. + + autosaveInterval: + title: Interval automatického ukládání + description: >- + Určuje jak často se hra automaticky ukládá. Lze ji zde také úplně zakázat. + intervals: + one_minute: 1 minuta + two_minutes: 2 minuty + five_minutes: 5 minut + ten_minutes: 10 minut + twenty_minutes: 20 minut + disabled: Zrušeno + + compactBuildingInfo: + title: Kompaktní informace o stavbách + description: >- + Zkrátí informační políčka pro budovy tím, že pouze ukáže jejich koeficient. + V opačném případě zobrazí popis a obrázek. + + disableCutDeleteWarnings: + title: Zakázat upozornění o vyjmutí nebo odstranění + description: >- + Deaktivujte varovná dialogová okna vyvolaná při vymutí/mazání více než 100 + entit. + + enableColorBlindHelper: + title: Režim pro barvoslepé + description: Zapné různé nástroje, které vám umožní hrát hru i pokud jste barvoslepí. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. keybindings: title: Klávesové zkratky @@ -715,7 +761,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Zrušit stavbu rotateWhilePlacing: Otočit rotateInverseModifier: >- Modifikátor: Otočit proti směru hodinových ručiček @@ -733,8 +778,9 @@ keybindings: pasteLastBlueprint: Vložit poslední plán massSelectCut: Vyjmout oblast exportScreenshot: Exportovat celou základnu jako obrázek - lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + lockBeltDirection: Zamknout směr pásu + switchDirectionLockSide: Otočit strany zámku plánovače + pipette: Kapátko about: title: O hře diff --git a/translations/base-da.yaml b/translations/base-da.yaml new file mode 100644 index 00000000..930e5f29 --- /dev/null +++ b/translations/base-da.yaml @@ -0,0 +1,848 @@ +# +# 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 + subreddit: Reddit + 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: Delete + pasteLastBlueprint: Paste last blueprint + lockBeltDirection: Enable belt planner + plannerSwitchSide: Flip planner side + cutSelection: Cut + copySelection: Copy + clearSelection: Clear Selection + pipette: Pipette + switchLayers: Switch Layers + + # Names of the colors, used for the color blind mode + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + + # 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. + + # 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. + + # Shape viewer + shapeViewer: + title: Layers + empty: Empty + copyKey: Copy Key + + # 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. + + energy_generator: + deliver: Deliver + toGenerateEnergy: For energy + + default: + name: &energy_generator Energy Generator + description: Generates energy by consuming shapes. Each energy generator requires a different shapes. + +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, there is a color blind mode in the settings! + + 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! + + reward_wires: + title: Wires + desc: TODO + + 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 + + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it entirely here. + + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + + 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! + + enableColorBlindHelper: + title: Color Blind Mode + description: >- + Enables various tools which allow to play the game if you are color blind. + + 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. + + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 entities. + +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 + switchLayers: Switch layers + exportScreenshot: Export whole Base as Image + belt: *belt + splitter: *splitter + underground_belt: *underground_belt + miner: *miner + cutter: *cutter + rotater: *rotater + stacker: *stacker + mixer: *mixer + energy_generator: *energy_generator + painter: *painter + trash: *trash + + pipette: Pipette + rotateWhilePlacing: Rotate + rotateInverseModifier: >- + Modifier: Rotate CCW instead + cycleBuildingVariants: Cycle Variants + confirmMassDelete: Delete area + 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-de.yaml b/translations/base-de.yaml index 73efe45c..057020ea 100644 --- a/translations/base-de.yaml +++ b/translations/base-de.yaml @@ -155,6 +155,7 @@ mainMenu: continue: Fortsetzen newGame: Neues Spiel madeBy: Ein Spiel von + subreddit: Reddit dialogs: buttons: @@ -283,14 +284,18 @@ ingame: delete: Löschen pasteLastBlueprint: Letzte Blaupause einfügen lockBeltDirection: Bandplaner aktivieren - plannerSwitchSide: 'Planer: Seite wechseln' + plannerSwitchSide: "Planer: Seite wechseln" + cutSelection: Ausschneiden + copySelection: Kopieren + clearSelection: Auswahl aufheben + pipette: Pipette # 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: Wechsle Variante # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- @@ -319,11 +324,6 @@ ingame: newUpgrade: Ein neues Upgrade ist verfügbar! gameSaved: Dein Spiel wurde gespeichert. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Drücke zum Ausschneiden, zum Kopieren, zum Entfernen und um Abzubrechen. - # The "Upgrades" window shop: title: Upgrades @@ -395,6 +395,19 @@ ingame: 1_3_expand: >- Dies ist KEIN Idle-Game! Baue mehr Extrahierer und Förderbänder, um das Ziel schneller zu erreichen.

Tipp: Halte UMSCH, um mehrere Gebäude zu platzieren und nutze R um sie zu rotieren. + colors: + red: Rot + green: Grün + blue: Blau + yellow: Gelb + purple: Violett + cyan: Cyan + white: Weiß + uncolored: Farblos + shapeViewer: + title: Ebenen + empty: Leer + # All shop upgrades shopUpgrades: belt: @@ -519,7 +532,7 @@ storyRewards: reward_painter: title: Färben desc: >- - Der Färber wurde freigeschaltet! Extrahiere ein paar Farben (genauso wie die Formen) und lasse sie vom Färber bemalen!

PS: Falls du farbenblind bist: Ich arbeite bereits an einer Lösung! + 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, there is a color blind mode in the settings! reward_mixer: title: Farben mischen @@ -686,7 +699,41 @@ settings: title: Vignette description: >- Aktiviert den Vignetteneffekt, der den Rand des Bildschirms zunehmend verdunkelt - und das Lesen der Textfelder vereinfacht. + und das Lesen der Textfelder vereinfacht. + + autosaveInterval: + title: Intervall für automatisches Speichern + description: >- + Ändert das Intervall, in dem der Spielstand automatisch gespeichert wird. + Die Funktion kann hier auch deaktiviert werden. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minuten + five_minutes: 5 Minuten + ten_minutes: 10 Minuten + twenty_minutes: 20 Minuten + disabled: Deaktiviert + + compactBuildingInfo: + title: Kompakte Gebäudeinformationen + description: >- + Reduziert die Infoboxen der Gebäude auf ihre Arbeitsgeschwindigkeit. Anderenfalls wird ein + Bild mit Beschreibung angezeigt. + + disableCutDeleteWarnings: + title: Deaktiviere Warnungsdialog beim Löschen + description: >- + Deaktiviert die Warnung, die beim Löschen und Ausschneiden von mehr als 100 Feldern angezeigt wird. + + enableColorBlindHelper: + title: Modus für Farbenblinde + description: Aktiviert verschiedene Werkzeuge, die dir das Spielen trotz Farbenblindheit ermöglichen. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. keybindings: title: Tastenbelegung @@ -715,7 +762,7 @@ keybindings: mapZoomIn: Hineinzoomen mapZoomOut: Herauszoomen - createMarker: Markeirung erstellen + createMarker: Markierung erstellen menuOpenShop: Upgrades menuOpenStats: Statistiken @@ -733,10 +780,9 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Platzieren abbrechen rotateWhilePlacing: Rotieren rotateInverseModifier: >- - Modifier: stattdessen gegen UZS rotieren + Modifikator: stattdessen gegen UZS rotieren cycleBuildingVariants: Variante wählen confirmMassDelete: Massenlöschung bestätigen cycleBuildings: Gebäude rotieren @@ -753,27 +799,28 @@ keybindings: exportScreenshot: Ganze Fabrik als Foto exportieren mapMoveFaster: Schneller bewegen lockBeltDirection: Bandplaner aktivieren - switchDirectionLockSide: 'Planer: Seite wechseln' + switchDirectionLockSide: "Planer: Seite wechseln" + pipette: Pipette about: title: Über dieses Spiel body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Dieses Spiel hat einen offenen Quellcode (Open Source) und wurde von Tobias Springer (das bin ich!) entwickelt.

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

+ Wenn du etwas zum Spiel beitragen möchtest, dann schaue dir shapez.io auf GitHub an.

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

+ Das Spiel wurde erst durch die großartige Discord-Community + um meine Spiele möglich gemacht. Komm doch einfach mal auf dem Discord-Server vorbei!

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

+ Der Soundtrack wurde von Peppsen komponiert! Klasse Typ.

- Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + Abschließend möchte ich meinem Kumpel Niklas danken! Ohne unsere + etlichen gemeinsamen Stunden in Factorio wäre dieses Projekt nie zustande gekommen. changelog: title: Änderungen diff --git a/translations/base-el.yaml b/translations/base-el.yaml index e077ec1f..3b7bec15 100644 --- a/translations/base-el.yaml +++ b/translations/base-el.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,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 @@ -398,6 +398,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -518,7 +531,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -688,6 +701,41 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -733,7 +781,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -753,7 +800,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: About this Game diff --git a/translations/base-en.yaml b/translations/base-en.yaml index cb4d7024..9d1813e4 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -121,6 +121,7 @@ mainMenu: continue: Continue newGame: New Game changelog: Changelog + subreddit: Reddit importSavegame: Import openSourceHint: This game is open source! discordLink: Official Discord Server @@ -281,7 +282,7 @@ ingame: toggleHud: Toggle HUD placeBuilding: Place building createMarker: Create Marker - delete: Destroy + delete: Delete pasteLastBlueprint: Paste last blueprint lockBeltDirection: Enable belt planner plannerSwitchSide: Flip planner side @@ -289,6 +290,18 @@ ingame: copySelection: Copy clearSelection: Clear Selection pipette: Pipette + switchLayers: Switch Layers + + # Names of the colors, used for the color blind mode + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -384,6 +397,12 @@ ingame: 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. + # Shape viewer + shapeViewer: + title: Layers + empty: Empty + copyKey: Copy Key + # Interactive tutorial interactiveTutorial: title: Tutorial @@ -504,6 +523,14 @@ buildings: name: Storage description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + energy_generator: + deliver: Deliver + toGenerateEnergy: For energy + + default: + name: &energy_generator Energy Generator + description: Generates energy by consuming shapes. Each energy generator requires a different shapes. + storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: @@ -517,7 +544,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -582,6 +609,10 @@ storyRewards: 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! + reward_wires: + title: Wires + desc: TODO + no_reward_freeplay: title: Next level desc: >- @@ -611,6 +642,19 @@ settings: large: Large huge: Huge + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it entirely here. + + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + scrollWheelSensitivity: title: Zoom sensitivity description: >- @@ -639,6 +683,11 @@ settings: description: >- Change the language. All translations are user contributed and might be incomplete! + enableColorBlindHelper: + title: Color Blind Mode + description: >- + Enables various tools which allow to play the game if you are color blind. + fullscreen: title: Fullscreen description: >- @@ -692,11 +741,21 @@ settings: description: >- Enables the vignette which darkens the screen corners and makes text easier to read. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + compactBuildingInfo: title: Compact Building Infos description: >- Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 entities. + keybindings: title: Keybindings hint: >- @@ -732,6 +791,7 @@ keybindings: toggleHud: Toggle HUD toggleFPSInfo: Toggle FPS and Debug Info + switchLayers: Switch layers exportScreenshot: Export whole Base as Image belt: *belt splitter: *splitter @@ -741,6 +801,7 @@ keybindings: rotater: *rotater stacker: *stacker mixer: *mixer + energy_generator: *energy_generator painter: *painter trash: *trash @@ -749,7 +810,7 @@ keybindings: rotateInverseModifier: >- Modifier: Rotate CCW instead cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete + confirmMassDelete: Delete area pasteLastBlueprint: Paste last blueprint cycleBuildings: Cycle Buildings lockBeltDirection: Enable belt planner diff --git a/translations/base-es.yaml b/translations/base-es.yaml index 641019ed..77273462 100644 --- a/translations/base-es.yaml +++ b/translations/base-es.yaml @@ -57,7 +57,7 @@ steamPage: [*] Modo historia en el que los edificios cuesten figuras [*] Más niveles y edificios (exclusivos del juego completo) [*] Mapas diferentes y tal vez obstáculos en el mapa - [*] Configuración en la cración del mapa (Editar el número y tamaño de los recursos, la semilla, y más) + [*] Configuración en la creación del mapa (Editar el número y tamaño de los recursos, la semilla, y más) [*] Más tipos de formas [*] Mejoras de rendimiento (Aunque el juego ya funciona muy bien!) [*] Modo para daltónicos @@ -155,6 +155,7 @@ mainMenu: showInfo: Ver contestOver: El concurso ha terminado - Únete al discord para enterarte sobre nuevos concursos! + subreddit: Reddit dialogs: buttons: @@ -282,9 +283,13 @@ ingame: placeBuilding: Colocar edificio createMarker: Crear marca delete: Destruir - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + pasteLastBlueprint: Pegar último plano + lockBeltDirection: Activar planificador de cintas transportadoras + plannerSwitchSide: Invertir giro del planificador + cutSelection: Cortar + copySelection: Copiar + clearSelection: Limpiar Selección + pipette: Pipette # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -320,11 +325,6 @@ ingame: newUpgrade: ¡Una nueva mejora está disponible! gameSaved: Tu partida ha sido guardada. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Presiona para cortar, para copiar, para eliminar y para cancelar. - # The "Upgrades" window shop: title: Mejoras @@ -394,6 +394,20 @@ ingame: ¡Conecta el extractor con una cinta transportadora a tu edificio central!

Pista: Pulsa y arrastra la cinta transportadora con el ratón! 1_3_expand: >- ¡Esto NO es un "juego de esperar"! Construye más extractores y cintas transportadoras para completar el objetivo más rápido.

Pista: Mantén pulsado SHIFT para colocar varios extractores y usa R para rotarlos. + + colors: + red: Rojo + green: Verde + blue: Azul + yellow: Amarillo + purple: Morado + cyan: Cian + white: Blanco + uncolored: Sin color + shapeViewer: + title: Capas + empty: Vacio + # All shop upgrades shopUpgrades: belt: @@ -440,7 +454,7 @@ buildings: description: Multifuncional - Distribuye equitativamente todas las entradas a todas las salidas. compact: - name: fusionador (compacto) + name: Fusionador (compacto) description: Junta dos cintas transportadoras en una. compact-inverse: @@ -514,7 +528,8 @@ storyRewards: reward_painter: title: Pintor desc: >- - El pintor ha sido desbloqueado - ¡Extrae color de las betas (al igual que haces con las figuras) y combínalo con una figura para pintarla de ese color!

PS: Si eres daltónico, estoy trabajando en una solución! + 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, there is a color blind mode in the settings! + reward_mixer: title: Mezclador de Color desc: El mezclador ha sido desbloqueado - ¡Combina dos colores usando mezcla aditiva con este edificio! @@ -606,7 +621,7 @@ settings: huge: Enorme scrollWheelSensitivity: - title: Sensitividad del zoom + title: Sensibilidad del zoom description: >- Cambia como de sensible es el zoom (Tanto la ruedo del ratón como el trackpad) sensitivity: @@ -675,10 +690,39 @@ settings: Si está activado, colocar túneles automáticamente removerá las cintas transportadoras innecesarias. Esto también permite arrastrar con el ratón y los túneles excedentes serán removidos. vignette: - title: Vignette + title: Viñeta description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Activa el efecto viñeta que oscurece loas esquinas de la pantalla y hace el texto mas fácil de leer. + + autosaveInterval: + title: Intervalo de Autoguardado + description: >- + Controla cada cuanto tiempo se guarda el juego automaticamente. Aquí tambien puedes deshabilitarlo por completo. + intervals: + one_minute: 1 Minuto + two_minutes: 2 Minutos + five_minutes: 5 Minutos + ten_minutes: 10 Minutos + twenty_minutes: 20 Minutos + disabled: Deshabilitado + compactBuildingInfo: + title: Información Compacta de Edificios + description: >- + Acorta la caja de información mostrando solo sus ratios. Si no, se mostrara una descripción y una imagen. + disableCutDeleteWarnings: + title: Deshabilitar las advertencias de Cortar/Eliminar + description: >- + Deshabilita los dialogos de advertencia que se muestran cuando se cortan/eliminan mas de 100 elementos. + + enableColorBlindHelper: + title: Modo para Daltonicos + description: Activa varias herramientas que permiten jugar si eres daltonico. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. keybindings: title: Atajos de Teclado @@ -724,7 +768,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Cancelar Colocación rotateWhilePlacing: Rotar rotateInverseModifier: >- Modificador: Rotar inversamente en su lugar @@ -744,7 +787,8 @@ keybindings: massSelectCut: Cortar área exportScreenshot: Exportar toda la base como imagen mapMoveFaster: Mover más rápido - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: Sobre el Juego diff --git a/translations/base-fr.yaml b/translations/base-fr.yaml index 9f43384f..7140e456 100644 --- a/translations/base-fr.yaml +++ b/translations/base-fr.yaml @@ -157,6 +157,7 @@ mainMenu: continue: Continuer newGame: Nouvelle partie madeBy: Créé par + subreddit: Reddit dialogs: buttons: @@ -212,7 +213,7 @@ dialogs: keybindingsResetOk: title: Réinitialisation des contrôles - desc: Les contrôles ont été réinitialisés par leur état par défaut respectifs ! + desc: Les contrôles ont été réinitialisés dans leur état par défaut respectifs ! featureRestriction: title: Version démo @@ -236,7 +237,7 @@ dialogs: massDeleteConfirm: title: Confirmation de suppression desc: >- - Vous allez supprimer pas mal de bâtiments ( pour être exact) ! Etes vous certains de vouloir faire cela ? + Vous allez supprimer pas mal de bâtiments ( pour être exact) ! Êtes vous certains de vouloir faire cela ? massCutConfirm: title: Confirmer la coupure @@ -247,7 +248,7 @@ dialogs: blueprintsNotUnlocked: title: Pas encore débloqué desc: >- - Les patrons n'ont pas encore étés débloqués ! Terminez encore quelques niveaux pour les débloquer. + Les patrons n'ont pas encore étés débloqués ! Terminez encore quelques niveaux pour y avoir accès. keybindingsIntroduction: title: Raccourcis utiles @@ -288,6 +289,10 @@ ingame: pasteLastBlueprint: Copier le dernier patron lockBeltDirection: Utiliser le plannificateur de convoyeurs plannerSwitchSide: Échanger la direction du plannificateur + cutSelection: Couper + copySelection: Copier + clearSelection: Effacer la sélection + pipette: Pipette # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -323,11 +328,6 @@ ingame: newUpgrade: Une nouvelle amélioration est disponible ! gameSaved: Votre partie a été sauvegardée. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Apuyez sur pour couper, pour copier, pour effacer et pour annuler. - # The "Upgrades" window shop: title: Améliorations @@ -398,6 +398,19 @@ ingame: 1_3_expand: >- Ceci n'est PAS un jeu incrémental et inactif ! Construisez plus d'extracteurs et de convoyeurs pour atteindre plus vite votre votre but.

Astuce: Gardez SHIFT enfoncé pour placer plusieurs extracteurs, et utilisez R pour les faire pivoter. + colors: + red: Rouge + green: Vert + blue: Bleu + yellow: Jaune + purple: Violet + cyan: Cyan + white: Blanc + uncolored: Non coloré + shapeViewer: + title: Calques + empty: Vide + # All shop upgrades shopUpgrades: belt: @@ -520,7 +533,7 @@ storyRewards: reward_painter: title: Peintre desc: >- - Le peintre a été débloqué - Extrayez des pigments de couleur (comme vous le faites avec les formes) et combinez les avec une forme dans un peintre pour les colorier !

PS: Si vous êtes daltonien, je travaille déjà à une solution ! + 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, there is a color blind mode in the settings! reward_mixer: title: Mélangeur de couleurs @@ -691,6 +704,36 @@ settings: description: >- Permet l'affichage de l'effet de vignette qui assombrit les coins de l'écran afin de rendre le texte plus facile à lire. + autosaveInterval: + title: Fréquence des sauvegardes automatiques + description: >- + Contrôle avec quelle fréquence le jeu sera sauvegardé automatiquement. Vous pouvez aussi entièrement désactiver cette fonctionnalité ici. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Désactivé + compactBuildingInfo: + title: Informations réduites sur les bâtiments + description: >- + Raccourcit les panneaux d'information sur les bâtiments en n'affichant que les ratios. Dans le cas contraire, une description et une imagine sont présentés. + disableCutDeleteWarnings: + title: Désactive les avertissement pour Couper/Effacer + description: >- + Désactive la boîte de dialogue qui s'affiche lorsque vous vous apprêtez à couper/effacer plus de 100 entités. + + enableColorBlindHelper: + title: Mode Daltonien + description: Active divers outils qui permettent de jouer à ce jeu si vous êtes daltonien. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Contrôles hint: >- @@ -736,7 +779,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Annuler le placement rotateWhilePlacing: Pivoter rotateInverseModifier: >- Variante: Pivote à gauche @@ -756,7 +798,8 @@ keybindings: exportScreenshot: Exporter toute la base en tant qu'image. mapMoveFaster: Se déplacer plus vite lockBeltDirection: Utiliser le plannificateur de convoyeurs - switchDirectionLockSide: 'Plannificateur: changer de côté' + switchDirectionLockSide: "Plannificateur: changer de côté" + pipette: Pipette about: title: À propos de ce jeu diff --git a/translations/base-hr.yaml b/translations/base-hr.yaml index 8321e20b..2cad65a1 100644 --- a/translations/base-hr.yaml +++ b/translations/base-hr.yaml @@ -156,6 +156,7 @@ mainMenu: showInfo: View contestOver: This contest has ended - Join the discord to get noticed about new contests! + subreddit: Reddit dialogs: buttons: @@ -285,6 +286,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 +325,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 @@ -396,6 +396,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -518,7 +531,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -688,6 +701,39 @@ settings: description: >- Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -735,7 +781,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -755,6 +800,7 @@ keybindings: placementDisableAutoOrientation: Disable automatic orientation placeMultiple: Stay in placement mode placeInverse: Invert automatic belt orientation + pipette: Pipette about: title: About this Game diff --git a/translations/base-hu.yaml b/translations/base-hu.yaml index bbbd3feb..45a51e37 100644 --- a/translations/base-hu.yaml +++ b/translations/base-hu.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,6 @@ ingame: newUpgrade: Egy új fejlesztés elérhető! gameSaved: A játékod el lett mentve. - # 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: Fejlesztések @@ -398,6 +398,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -517,7 +530,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -687,6 +700,39 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -732,7 +778,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -752,7 +797,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: A játékról diff --git a/translations/base-it.yaml b/translations/base-it.yaml index e077ec1f..412d947a 100644 --- a/translations/base-it.yaml +++ b/translations/base-it.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,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 @@ -398,6 +398,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -518,7 +531,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -688,6 +701,39 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -733,7 +779,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -753,7 +798,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: About this Game diff --git a/translations/base-ja.yaml b/translations/base-ja.yaml index afda0215..500238db 100644 --- a/translations/base-ja.yaml +++ b/translations/base-ja.yaml @@ -156,6 +156,7 @@ mainMenu: continue: 続きから newGame: 新規ゲーム madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -286,6 +287,10 @@ ingame: pasteLastBlueprint: ブループリントの内容を設置 lockBeltDirection: ベルトプランナーを有効化 plannerSwitchSide: プランナーが通る側を反転 + cutSelection: カット + copySelection: コピー + clearSelection: 選択範囲をクリア + pipette: ピペット # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -321,11 +326,6 @@ ingame: newUpgrade: 新しいアップグレードが利用可能です! gameSaved: ゲームをセーブしました。 - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: キーでカット キーでコピー キーで削除 キーでキャンセル - # The "Upgrades" window shop: title: アップグレード @@ -397,6 +397,19 @@ ingame: 1_3_expand: >- このゲームは放置系のゲームではありません! もっと早く要件を満たせるように、追加の抽出機とベルトを設置しましょう。

Tip: SHIFT キーを押し続けると抽出機を連続配置できます。Rキーで設置方向を回転できます。 + colors: + red: 赤 + green: 緑 + blue: 青 + yellow: 黄 + purple: 紫 + cyan: シアン + white: 白 + uncolored: 無色 + shapeViewer: + title: レイヤー + empty: 空 + # All shop upgrades shopUpgrades: belt: @@ -517,7 +530,7 @@ storyRewards: reward_painter: title: 着色 desc: >- - 着色機が利用可能になりました。 - 色の鉱脈から形の手順と同様に色を抽出し、着色機で形と組み合わせることで着色できます。

PS:もしあなたが色の認識に問題があっても安心してください。我々はすでにその解決に着手しています! + 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, there is a color blind mode in the settings! reward_mixer: title: 色の混合 @@ -686,6 +699,36 @@ settings: description: >- 画面の隅を暗くして文字を読みやすくするビネットを有効化します。 + autosaveInterval: + title: オートセーブ間隔 + description: >- + ゲームが自動的にセーブされる頻度を設定します。無効化することも可能です。 + intervals: + one_minute: 1 分 + two_minutes: 2 分 + five_minutes: 5 分 + ten_minutes: 10 分 + twenty_minutes: 20 分 + disabled: 無効 + compactBuildingInfo: + title: コンパクトな建造物情報 + description: >- + レートのみを表示することで、建造物の情報ボックスを短くします。選択しない場合は、説明文と画像も表示されます。 + disableCutDeleteWarnings: + title: カット/削除の警告を無効化 + description: >- + 100個以上のエンティティをカット/削除する際に表示される警告ダイアログを無効にします。 + + enableColorBlindHelper: + title: 色覚モード + description: 色覚異常を持っていてもゲームがプレイできるようにするための各種ツールを有効化します。 + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: キー設定 hint: >- @@ -731,7 +774,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: 配置の中止 rotateWhilePlacing: 回転 rotateInverseModifier: >- Modifier: 逆時計回りにする @@ -751,7 +793,8 @@ keybindings: exportScreenshot: 工場の全体像を画像出力 mapMoveFaster: より速く移動 lockBeltDirection: ベルトプランナーを有効化 - switchDirectionLockSide: 'プランナー: 通る側を切り替え' + switchDirectionLockSide: "プランナー: 通る側を切り替え" + pipette: ピペット about: title: このゲームについて diff --git a/translations/base-kor.yaml b/translations/base-kor.yaml index 87ebf5ed..e9f19157 100644 --- a/translations/base-kor.yaml +++ b/translations/base-kor.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,6 @@ ingame: 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. - # The "Upgrades" window shop: title: 업그레이드 @@ -398,6 +398,19 @@ ingame: 1_3_expand: >- 이것은 방치형 게임이 아닙니다! 추출기를 더 놓아 목표를 빨리 달성하세요.

팁: SHIFT를 눌러 여러 개의 추출기를 놓고 R로 회전 시키세요. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -518,7 +531,7 @@ storyRewards: reward_painter: title: 색칠기 desc: >- - 색칠기가 잠금 해제 되었습니다! 색소 광물을 추출해서 이 기계로 도형을 색칠하세요.

PS: 당신이 색맹이라면, 해결책을 찾고 있으니 잠시만 기다려주세요! + 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, there is a color blind mode in the settings! reward_mixer: title: 혼합기 @@ -689,6 +702,39 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: 키바인딩 hint: >- @@ -734,7 +780,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: 건물 배치 취소 rotateWhilePlacing: 회전 rotateInverseModifier: >- Modifier: 대신 반시계방향으로 회전 @@ -754,7 +799,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: 이 게임의 정보 diff --git a/translations/base-lt.yaml b/translations/base-lt.yaml index 4623b773..bd33d5b1 100644 --- a/translations/base-lt.yaml +++ b/translations/base-lt.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,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 @@ -398,6 +398,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -518,7 +531,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -687,6 +700,39 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -732,7 +778,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -752,7 +797,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: About this Game diff --git a/translations/base-nl.yaml b/translations/base-nl.yaml index df5f7546..2deb72b7 100644 --- a/translations/base-nl.yaml +++ b/translations/base-nl.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Verder newGame: Nieuw Spel madeBy: Gemaakt door + subreddit: Reddit dialogs: buttons: @@ -283,8 +284,12 @@ ingame: createMarker: Plaats markering delete: Vernietig pasteLastBlueprint: Plak de laatst gekopiëerde blauwdruk - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + lockBeltDirection: Maak gebruik van de lopende band planner + plannerSwitchSide: Draai de richting van de planner + cutSelection: Knip + copySelection: Kopieer + clearSelection: Cancel selectie + pipette: Pipet # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -320,11 +325,6 @@ ingame: newUpgrade: Er is een nieuwe upgrade beschikbaar! gameSaved: Je spel is opgeslagen. - # 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 te annuleren. - # The "Upgrades" window shop: title: Upgrades @@ -396,6 +396,19 @@ ingame: 1_3_expand: >- 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. + colors: + red: Rood + green: Groen + blue: Blauw + yellow: Geel + purple: Paars + cyan: Cyaan + white: Wit + uncolored: Geen kleur + shapeViewer: + title: Lagen + empty: Leeg + # All shop upgrades shopUpgrades: belt: @@ -516,11 +529,11 @@ storyRewards: 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 de vorm een kleur te geven!

PS: Ik werk aan een oplossing voor kleurenblinden! + 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, there is a color blind mode in the settings! reward_mixer: title: Kleuren mengen - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + desc: De menger is ontgrendeld - gebruik dit gebouw om twee kleuren te mengen via 'additive blending'! reward_stacker: title: Stapelaar @@ -685,6 +698,39 @@ settings: description: >- Schakelt de vignet in, wat de hoeken van het scherm donkerder maakt zodat de tekst makkelijker te lezen is. + autosaveInterval: + title: Autosave Interval + description: >- + Bepaalt hoe vaak het spel automatisch opslaat. Je kan het hier ook volledig + mee uitschakelen. + + intervals: + one_minute: 1 Minuut + two_minutes: 2 Minuten + five_minutes: 5 Minuten + ten_minutes: 10 Minuten + twenty_minutes: 20 Minuten + disabled: Uitgeschakeld + compactBuildingInfo: + title: Combacte gebouwinformatie + description: >- + Informatie weergeven bij gebouwen wordt beperkt tot alleen hun 'ratios'. Anders + zie je een beschrijving en een afbeelding. + disableCutDeleteWarnings: + title: Schakel knip/delete waarschuwingen uit. + description: >- + Schakelt de waarschuwing uit die wordt weergegeven wanneer je meer dan 100 dingen probeert te + knippen/deleten. + enableColorBlindHelper: + title: Kleurenblindmodus + description: Schakelt verschillende hulpmiddelen in zodat je het spel alsnog kunt spelen wanneer je kleurenblind bent. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Sneltoetsen hint: >- @@ -730,7 +776,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Cancel plaatsen rotateWhilePlacing: Roteren rotateInverseModifier: >- Aanpassing: Roteer tegen de klok in @@ -750,7 +795,8 @@ keybindings: exportScreenshot: Exporteer volledige basis als afbeelding mapMoveFaster: Beweeg sneller lockBeltDirection: Schakel lopende band-planner in - switchDirectionLockSide: 'Planner: Wissel van kant' + switchDirectionLockSide: "Planner: Wissel van richting" + pipette: Pipet about: title: Over dit spel diff --git a/translations/base-no.yaml b/translations/base-no.yaml index a4828638..b3c1bc84 100644 --- a/translations/base-no.yaml +++ b/translations/base-no.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Fortsett newGame: Nytt Spill madeBy: Laget av + subreddit: Reddit dialogs: buttons: @@ -285,6 +286,10 @@ ingame: pasteLastBlueprint: Lim inn forrige blåkopi lockBeltDirection: Aktiver båndplanleggeren plannerSwitchSide: Flipp båndplanleggeren + cutSelection: Klipp Ut + copySelection: Kopier + clearSelection: Fjern Valgte + pipette: Pipette # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -320,11 +325,6 @@ ingame: newUpgrade: En ny oppgradering er tilgjengelig! gameSaved: Spillet ditt er lagret. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Trykk for å klippe, for å kopiere, for å slette, og for å avbryte. - # The "Upgrades" window shop: title: Oppgraderinger @@ -396,6 +396,19 @@ ingame: 1_3_expand: >- Dette er IKKE et idle-spill! Bygg flere utdragere og belter for å nå målet raskere.

Tips: Hold SHIFT for å plassere flere utdragere, og bruk R for å rotere dem. + colors: + red: Rød + green: Grønn + blue: Blå + yellow: Gul + purple: Lilla + cyan: Cyan + white: Hvit + uncolored: Ingen farge + shapeViewer: + title: Lag + empty: Tom + # All shop upgrades shopUpgrades: belt: @@ -516,7 +529,7 @@ storyRewards: reward_painter: title: Maling desc: >- - Maleren har blitt tilgjengelig - Hent ut fargeressurser (på samme måte som du gjør med objekter) og kombiner det med et objekt i maleren for å male de!

PS: Hvis du er fargeblind, så jobber jeg med en løsning alt! + 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, there is a color blind mode in the settings! reward_mixer: title: Fargemikser @@ -573,7 +586,7 @@ storyRewards: reward_blueprints: title: Blåkopier - desc: Du kan nå kopiere og lime inn deler av fabrikken din! Velg et område (Hold inne CTRL, så dra med musa), trykk så 'C' for å kopiere det.

Lime det inn er ikke graits, du må produsere blåkopi objekter for å få råd til det! (Det du nettop leverte). + desc: Du kan nå kopiere og lime inn deler av fabrikken din! Velg et område (Hold inne CTRL, så dra med musa), trykk så 'C' for å kopiere det.

Lime det inn er ikke gratis, du må produsere blåkopi objekter for å få råd til det! (Det du nettop leverte). # Special reward, which is shown when there is no reward actually no_reward: @@ -687,6 +700,39 @@ settings: Aktiverer vignett som gjør hjørnene på skjermen mørkere og teksten lettere å lese. + autosaveInterval: + title: Autolagringsintervall + description: >- + Jsuter hvor ofte spillet lagres automatisk. Du kan også + deaktivere det fullstendig. + intervals: + one_minute: 1 Minutt + two_minutes: 2 Minutter + five_minutes: 5 Minutter + ten_minutes: 10 Minutter + twenty_minutes: 20 Minutter + disabled: Deaktivert + compactBuildingInfo: + title: Kompakt Bygningsinformasjon + description: >- + Forkorter informasjonsboksen for bygninger ved å bare vise dems forhold. Ellers + vises en beskrivelse og bilde er vist. + disableCutDeleteWarnings: + title: Deaktiverer Kutt/Slette Advarsler + description: >- + Deaktiverer advarselsdialogen som kommer frem når du kutter/sletter mer enn 100 + bygninger. + + enableColorBlindHelper: + title: Fargeblind Modus + description: Aktiverer forskjellige verktøy som lar deg spille spillet om du er fargeblind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Hurtigtaster hint: >- @@ -734,7 +780,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Avbryt Plassering rotateWhilePlacing: Roter rotateInverseModifier: >- Alternativ: Roter mot klokken isteden @@ -752,7 +797,8 @@ keybindings: placeMultiple: Forbli i plasseringsmodus placeInverse: Inverter automatisk transportbånd orientering lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planlegger: Bytt side" + pipette: Pipette about: title: Om dette spillet diff --git a/translations/base-pl.yaml b/translations/base-pl.yaml index 882f22ac..8f66d2a0 100644 --- a/translations/base-pl.yaml +++ b/translations/base-pl.yaml @@ -21,7 +21,7 @@ steamPage: # This is the short text appearing on the steam page - shortText: shapez.io to gra polegająca na budowaniu automatycznej fabryki różnych, z każdym poziomem bardziej skomplikowanych kształtów, na mapie która nie ma końca. + shortText: shapez.io to gra polegająca na budowaniu fabryki automatyzującej tworzenie i łączenie ze sobą coraz bardziej skomplikowanych kształtów na mapie, która nie ma końca. # 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: @@ -30,13 +30,13 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io jest grą o budowaniu i automatyzacji fabryki różnych kształtów. Dostarczaj coraz bardziej skomplikowane kształty, żeby odblokować nowe ulepszenia żeby przyspieszyć produkcję w twojej fabryce. + shapez.io jest grą o budowaniu i automatyzacji fabryki różnych kształtów. Dostarczaj coraz bardziej skomplikowane kształty, żeby odblokować nowe ulepszenia i przyspieszyć produkcję w twojej fabryce. - Będziesz potrzebował produkować coraz więcej elementów, więc potrzebujesz również sporo miejsca na powiększanie fabryki. [b]Nieskończona mapa[/b] to coś co ułatwi Ci ten proces! + Będziesz potrzebował coraz więcej elementów, więc również sporo miejsca na powiększanie fabryki. [b]Nieskończona mapa[/b] to coś co ułatwi Ci ten proces! - Same kształty mogą z czasem być nudne, dlatego gra będzie wymagała od Ciebie malowania kształtów różnymi kolorami - Połącz czerwoną, zieloną i niebieską farbę, a powstanie farba o innym kolorze. Korzystaj z farb by postępować z kolejnymi poziomami. + Same kształty mogą z czasem być nudne, dlatego gra będzie wymagała od Ciebie malowania ich różnymi kolorami - połącz czerwoną, zieloną i niebieską farbę, a powstanie nowa o innym kolorze. Korzystaj z farb, by móc ukończyć kolejne poziomy. - Na tą chwilę gra oferuje 18 poziomów (które powinny zagwarantować rozrywkę na co najmniej kilka godzin!) ale bez przerwy dodaję nowe - Jest naprawdę wiele do dodania! + Na tę chwilę gra oferuje 18 poziomów (które powinny zagwarantować rozrywkę na co najmniej kilka godzin!), ale bez przerwy dodaję nowe - jest naprawdę wiele do dodania! [b]Zalety pełnej wersji[/b] @@ -46,21 +46,21 @@ steamPage: [*] Nielimitowana ilość zapisanych gier [*] Ciemny motyw gry [*] Więcej ustawień - [*] Pomóż mi w dalszym rozwijaniu shapez.io ❤️ + [*] Pomożesz mi w dalszym rozwijaniu shapez.io ❤️ [*] Więcej zawartości niedługo! [/list] [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 generowanej 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!) + [*] Optymalizacja (mimo wszystko gra już działa dość płynnie!) [*] Tryb dla ślepoty barw [*] I wiele więcej! [/list] @@ -159,7 +159,8 @@ mainMenu: showInfo: Wyświetl contestOver: Ten konkurs już się skończył - Dołącz do serwera Discord by nie przegapić kolejnych! - madeBy: Made by + madeBy: Gra wykonana przez + subreddit: Reddit dialogs: buttons: @@ -207,7 +208,7 @@ dialogs: editKeybinding: title: Zmień klawiszologię - desc: Naciśnij klawisz bądź przycisk myszy który chcesz przypisać, lub wciśnij Escape aby anulować. + desc: Naciśnij klawisz bądź przycisk myszy, który chcesz przypisać lub wciśnij Escape, aby anulować. resetKeybindingsConfirmation: title: Zresetuj klawiszologię @@ -233,7 +234,7 @@ dialogs: upgradesIntroduction: title: Ulepszenia desc: >- - Wszystkie kształty które produkujesz mogą zostać użyte do ulepszeń - Nie niszcz starych fabryk! + Wszystkie kształty, które produkujesz, mogą zostać użyte do ulepszeń - Nie niszcz starych fabryk! Zakładka "Ulepszenia" dostępna jest w prawym górnym rogu. massDeleteConfirm: @@ -253,7 +254,7 @@ dialogs: Oto kilka z nich, lecz nie zmienia to faktu iż warto sprawdzić dostępne kombinacje!

CTRL + Przeciąganie: Zaznacz obszar do kopiowania/usuwania.
SHIFT: Przytrzymaj, by wstawić więcej niż jeden budynek.
- ALT: Odwróć orientacje stawianych taśmociągów.
+ ALT: Odwróć orientację stawianych taśmociągów.
createMarker: title: Nowy Znacznik @@ -283,15 +284,30 @@ ingame: stopPlacement: Przestań stawiać rotateBuilding: Obróć budynek placeMultiple: Postaw więcej - reverseOrientation: Odwróć orientacje - disableAutoOrientation: Wyłącz orientacje automatyczną + reverseOrientation: Odwróć orientację + disableAutoOrientation: Wyłącz orientację automatyczną toggleHud: Przełącz widoczność interfejsu placeBuilding: Postaw budynek createMarker: Stwórz znacznik delete: Usuń pasteLastBlueprint: Wklej ostatnio skopiowany obszar - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + lockBeltDirection: Tryb planowania taśmociągu + plannerSwitchSide: Obróć planowany taśmociąg + cutSelection: Wytnij + copySelection: Skopiuj + clearSelection: Wyczyść zaznaczenie + pipette: Wybierz obiekt z mapy + + # Names of the colors, used for the color blind mode + colors: + red: Czerwony + green: Zielony + blue: Niebieski + yellow: Żółty + purple: Fioletowy + cyan: Cyjanowy + white: Biały + uncolored: Brak koloru # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -327,11 +343,6 @@ ingame: newUpgrade: Nowe ulepszenie dostępne! gameSaved: Postęp gry został zapisany. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Naciśnij by wyciąć, by skopiować, by usunąć lub by anulować. - # The "Upgrades" window shop: title: Ulepszenia @@ -392,18 +403,23 @@ ingame: waypoints: waypoints: Znaczniki hub: Budynek Główny - description: Kliknij znacznik lewym przyciskiem myszy, by się do niego przenieść lub prawym, by go usunąć.

Naciśnij by stworzyć marker na środku widoku lub prawy przycisk myszy by stworzyć na wskazanej lokacji. + description: Kliknij znacznik lewym przyciskiem myszy, by się do niego przenieść lub prawym, by go usunąć.

Naciśnij , by stworzyć marker na środku widoku lub prawy przycisk myszy, by stworzyć na wskazanej lokacji. creationSuccessNotification: Utworzono znacznik. + # Shape viewer + shapeViewer: + title: Poziomy + empty: Puste + # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Postaw ekstraktor na źródle kształtu koła aby go wydobyć! + 1_1_extractor: Postaw ekstraktor na źródle kształtu koła, aby go wydobyć! 1_2_conveyor: >- Połącz ekstraktor taśmociągiem do głównego budynku!

Porada: Kliknij i przeciągnij taśmociąg myszką! 1_3_expand: >- - To NIE JEST gra "do poczekania"! Buduj więcej taśmociągów i ekstraktorów by wydobywać szybciej.

Porada: Przytrzymaj SHIFT by postawić wiele ekstraktorów. Naciśnij R, by je obracać. + To NIE JEST gra "do poczekania"! Buduj więcej taśmociągów i ekstraktorów, by wydobywać szybciej.

Porada: Przytrzymaj SHIFT, by postawić wiele ekstraktorów. Naciśnij R, by je obracać. # All shop upgrades shopUpgrades: belt: @@ -429,7 +445,7 @@ buildings: belt: default: name: &belt Taśmociąg - description: Transportuje obiekty, przytrzymaj by postawić kilka. + description: Transportuje obiekty, przytrzymaj i przeciągnij, by postawić kilka. miner: # Internal name for the Extractor default: @@ -497,7 +513,7 @@ buildings: description: &painter_desc Koloruje kształt za pomocą koloru dostarczonego od boku. double: name: Malarz (Podwójny) - description: Koloruje kształt za pomocą koloru dostarczonych od boku. Koloruje 2 kształty używając 1 barwnika. + 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ą ćwiartkę kształtu na inny kolor, używając dostarczonych kolorów. @@ -519,18 +535,18 @@ storyRewards: reward_cutter_and_trash: title: Przecinanie Kształtów desc: >- - Odblokowano nową maszynę: przecinak - tnie kształt na pół pionowo - od góry do dołu, niezależnie od orientacji!

Upewnij się że zniszczysz nichciane kawałki, ponieważ może się zatkać - Na potrzeby tego otrzymujesz też kosz - niszczy wszystko co do niego przekierujesz! + Odblokowano nową maszynę: Przecinak - tnie kształt na pół pionowo - od góry do dołu, niezależnie od orientacji!

Upewnij się, że zniszczysz niechciane kawałki, ponieważ może się zatkać - Na potrzeby tego otrzymujesz też kosz - niszczy wszystko co do niego przekierujesz! reward_rotater: title: Obracanie desc: >- - Odblokowano nową maszynę: Obracacz! Obraca wejście o 90 stopni zgodnie z wskazówkami zegara. + Odblokowano nową maszynę: Obracacz! Obraca wejście o 90 stopni zgodnie ze wskazówkami zegara. #2nd translator's note: "Color objects" should be translated as "dye" reward_painter: title: Malowanie desc: >- - Odblokowano nową maszynę: Malarz - Wydobądź barwniki (tak jak w przypadku kształtów) i połącz z kształtem by go pomalować!

PS: Jeśli cierpisz na ślepotę barw, pracuje nad tym! + 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, there is a color blind mode in the settings! reward_mixer: title: Mieszanie @@ -544,7 +560,7 @@ storyRewards: reward_splitter: title: Rozdzielacz/Łącznik - desc: Wielofunkcyjne urządzenie balansujące zostało odblokowane - Może zostać wykorzystane do tworzenia większych fabryk poprzez rozdzielanie i łaczenie taśmociągów!

+ desc: Wielofunkcyjne urządzenie balansujące zostało odblokowane - Może zostać wykorzystane do tworzenia większych fabryk poprzez rozdzielanie i łączenie taśmociągów!

reward_tunnel: title: Tunel @@ -552,11 +568,11 @@ storyRewards: reward_rotater_ccw: title: Obracanie odwrotne - desc: Odblokowano nowy wariant Obracacza - Pozwala odwracać przeciwnie do wskazówek zegara! Aby zbudować, zaznacz Obracacz i naciśnij 'T' by zmieniać warianty! + desc: Odblokowano nowy wariant Obracacza - Pozwala odwracać przeciwnie do wskazówek zegara! Aby zbudować, zaznacz Obracacz i naciśnij 'T', by zmieniać warianty! reward_miner_chainable: title: Wydobycie Łańcuchowe - desc: Odblokowano nowy wariant ekstraktora! Może przekierować obiekty do ekstraktorów przed nim zwiększając efektywność wydobycia! + desc: Odblokowano nowy wariant ekstraktora! Może przekierować obiekty do ekstraktorów przed nim, zwiększając efektywność wydobycia! reward_underground_belt_tier_2: title: Tunel Poziomu II @@ -574,7 +590,7 @@ storyRewards: reward_painter_double: title: Podwójne Malowanie - desc: Odblokowano nowy wariant Malarza - Działa jak zwykły malarz, z tą różnicą że maluje dwa kształty na raz pobierając wyłącznie jeden barwnik! + desc: Odblokowano nowy wariant Malarza - Działa jak zwykły malarz, z tą różnicą, że maluje dwa kształty na raz, pobierając wyłącznie jeden barwnik! reward_painter_quad: title: Poczwórne malowanie @@ -601,7 +617,7 @@ storyRewards: no_reward: title: Następny Poziom desc: >- - Ten poziom nie daje nagrody, lecz kolejny już tak!

PS: Lepiej nie niszczyć istniejących fabryk - Potrzebujesz wszystkich kształtów w późniejszych etapach by odblokować ulepszenia! + Ten poziom nie daje nagrody, lecz kolejny już tak!

PS: Lepiej nie niszczyć istniejących fabryk - Potrzebujesz wszystkich kształtów w późniejszych etapach, by odblokować ulepszenia! no_reward_freeplay: title: Następny Poziom @@ -686,7 +702,7 @@ settings: refreshRate: title: Częstość Odświeżania description: >- - Jeśli posiadasz monitor z częstotliwością odświeżania 144hz, zmień tę opcje na poprawną częstotliwość odświeżania ekranu. To może wpłynąć na FPS jeśli masz za wolny komputer. + Jeśli posiadasz monitor z częstotliwością odświeżania 144hz, zmień tę opcje na poprawną częstotliwość odświeżania ekranu. Może to wpłynąć na FPS jeśli masz za wolny komputer. alwaysMultiplace: title: Wielokrotne budowanie @@ -696,18 +712,52 @@ settings: offerHints: title: Porady i Tutoriale description: >- - Oferuje porady i tutoriale podczas gry. Dodatkowo, chowa pewne elementy interfejsu by ułatwić poznanie gry. + Oferuje porady i tutoriale podczas gry. Dodatkowo chowa pewne elementy interfejsu, by ułatwić poznanie gry. enableTunnelSmartplace: - title: Smart Tunnels + title: Inteligentne taśmociągi i tunele description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + Gdy włączone, umieszczenie tunelu automatycznie usuwa zbędny taśmociąg. + Pozwala również budować tunele przez przeciąganie, gdyż niepotrzebne tunele zostają usunięte. vignette: - title: Vignette + title: Winieta description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Włącza winietę - przyciemnia rogi ekranu, poprawiając czytelność tekstu. + + autosaveInterval: + title: Częstość auto-zapisu + description: >- + Zmienia, jak często gra automatycznie zapisuje fabrykę. + Można tą funkcję również całkowicie wyłączyć. + intervals: + one_minute: Co minutę + two_minutes: Co 2 minuty + five_minutes: Co 5 minut + ten_minutes: Co 10 minut + twenty_minutes: Co 20 minut + disabled: Wyłączone + + compactBuildingInfo: + title: Wyłącz opis budynków + description: >- + Ukrywa opis i zdjęcie budynków w obszarze informacyjnym, pokazując jedynie + ich tytuł i specyfikacje techniczne. + + disableCutDeleteWarnings: + title: Wyłącz ostrzeżenia usuwania/wycinania + description: >- + Wyłącza ostrzeżenia wyświetlające się przy usuwaniu lub wycinaniu więcej niż + 100 budynków. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. keybindings: title: Klawiszologia @@ -754,26 +804,27 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Anuluj Stawianie rotateWhilePlacing: Obróć rotateInverseModifier: >- - Modyfikator: Obróć Odrwotnie + Modyfikator: Obróć Odwrotnie cycleBuildingVariants: Zmień Wariant confirmMassDelete: Potwierdź usuwanie cycleBuildings: Zmień Budynek - massSelectStart: Przytrzymaj i przeciągnij by zaznaczyć + massSelectStart: Przytrzymaj i przeciągnij, by zaznaczyć massSelectSelectMultiple: Zaznacz kilka obszarów massSelectCopy: Skopiuj obszar - placementDisableAutoOrientation: Wyłącz automatyczną orientacje + placementDisableAutoOrientation: Wyłącz automatyczną orientację placeMultiple: Pozostań w trybie stawiania - placeInverse: Odwróć automatyczną orientacje pasów + placeInverse: Odwróć automatyczną orientację pasów pasteLastBlueprint: Wklej ostatnio skopiowany obszar massSelectCut: Wytnij obszar exportScreenshot: Wyeksportuj całą fabrykę jako zrzut ekranu - lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + lockBeltDirection: Tryb planowania taśmociągu + switchDirectionLockSide: >- + Planowanie taśmociągu: Zmień stronę + pipette: Wybieranie obiektów z mapy about: title: O Grze @@ -782,7 +833,7 @@ about: Jeżeli chcesz pomóc w rozwoju gry, sprawdź repozytorium shapez.io na Githubie.

Ta gra nie byłaby możliwa bez wspaniałej społeczności Discord skupionej na moich grach - Naprawdę powinieneś dołączyć do mojego serwera Discord!

Ścieżka dźwiękowa tej gry została stworzona przez Peppsena - Jest niesamowity.

- Na koniec, wielkie dzięki mojemu najlepszemu przyjacielowi: Niklas - Bez naszego wspólnego grania w Factorio, ta gra nigdy by nie powstała. + Na koniec, wielkie dzięki mojemu najlepszemu przyjacielowi: Niklas - Bez naszego wspólnego grania w Factorio ta gra nigdy by nie powstała. changelog: title: Dziennik zmian diff --git a/translations/base-pt-BR.yaml b/translations/base-pt-BR.yaml index 668f4464..e53c845f 100644 --- a/translations/base-pt-BR.yaml +++ b/translations/base-pt-BR.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,10 @@ ingame: pasteLastBlueprint: Colar último projeto 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) @@ -322,11 +327,6 @@ ingame: newUpgrade: Nova melhoria disponível! gameSaved: Seu jogo foi salvo. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Pressione para cortar, para copiar, para destruir e para cancelar. - # The "Upgrades" window shop: title: Melhorias @@ -397,6 +397,19 @@ ingame: 1_3_expand: >- Este NÃO é um jogo inativo! Construa mais extratores e esteiras para concluir o objetivo mais rapidamente.

Dica, segure SHIFT para colocar vários extratores e use R para girá-los. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -519,7 +532,7 @@ storyRewards: reward_painter: title: Pintura desc: >- - O pintor foi desbloqueado - Extraia algumas fontes coloridas (como você faz com formas) e combine-as com uma forma no pintor para colorí-las!

PS: Se você é daltônico, já estou trabalhando em uma solução! + 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, there is a color blind mode in the settings! reward_mixer: title: Misturando cores @@ -688,6 +701,39 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Controles hint: >- @@ -733,7 +779,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Cancelar rotateWhilePlacing: Rotacionar rotateInverseModifier: >- Modifier: Rotação anti-horária @@ -753,7 +798,8 @@ keybindings: exportScreenshot: Exportar base inteira como imagem mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: Sobre o jogo diff --git a/translations/base-pt-PT.yaml b/translations/base-pt-PT.yaml index f0ec758d..a9f93efc 100644 --- a/translations/base-pt-PT.yaml +++ b/translations/base-pt-PT.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continuar newGame: Novo Jogo madeBy: Criado por + subreddit: Reddit dialogs: buttons: @@ -286,6 +287,10 @@ ingame: pasteLastBlueprint: Colar o último blueprint lockBeltDirection: Ativa o planeamento de tapetes plannerSwitchSide: Lado de rotação do planeamento + cutSelection: Cortar + copySelection: Copiar + clearSelection: Cancelar + pipette: Pipeta # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -321,11 +326,6 @@ ingame: newUpgrade: Está disponível um novo upgrade! gameSaved: O teu jogo foi gravado. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: Clica para cortar, para copiar, para remover e para cancelar. - # The "Upgrades" window shop: title: Upgrades @@ -397,6 +397,19 @@ ingame: 1_3_expand: >- Isto NÃO é um jogo idle! Constrói mais extratores e tapetes para atingir o objetivo mais rapidamente.

Dica: Pressiona SHIFT para colocar vários extratores, e usa R para os rodar. + colors: + red: Vermelho + green: Verde + blue: Azul + yellow: Amarelo + purple: Roxo + cyan: Azul-bebé + white: Branco + uncolored: Sem cor + shapeViewer: + title: Camadas + empty: Vazio + # All shop upgrades shopUpgrades: belt: @@ -516,7 +529,7 @@ storyRewards: reward_painter: title: Pintura desc: >- - O Pintor foi desbloqueado - Extrai alguns pigmentos coloridos (tal como fazes com as formas) e combina-os com uma forma no pintor para a colorir!

PS: Se fores daltónico, já estou a trabalhar para encontrar uma solução! + 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, there is a color blind mode in the settings! reward_mixer: title: Mistura de Cores @@ -666,14 +679,14 @@ settings: Se ativado, dá dicas e tutoriais de apoio ao jogo. Adicionalmente, esconde certos elementos da interface do utilizador até ao nível em que são desbloqueados de forma a simplificar o início do jogo. movementSpeed: - title: Velociade de movimentação + title: Velocidade de movimentação description: Define quão rápida é a movimentação usando o teclado. speeds: super_slow: Muito lenta slow: Lenta regular: Média - fast: Rápiada - super_fast: Muito rádida + fast: Rápida + super_fast: Muito rápida extremely_fast: Extremamente rápida enableTunnelSmartplace: title: Túneis inteligentes @@ -686,6 +699,39 @@ settings: Ativa a vinheta, que escurece os cantos do ecrã e torna a leitura do texto mais fácil. + autosaveInterval: + title: Intervalo de gravação automática + description: >- + Define o quão frequentemente o jogo grava automaticamente. Também podes desativar + aqui. + intervals: + one_minute: 1 Minuto + two_minutes: 2 Minutos + five_minutes: 5 Minutos + ten_minutes: 10 Minutos + twenty_minutes: 20 Minutos + disabled: Desligado + compactBuildingInfo: + title: Informações de construções compactas + description: >- + Encurta caixas de informação mostrando apenas os respetivos rácios. Caso contrário + é mostrada a descrição e a imagem. + disableCutDeleteWarnings: + title: Desativar Avisos de Corte/Eliminação + description: >- + Desativa os avisos mostrados quando é feito o corte ou a eliminação de mais de 100 + entidades. + + enableColorBlindHelper: + title: Modo Daltónico + description: Ativa várias ferramentas para daltónicos. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Atalhos hint: >- @@ -731,7 +777,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Cancelar posicionamento rotateWhilePlacing: Rotação rotateInverseModifier: >- Modifier: Rotação CCW @@ -751,7 +796,8 @@ keybindings: exportScreenshot: Exportar a base como uma imagem mapMoveFaster: Mover rapidamente lockBeltDirection: Ativa o planeamento de tapetes - switchDirectionLockSide: 'Planeador: Troca o lado' + switchDirectionLockSide: "Planeador: Troca o lado" + pipette: Pipeta about: title: Sobre o jogo body: >- diff --git a/translations/base-ro.yaml b/translations/base-ro.yaml index 8ce591dd..48b29af4 100644 --- a/translations/base-ro.yaml +++ b/translations/base-ro.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,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 @@ -398,6 +398,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -517,7 +530,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -687,6 +700,39 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -732,7 +778,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -752,7 +797,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: About this Game diff --git a/translations/base-ru.yaml b/translations/base-ru.yaml index 6935440d..1e0fee9e 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: k + millions: M + billions: B + trillions: T # Shown for infinitely big numbers infinite: ∞ @@ -157,6 +157,7 @@ mainMenu: continue: Продолжить newGame: Новая Игра madeBy: Создал + subreddit: Reddit dialogs: buttons: @@ -289,6 +290,10 @@ ingame: pasteLastBlueprint: Вставить последний чертеж lockBeltDirection: Включить конвейерный планировщик plannerSwitchSide: Поменять местами стороны планировщика + cutSelection: Вырезать + copySelection: Копировать + clearSelection: Отменить + pipette: Пипетка # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -324,11 +329,6 @@ ingame: newUpgrade: Новое улучшение доступно! gameSaved: Игра сохранена. - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: - Вырезать; - Копировать; - Удалить; - Отменить. - # The "Upgrades" window shop: title: Улучшения @@ -400,6 +400,19 @@ ingame: 1_3_expand: >- Это НЕ idle-игра! Постройте больше экстракторов и конвейеров, чтобы достичь цели быстрее.

Подсказка: Удерживайте SHIFT чтобы разместить несколько экстракторов, а R чтобы вращать их. + colors: + red: Красный + green: Зеленый + blue: Синий + yellow: Желтый + purple: Фиолетовый + cyan: Бирюзовый + white: Белый + uncolored: Бесцветный + shapeViewer: + title: Слои + empty: Пусто + # All shop upgrades shopUpgrades: belt: @@ -519,7 +532,7 @@ storyRewards: reward_painter: title: Покраска desc: >- - Разблокирован покрасчик! Добудьте краситель из жилы (так же как и фигуры) и объедините его с фигурой в покрасчике, чтобы раскрасить ее!

PS: Если вы дальтоник, я уже работаю над решением! + 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, there is a color blind mode in the settings! reward_mixer: title: Смешивание Цветов @@ -688,6 +701,39 @@ settings: description: >- Включает виньетирование, которое затемняет углы экрана и облегчает чтение текста. + autosaveInterval: + title: Интервал авто-сохранения + description: >- + Управляет тем, как часто игра автоматически сохраняется. + А также здесь можно полностью отключить авто-сохранение. + intervals: + one_minute: 1 Минута + two_minutes: 2 Минуты + five_minutes: 5 Минут + ten_minutes: 10 Минут + twenty_minutes: 20 Минут + disabled: Отключено + compactBuildingInfo: + title: Компактная Информация о Зданиях + description: >- + Сокращает отображаемую информацию о зданиях, показывая только их множители. + Иначе информация отображается с описанием и изображением. + disableCutDeleteWarnings: + title: Отключить Предупреждение о Вырезании\Удалении + description: >- + Отключает диалоговые окна с предупреждениями, появляющиеся при + вырезании/удалении более 100 объектов. + + enableColorBlindHelper: + title: Режим Дальтоника + description: Включает различные инструменты, которые позволяют играть в игру дальтоникам. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Настройки управления hint: >- @@ -733,7 +779,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Прекратить размещение rotateWhilePlacing: Вращать rotateInverseModifier: >- Модификатор: Вращать против часовой стрелки @@ -753,7 +798,8 @@ keybindings: exportScreenshot: Экспорт всей Базы в виде Изображения mapMoveFaster: Ускорение передвижения lockBeltDirection: Включает конвейерный планировщик - switchDirectionLockSide: 'Планировщик: Переключение сторон' + switchDirectionLockSide: "Планировщик: Переключение сторон" + pipette: Пипетка about: title: Об игре diff --git a/translations/base-sv.yaml b/translations/base-sv.yaml index 8ce591dd..2aebe2ff 100644 --- a/translations/base-sv.yaml +++ b/translations/base-sv.yaml @@ -21,7 +21,7 @@ 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 är ett spel som går ut på att automatisera skapandet av former med ökande komplexitet inom den oändligt stora världen. # 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: @@ -30,49 +30,49 @@ 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 är ett spel som går ut på att automatisera skapandet av former. Leverera de efterfrågade, alltmer komplexa formerna för att utvecklas genom spelet och skaffa uppgraderingar för att öka hastigheten i fabriken. - 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]! + Eftersom efterfrågan ökar behöver du bygga ut fabriken för att möta behoven - Glöm bara inte bort resurserna, du kommer behöva expadera fabriken över den [b]oändligt stora världen[/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. + Eftersom former kan bli tråkiga kommer du behöva blanda färger och måla dina former med dem - Kombinera röd, grön, och blå för att producera olika färger och måla former med dem för att tillfredställa efterfrågan. - 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! + Detta spel innehåller just nu 18 nivåer (Vilket borde hålla dig upptagen i några timmar!) men jag lägger konstant till fler saker - Det finns mycket planerat! - [b]Standalone Advantages[/b] + [b]Fristående Fördelar[/b] [list] [*] Waypoints - [*] Unlimited Savegames - [*] Dark Mode - [*] More settings - [*] Allow me to further develop shapez.io ❤️ - [*] More features in the future! + [*] Oändligt antal sparfiler + [*] Mörkt tema + [*] Fler inställningar + [*] Tillåter mig att vidare utveckla shapez.io ❤️ + [*] Fler funktioner i framtiden! [/list] - [b]Planned features & Community suggestions[/b] + [b]Planerade tillägg & Gruppförslag[/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. + Detta spel är open source - Vem som helst kan hjälpa! Förutom det lyssnar jag [b]ofta[/b] på min community! Jag försöker läsa alla förslag och ta till mig så mycket feedback som möjligt. [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! + [*] Story mode däri byggnader kostar former + [*] Fler nivåer & och byggnader (exklusivt för den fristående versionen) + [*] Olika världar, och kanske världshinder + [*] Konfigurerbar världskapande (Ändra antal och storlek på resursfläckar, seed, med mera) + [*] Fler sorters former + [*] Fler prestandaförbättringar (Även om spelet redan spelar ganska väl!) + [*] Färgblint läge + [*] Och mycket mer! [/list] - Be sure to check out my trello board for the full roadmap! https://trello.com/b/ISQncpJP/shapezio + Se till att kolla min trello för en full framtidskarta! https://trello.com/b/ISQncpJP/shapezio global: - loading: Loading + loading: Laddar error: Error # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: "." # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: @@ -86,251 +86,251 @@ global: 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: för en sekund sedan + xSecondsAgo: för sekunder sedan + oneMinuteAgo: för en minut sedan + xMinutesAgo: för minuter sedan + oneHourAgo: för en timme sedan + xHoursAgo: för timmar sedan + oneDayAgo: för en dag sedan + xDaysAgo: för dagar sedan # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s - hoursAndMinutesShort: h s + hoursAndMinutesShort: t s - xMinutes: minutes + xMinutes: minuter keys: tab: TAB control: CTRL alt: ALT escape: ESC - shift: SHIFT - space: SPACE + shift: SKIFT + space: MELLANSLAG 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! + Skaffa den fristående versionen för att låsa upp alla funktioner! mainMenu: - play: Play + play: Spela changelog: Changelog - importSavegame: Import - openSourceHint: This game is open source! - discordLink: Official Discord Server - helpTranslate: Help translate! + importSavegame: Importera + openSourceHint: Detta spel är open source! + discordLink: Officiell Discord Server + helpTranslate: Hjälp till att översätta! # 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. + Förlåt, men det är känt att spelet spelar långsamt på din browser! Skaffa den fristående versionen eller ladda ner chrome för den fulla upplevelsen. - savegameLevel: Level - savegameLevelUnknown: Unknown Level + savegameLevel: Nivå + savegameLevelUnknown: Okänd Nivå contests: contest_01_03062020: - title: "Contest #01" - desc: Win $25 for the coolest base! + title: "Tävling #01" + desc: Vinn $25 för den coolaste fabriken! longDesc: >- - To give something back to you, I thought it would be cool to make weekly contests! + För att ge något åter till dig, tänkte jag att det skulle vara coolt att skapa veckovisa tävlingar!

- This weeks topic: Build the coolest base! + Denna veckas tema: Bygg den coolaste fabriken!

- Here's the deal:
+ Så här går det till:
    -
  • 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)
  • +
  • Skicka in en skärmdump av din fabrik till contest@shapez.io
  • +
  • Bonuspoäng om du delar den på sociala medier!
  • +
  • Jag kommer välja 5 skärmdumpar och framföra dem tilldiscordgruppen och låta dem rösta.
  • +
  • Vinnaren får $25 (Paypal, Amazon Gift Card, Vilket du än föredrar)
  • Deadline: 07.06.2020 12:00 AM CEST

- I'm looking forward to seeing your awesome creations! + Jag ser fram emot att se era grymma skapelser! - 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: Se + contestOver: Tävlingen är avslutad - Gå med i discordservern för att bli notifierad kring nya tävlingar! + continue: Fortsätt + newGame: Nytt spel + madeBy: Skapad av + subreddit: Reddit 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 + delete: Radera + cancel: Avbryt + later: Senare + restart: Starta om + reset: Återställ + getStandalone: Skaffa fristående + deleteGame: Jag vet vad jag måste göra + viewUpdate: Se uppdateringar + showUpgrades: Visa uppgraderingar + showKeybindings: Visa tangentbindingar importSavegameError: - title: Import Error + title: Importfel text: >- - Failed to import your savegame: + Kunde inte importera sparfil: importSavegameSuccess: - title: Savegame Imported + title: Sparfil importerad text: >- - Your savegame has been successfully imported. + Din sparfil har blivit importerad. gameLoadFailure: - title: Game is broken + title: Spel är brutet text: >- - Failed to load your savegame: + Kunde inte ladda sparfil: confirmSavegameDelete: - title: Confirm deletion + title: Bekräfta radering text: >- - Are you sure you want to delete the game? + Är du säker på att du vill radera spelet? savegameDeletionError: - title: Failed to delete + title: Kunde inte radera text: >- - Failed to delete the savegame: + Kunde inte radera sparfil: restartRequired: - title: Restart required + title: Omstart krävs text: >- - You need to restart the game to apply the settings. + Du behöver starta om spelet för att applicera inställningar. editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. + title: Ändra tangentbindningar + desc: Tryck ned tangenten eller musknappen du vill tillsätta, eller escape för att avbryta. resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. + title: Återställ tangentbindningar + desc: Detta kommer att återställa alla tangentbindningar till deras standardtangenter. Var snäll och bekräfta. keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! + title: Återställning av tangentbindningar + desc: Tangentbindningar har återställts! 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: Demoversion + desc: Du försökte nå en funktion () som inte är tillgänglig i demversionen. Överväg att skaffa den fristående versionen för den fulla upplevelsen! 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: Limiterad mängd sparfiler + desc: Du kan bara ha en sparfil åt gången i demoversionen. Var snäll och ta bort det existerande eller skaffa den fristående versionen! updateSummary: - title: New update! + title: Ny uppdatering! desc: >- - Here are the changes since you last played: + Här är ändringarna sen du sist spelade: upgradesIntroduction: - title: Unlock Upgrades + title: Lås upp Uppgraderingar 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. + Alla former du producerar kan användas för att låsa upp uppgraderingar - Förstör inte dina gamla fabriker! + Uppgraderingsmenyn kan finnas i det övre högra hörnet på skärmen. massDeleteConfirm: - title: Confirm delete + title: Bekräfta borttagning desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + Du tar nu bort ganska många byggnader ( för att vara exakt)! Är du säker på att du vill göra detta? blueprintsNotUnlocked: - title: Not unlocked yet + title: Inte än upplåst desc: >- - Blueprints have not been unlocked yet! Complete more levels to unlock them. + Ritningar är inte än upplåsta! Klara fler nivåer för att låsa upp dem. keybindingsIntroduction: - title: Useful keybindings + title: Användbara tangentbindningar 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.
+ Detta spel använder en stor mängd tangentbindningar som gör det lättare att bygga stora fabriker. + Här är några men se till att kolla in tangentbindningarna!

+ CTRL + Dra: Välj en yta att kopiera / radera.
+ SHIFT: Håll ned för att placera flera av samma byggnad.
+ ALT: Invertera orientationen av placerade rullband.
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: Ny Markör + desc: Ge den ett meningsfullt namn, du kan också inkludera en kort kod av en form (Vilket du kan generera här ) markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + desc: Du kan endast skapa två markörer i demoversionen. Skaffa den fristående versionen för ett oändligt antal! massCutConfirm: - title: Confirm cut + title: Bekräfta Klipp desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? + Du klipper en stor mängd byggnader ( för att vara exakt)! + Är du säker på att du vill göra detta? exportScreenshotWarning: - title: Export screenshot + title: Exportera skärmdump 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! + Du efterfrågade att exportera din fabrik som en skärmdump. + Var snäll och notera att detta kan ta ett tag för en stor bas och i vissa fall till och med krascha ditt spel 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 + moveMap: Flytta + selectBuildings: Välj yta + stopPlacement: Avsluta placering + rotateBuilding: Rotera byggnader + placeMultiple: Placera flera + reverseOrientation: Vänd orientation + disableAutoOrientation: Stäng av automatisk orientation toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create Marker - delete: Destroy - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + placeBuilding: Placera Byggnad + createMarker: Skapa Markör + delete: Förstör + pasteLastBlueprint: Klistra in ritning + lockBeltDirection: Sätt på rullbandsplannerare + plannerSwitchSide: Vänd planerarsidan + cutSelection: Klipp + copySelection: Kopiera + clearSelection: Rensa vald + pipette: Pipett # 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: Tryck ned För att cykla igenom varianter. # 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 + speed: Hastighet + range: Räckvidd + storage: Förvaring + oneItemPerSecond: 1 objekt / sekund + itemsPerSecond: objekt / s itemsPerSecondDouble: (x2) - tiles: tiles + tiles: plattor # 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: Nivå + completed: Avklarad + unlockText: Upplåst ! + buttonNextLevel: Nästa Nivå # 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. + newUpgrade: En ny uppgradering är tillgänglig! + gameSaved: Ditt spel har sparats. # The "Upgrades" window shop: - title: Upgrades - buttonUnlock: Upgrade + title: Upgraderingar + buttonUnlock: Upgradera # Gets replaced to e.g. "Tier IX" tier: Tier @@ -338,389 +338,435 @@ ingame: # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) + maximumLevel: MAXNIVÅ (Hastighet x) # The "Statistics" window statistics: - title: Statistics + title: Statistik dataSources: stored: - title: Stored - description: Displaying amount of stored shapes in your central building. + title: Förvarade + description: Visar mängd förvarade former i din centrala byggnad. produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + title: Producerade + description: Visar alla former din fabrik producerar, detta inkluderar mellanhandsprodukter. delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + title: Levererade + description: Visar former som levereras till din centrala byggnad. + noShapesProduced: Inga former har producerats än. # Displays the shapes per minute, e.g. '523 / m' shapesPerMinute: / m # Settings menu, when you press "ESC" settingsMenu: - playtime: Playtime + playtime: Speltid - buildingsPlaced: Buildings - beltsPlaced: Belts + buildingsPlaced: Byggnader + beltsPlaced: Rullband buttons: - continue: Continue - settings: Settings - menu: Return to menu + continue: Fortsätt + settings: Inställningar + menu: Återvänd till meny # Bottom left tutorial hints tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close + title: Behöver hjälp? + showHint: Visa tips + hideHint: Stäng # When placing a blueprint blueprintPlacer: - cost: Cost + cost: Kostnad # Map markers waypoints: - waypoints: Markers + waypoints: Markörer 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. + description: Vänsterklicka en markör för att hoppa till den, högerklicka för att ta bort den.

Tryck för att skapa en markör från nuvarande position, eller högerklicka för att skapa en markör vid vald plats. + creationSuccessNotification: Markör har skapats. # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: Placera en extraktor över en cirkel för att extrahera den! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + Koppla extraktorn med ettrullband till din hub!

Tips: Clicka och dra rullbandet med musen! 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. + Detta är INTE ett idle-spel! Bygg fler extraktörer för att klara målet snabbare.

Tips: Håll SHIFT för att placera flera extraktörer, och använd R för att rotera dem. + + colors: + red: Röd + green: Grön + blue: Blå + yellow: Gul + purple: Lila + cyan: Turkos + white: Vit + uncolored: Ofärgad + shapeViewer: + title: Lager + empty: Tom # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Rullband, Distributörer & Tunnlar + description: hastighet x → x miner: - name: Extraction - description: Speed x → x + name: Extraktion + description: Hastighet x → x processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: Klippning, Rotationg & Stapling + description: Hastighet x → x painting: - name: Mixing & Painting - description: Speed x → x + name: Blandning & Färgning + description: hastighet x → x # Buildings and their name / description buildings: belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. + name: &belt Rullband + description: Transporterar obejekt, håll in och dra för att placera flera. miner: # Internal name for the Extractor default: - name: &miner Extractor - description: Place over a shape or color to extract it. + name: &miner Extraktor + description: Placera över en form eller färg för att extrahera den. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. + name: Extraktor (kedja) + description: Placera över en form eller färg för att extrahera den. Kan kedjas. underground_belt: # Internal name for the Tunnel default: name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. + description: Låter dig tunnla under byggnader och rullband. tier2: name: Tunnel Tier II - description: Allows to tunnel resources under buildings and belts. + description: Låter dig tunnla resurser under byggnader och rullband. splitter: # Internal name for the Balancer default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. + name: &splitter balancer + description: Multifunktionell - Distribuerar alla inputs och outputs jämt. compact: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Sammanslagare (kompakt) + description: Slår ihop två rullband till ett. compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Sammanslagare (kompakt) + description: Slår ihop två rullband till ett. 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 Klippare + description: Klipper former från topp till botten och outputtar båda halver.Om du bara använder en halva, se till att förstöra den andra, annars kommer den uppehålla fabrkien! 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: Klippare (Quad) + description: Klipper former i fyra delar. Om du bara använder en del, se till att förstöra de andra, annars kommer de uppehålla fabrkien! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater Roterare + description: Roterar former 90 grader. ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. + name: Roterare (CCW) + description: Roterar former 90 motsols. 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 Staplare + description: Staplar båda obejekt. Om de inte kan slås ihop, placeras det högra obejektet över det vänstra. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. + name: &mixer Färgblandare + description: Blandar två färger genom additiv blandning. 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 Färgläggare + description: &painter_desc Färgar hela formen på den vänstra ingången med färgen från den högra. double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + name: Färgläggare (Dubbel) + description: Färgar formerna på de vänstra ingångarna med färgen från den högra. quad: - name: Painter (Quad) - description: Allows to color each quadrant of the shape with a different color. + name: Färgläggare (Quad) + description: Låter dig färglägga varje hörn av formen med olika färger. mirrored: name: *painter description: *painter_desc trash: default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. + name: &trash Skräphantering + description: Tar in former från alla sidor och förstör dem. För alltid. storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + name: Förvaring + description: Förvarar överskottliga objekt, till kapacitet. Kan användas som överflödsport. hub: - deliver: Deliver - toUnlock: to unlock + deliver: Leverera + toUnlock: Att låsa upp 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: Att klippa former + desc: Du låste just upp klipparen - den klipper former på hälften från topp till botten oavsett dess orientation!

Se till att ta bort allt överskott, annars kommer det att skapa uppehåll - Av denna anledning gav jag dig skräphantering, vilket förstör allt du inputtar! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + title: Rotation + desc: Roteraren har blivit upplåst! Den roterar former 90 grader medsols. reward_painter: - title: Painting + title: Måleri 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! + 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, there is a color blind mode in the settings! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + title: Färgblandning + desc: Färgblandaren har blivit upplåst - Kombinera två färger genom additiv färgblandning med denna byggnad! 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: Kombinera + desc: Du kan nu kombinera former medstaplaren! Båda inputs blir kombinerade och om de kan sättas brevid varandra kommer de att sättas ihop. Om inte kommer den högra staplas över den vänstra! 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: Delning/Sammanslagning + desc: Den multifunktiionella balanseraren har blivit upplåst - Den kan användas för att bygga större fabriker genom att dela eller slå ihop objekt till flera rullband!

reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now pipe items through belts and buildings with it! + desc: Tunneln blivit upplåst- Du kan nu transportera saker under rullband och byggnader med den! 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: Motsols rotation + desc: Du har låst upp en variant av roteraren - Den låter dig rotera saker motsols! För att bygga den, välj roteraren och tryck ned 'T' för att cykla genom dess varianter! 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: Kedjeextraktor + desc: Du har låst upp Kedjeextraktorn! Den kan föra sina resurser framåt till andra extraktorer så att du kan mer effektivt extrahera resurser! 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! + desc: Du har låst upp en ny variant av tunneln - Den har en större räckvidd, och du kan också mix-matcha tunnlarna nu! reward_splitter_compact: - title: Compact Balancer + title: Kompakt Balanserare desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + Du har låst upp en ny variant av balanseraren - Den accepterar två input och gör dem till en! 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: Quad Klippning + desc: Du har låst upp en ny variant av klipparen - Den låter dig klippa former i fyra delar istället för bara två! 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: Dubbelfärgläggning + desc: Du har låst upp en ny variant av Färgläggaren - Den fungerar som en vanlig färgläggare fast den färglägger två former åt gången och använder bara en färg istället för två! 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: Quad Färgläggning + desc: Du har låst upp en ny variant av Färgläggaren - Den tillåter dig att färglägga varje del av en form individuellt! 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: Förvaringsbuffert + desc: Du har låst upp en ny variant av skräphantering - Den tillåter dig att förvara objekt upp till en viss kapacitet! 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: Friläge + desc: Du gjorde det! Du låste upp friläge! Det betyder att former är nu slumpmässigt genererade! (oroa dig inte, mer innehåll är planerat för den fristående versionen!) 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: Ritningar + desc: Du kan nu kopiera och klistra in delar av din fabrik! Välj ett område (håll in CTRL, dra sedan med musen), och tryck 'C' för att kopiera det.

Att klistra in ärinte gratis, du behöver producera ritningsformer för att ha råd med det! (De du just levererade). # Special reward, which is shown when there is no reward actually no_reward: - title: Next level + title: Nästa nivå 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! + Denna nivå har ingen belöning, men nästa kommer!

PS: Se till att inte förstöra din redan existerande fabrik - Du behöver alla de där formerna igen för att låsa upp uppgraderingar! no_reward_freeplay: - title: Next level + title: Nästa nivå desc: >- - Congratulations! By the way, more content is planned for the standalone! + Grattis! Föresten, mer spelinnehåll är planerat för den fristående versionen! settings: - title: Settings + title: Inställningar categories: - game: Game - app: Application + game: Spelinställningar + app: Applikation versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built + dev: Utveckling + staging: Iscensättning + prod: Produktion + buildDate: Skapad labels: uiScale: - title: Interface scale + title: Gränssnittsskala 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. + Ändrar storleken på gränssnittet. gränssnittet kommer fortfarande baseras på skärmupplösning, men denna inställning kontrollerar mängdskala. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge + super_small: Superliten + small: Liten + regular: Normal + large: Stor + huge: Enorm scrollWheelSensitivity: - title: Zoom sensitivity + title: Zoomkänslighet description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + Ändrar hur känslig zoomen är (Mushjul eller styrplatta). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast + super_slow: Superlångsam + slow: Långsam + regular: Normal + fast: Snabb + super_fast: Supersnabb language: - title: Language + title: Språk description: >- - Change the language. All translations are user contributed and might be incomplete! + Ändra språk. Alla språk är användarbidragna och kan vara inkompletta! fullscreen: - title: Fullscreen + title: Fullskärm description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + Det är rekommenderat att spela i fullskärm för bästa upplevelse. Endast tillgänglig i den fristående versionen. soundsMuted: - title: Mute Sounds + title: Dämpa Ljud description: >- - If enabled, mutes all sound effects. + Om på, stänger av alla ljud. musicMuted: - title: Mute Music + title: Dämpa Musik description: >- - If enabled, mutes all music. + Om på, stänger av all musik. theme: - title: Game theme + title: Spelutseende description: >- - Choose the game theme (light / dark). + Välj spelutseende (ljust / mörkt). themes: - dark: Dark - light: Light + dark: Mörkt + light: Ljust refreshRate: - title: Simulation Target + title: Simulationsmål 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. + Om du har en 144hz skärm, ändra uppdateringshastigheten här så kommer spelet simulera vid en högre uppdateringshastighet. Detta kan dock sänka FPS om din dator är långsam. alwaysMultiplace: - title: Multiplace + title: Flerplacering description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + Om på, alla byggnader kommer fortsätta vara valda efter placering. Att ha detta på är som att konstant hålla ned SKIFT. offerHints: - title: Hints & Tutorials + title: Tips & 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. + Om tips och tutorials ska synas under spelets gång. Gömmer också vissa delar av UI tills senare i spelet för att göra det lättare att komma in i spelet. movementSpeed: - title: Movement speed - description: Changes how fast the view moves when using the keyboard. + title: Rörelsehastighet + description: Ändrar hur snabbt kameran förflyttar sig när du använder tangentbordet för att flytta kameran. speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast + super_slow: Superlångsamt + slow: Långsamt + regular: Normal + fast: Snabbt + super_fast: Supersnabbt + extremely_fast: Extremt snabbt enableTunnelSmartplace: - title: Smart Tunnels + title: Smarta Tunnlar description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + När på, att placera ut tunnlar kommer automatiskt ta bort onödiga rullband. + Detta låter dig också dra för att sätta ut tunnlar och onödiga tunnlar kommer att tas bort. vignette: - title: Vignette + title: Vinjett description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Sätter på vinjetten vilket gör skärmen mörkare i hörnen och + gör text lättare att läsa + + autosaveInterval: + title: Intervall för automatisk sparning + description: >- + Kontrollerar hur ofta spelet sparas atomatiskt. + Du kan också stäng av det helt. + intervals: + one_minute: 1 Minut + two_minutes: 2 Minuter + five_minutes: 5 Minuter + ten_minutes: 10 Minuter + twenty_minutes: 20 Minuter + disabled: Avstängd + compactBuildingInfo: + title: Kompakt byggnadsinfo + description: >- + Kortar ned infotexter för byggnader genom att endast visa dess storlek. + Annars visas en beskrivning och bild. + disableCutDeleteWarnings: + title: Stäng av klipp/raderingsvarningar + description: >- + Stänger av varningsdialogen som kommer upp då fler än 100 saker + ska tas bort + + enableColorBlindHelper: + title: Färgblint läge + description: Aktiverar olika verktyg som låter dig spela spelet om du är färbling. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. keybindings: - title: Keybindings + title: Tangentbindningar hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + Tips: Se till att använda CTRL, SKIFT, och ALT! De låter dig använda olika placeringslägen. - resetKeybindings: Reset Keyinbindings + resetKeybindings: Återställ Tangentbindningar categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + general: Applikation + ingame: Spelinställningar + navigation: Navigation + placement: Placering + massSelect: Massval + buildings: Snabbtangenter + placementModifiers: Placeringsmodifierare mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - centerMap: Center Map + confirm: Godkänn + back: Tillbaka + mapMoveUp: Gå Upp + mapMoveRight: Gå Höger + mapMoveDown: Gå Nedåt + mapMoveLeft: Gå Vänster + centerMap: Till mitten av världen - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: Zooma in + mapZoomOut: Zooma ut + createMarker: Skapa Markör - menuOpenShop: Upgrades - menuOpenStats: Statistics + menuOpenShop: Uppgraderingar + menuOpenStats: Statistik toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info + toggleFPSInfo: Toggle FPS och Debug info belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -732,57 +778,57 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement - rotateWhilePlacing: Rotate + rotateWhilePlacing: Rotera rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete - cycleBuildings: Cycle Buildings + Modifiering: Rotera motsols istället + cycleBuildingVariants: Cykla varianter + confirmMassDelete: Godkänn massborttagning + cycleBuildings: Cykla byggnader - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area + massSelectStart: Håll in och dra för att starta + massSelectSelectMultiple: Välj flera ytor + massSelectCopy: Kopiera yta - 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' + placementDisableAutoOrientation: Stäng av automatisk orientering + placeMultiple: Stanna kvar i placeringsläge + placeInverse: Invertera automatisk rullbandsorientering + pasteLastBlueprint: Klistra in ritning + massSelectCut: Klipp yta + exportScreenshot: Exportera hela fabriken som bild + mapMoveFaster: Flytta dig snabbare + lockBeltDirection: Sätt på rullbandsplanerare + switchDirectionLockSide: "Planerare: Byt sida" + pipette: Pipett about: - title: About this Game + title: Om detta spel body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Detta spel är open source och utvecklas av Tobias Springer (Det är jag).

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

+ Om du vill hjälpa, kolla in shapez.io på 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.

+ Musiken skapades av Peppsen - Han är grym!

- Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + Och sist men inte minst, tack till min bästa vän Niklas - Utan våra + factoriosessioner hade detta spel aldrig funnits. 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 + restoringGames: Återställer sparfiler + importingGames: Importerar sparfiler + oneGameLimit: Limiterad till endast en sparfil + customizeKeybindings: Finjustera tangentbindningar + exportingBase: Exportera hela fabriken som en bild - settingNotAvailable: Not available in the demo. + settingNotAvailable: Inte tillgänglig i demoversionen. diff --git a/translations/base-tr.yaml b/translations/base-tr.yaml index a2033f65..8084ee4a 100644 --- a/translations/base-tr.yaml +++ b/translations/base-tr.yaml @@ -156,6 +156,7 @@ mainMenu: continue: Continue newGame: New Game madeBy: Made by + subreddit: Reddit dialogs: buttons: @@ -287,6 +288,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) @@ -322,11 +327,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 @@ -398,6 +398,19 @@ ingame: 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. + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + uncolored: No color + shapeViewer: + title: Layers + empty: Empty + # All shop upgrades shopUpgrades: belt: @@ -518,7 +531,7 @@ storyRewards: 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! + 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, there is a color blind mode in the settings! reward_mixer: title: Color Mixing @@ -688,6 +701,39 @@ settings: Enables the vignette which darkens the screen corners and makes text easier to read. + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it + entirely here. + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a + description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disable the warning dialogs brought up when cutting/deleting more than 100 + entities. + + enableColorBlindHelper: + title: Color Blind Mode + description: Enables various tools which allow to play the game if you are color blind. + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: Keybindings hint: >- @@ -733,7 +779,6 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead @@ -753,7 +798,8 @@ keybindings: exportScreenshot: Export whole Base as Image mapMoveFaster: Move Faster lockBeltDirection: Enable belt planner - switchDirectionLockSide: 'Planner: Switch side' + switchDirectionLockSide: "Planner: Switch side" + pipette: Pipette about: title: About this Game diff --git a/translations/base-zh-CN.yaml b/translations/base-zh-CN.yaml index 4263f618..1e44992c 100644 --- a/translations/base-zh-CN.yaml +++ b/translations/base-zh-CN.yaml @@ -19,7 +19,7 @@ # the basic structure so the game also detects it. # -# Chinese translation dictionary. TODO: better names for the buildings. +# Chinese translation dictionary. TODO: better names for the buildings. # Standalone:独立版 # Demo:演示版 # Level:关/关卡 @@ -49,7 +49,7 @@ steamPage: # This is the short text appearing on the steam page 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) @@ -63,8 +63,8 @@ steamPage: 只对图形进行加工可能会使你感到无聊。我们为你准备了颜色资源——将红、绿、蓝三种颜色混合,生产更多不同的颜色并粉刷在图形上以满足需求。 - 这个游戏目前有18个关卡(这应该已经能让你忙碌几个小时了!),并且正在不断地更新中。很多新关卡已经在开发计划当中! - + 这个游戏目前有18个关卡(这应该已经能让你忙碌几个小时了!),并且正在不断地更新中。很多新关卡已经在开发计划当中! + [b]独立版优势[/b] @@ -92,18 +92,18 @@ steamPage: [*] 色盲模式 [*] 以及更多其他的功能! [/list] - + 记得查看我的Trello计划板!那里有所有的开发计划!https://trello.com/b/ISQncpJP/shapezio global: loading: 加载中 error: 错误 - # Chinese translation: There is typically no divider used for numbers. + # Chinese translation: There is typically no divider used for numbers. # How big numbers are rendered, e.g. "10,000" thousandsDivider: "" - # TODO: Chinese translation: suffix changes every 10000 in Chinese numbering system. + # 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 @@ -187,10 +187,11 @@ mainMenu: continue: 继续游戏 newGame: 新游戏 madeBy: 作者: + subreddit: Reddit dialogs: buttons: - ok: 确认 # 好 完成 + ok: 确认 # 好 完成 delete: 删除 # Delete cancel: 取消 # Cancel later: 以后 # Later @@ -239,15 +240,15 @@ dialogs: resetKeybindingsConfirmation: title: 重置所有按键 desc: 你将要重置所有按键,请确认。 - + keybindingsResetOk: title: 重置所有按键 desc: 成功重置所有按键! - + featureRestriction: title: 演示版 desc: 你尝试使用了 功能。该功能在演示版中不可用。请考虑购买独立版以获得更好的体验。 - + oneSavegameLimit: title: 存档数量限制 desc: 演示版中只能保存一份存档。 请删除旧存档或者获取独立版! @@ -256,7 +257,6 @@ dialogs: title: 更新啦! desc: >- 以下为自上次游戏以来更新的内容: - upgradesIntroduction: title: 解锁建筑升级 @@ -284,12 +284,6 @@ dialogs: 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: 创建地图标记 @@ -325,6 +319,10 @@ ingame: pasteLastBlueprint: 粘贴上一个蓝图 lockBeltDirection: 启用传送带规划 plannerSwitchSide: 规划器换边 + cutSelection: 剪切 + copySelection: 复制 + clearSelection: 取消选择 + pipette: 选取器 # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -360,11 +358,6 @@ ingame: newUpgrade: 有新更新啦! gameSaved: 游戏已保存。 - # Mass select information, this is when you hold CTRL and then drag with your mouse - # to select multiple buildings - massSelect: - infoText: 剪切,复制,删除,取消. - # The "Upgrades" window shop: title: 建筑升级 @@ -384,20 +377,19 @@ ingame: title: 统计信息 dataSources: stored: - title: 储存 - description: 显示基地中每种图形储存的数量。 + title: 已交付 + description: 显示基地中每种图形已交付且未使用的数量。 produced: title: 生产 description: 显示所有正在被生产的图形数量,包括中间产物。 delivered: title: 送达 - description: 显示图形送达基地的速度。 + description: 显示图形送达基地并交付的速度。 noShapesProduced: 你还没有生产任何图形。 # Displays the shapes per minute, e.g. '523 / m' shapesPerMinute: 个/分钟 - # Settings menu, when you press "ESC" settingsMenu: playtime: 游戏时间 @@ -424,7 +416,7 @@ ingame: waypoints: waypoints: 地图标记 hub: 基地 - description: 左键快速跳转到地图标记,右键删除地图标记。

从当前视图中创建地图标记,或者在选定的位置上使用右键创建地图标记。 + description: 左键跳转到地图标记,右键删除地图标记。

在当前地点创建地图标记,或者在选定位置上右键创建地图标记. creationSuccessNotification: 成功创建地图标记。 # Interactive tutorial @@ -439,6 +431,19 @@ ingame: 这不是一个挂机游戏!建造更多的开采机和传送带来更快地完成目标。

提示:按住SHIFT键来放置多个开采机,用R键旋转它们。 + colors: + red: 红色 + green: 绿色 + blue: 蓝色 + yellow: 黄色 + purple: 紫色 + cyan: 青色 + white: 白色 + uncolored: 无色 + shapeViewer: + title: 层 # TODO: find better translation + empty: 空 + # All shop upgrades shopUpgrades: belt: @@ -497,7 +502,7 @@ buildings: name: &cutter 切割机 description: 将图形从上到下切开并输出。 如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! quad: - name: 切割机(四分) + name: 切割机(四向) description: 将输入的图形切成四块。 如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! rotater: @@ -549,73 +554,72 @@ storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: title: 切割图形 - desc: 切割机已解锁。不论切割机的方向,它都会把图形从上到下切成两半。

记得把不需要的部分处理掉,否则这个这个建筑会停止工作。为此我给你准备了垃圾桶,它会把所有放进去的物品销毁掉。 + desc: 恭喜!你解锁了切割机。切割机会把图形从上到下切成两半。注意切割的方向和切割机的朝向无关。

记得把不需要的部分处理掉,否则这个这个建筑会停止工作。为此我给你准备了垃圾桶,它会把所有放进去的物品销毁掉。 reward_rotater: title: 顺时针旋转 - desc: 旋转机已解锁。它会顺时针旋转输入的图形90度。 + desc: 恭喜!你解锁了旋转机。它会顺时针旋转输入的图形90度。 reward_painter: title: 上色 desc: >- - 上色机已解锁。和图形一样,从颜色矿脉中开采颜色,然后将在上色机中将颜色涂在图形上。

PS:我们正在开发色盲模式! + 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, there is a color blind mode in the settings! reward_mixer: title: 混合颜色 - desc: 混色机已解锁。在这个建筑中将两个颜色混合在一起(加法混合)。 + desc: The mixer has been unlocked - Combine two colors using additive blending with this building! reward_stacker: title: 堆叠 - desc: 堆叠机已解锁。堆叠机会尝试把两个输入的图形拼贴在一起。如果有重叠的部分,右边的输入会被堆叠在左边的输入上方! + desc: 恭喜!你解锁了堆叠机。堆叠机会尝试把两个输入的图形拼贴在一起。如果有重叠的部分,右边的输入会被堆叠在左边的输入上方! reward_splitter: title: 分离与合并 - desc: 平衡机已解锁。在大型工厂中,平衡机负责合并或分离多个传送带上的物品。

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

reward_tunnel: title: 隧道 - desc: 隧道已解锁。你现在可以从其他传送带或建筑底下运送物品了! + desc: 恭喜!你解锁了隧道。你现在可以从其他传送带或建筑底下运送物品了! reward_rotater_ccw: title: 逆时针旋转 - desc: 旋转机逆时针变体已解锁。这个变体可以逆时针旋转图形。选择旋转机然后按“T”键来选取这个变体。 + desc: 恭喜!你解锁了旋转机逆时针变体。这个变体可以逆时针旋转图形。选择旋转机然后按“T”键来选取这个变体。 reward_miner_chainable: title: 链式开采机 - desc: 链式开采机变体已解锁。它是开采机的一个变体。它可以将开采出来的资源传递给其他的开采机,使得资源提取更加高效! + 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: 二级隧道 - desc: 二级隧道变体已解锁。这个隧道有更长的传输距离。你还可以混用不同的隧道变体! + desc: 恭喜!你解锁了二级隧道。这是隧道的一个变体。二级隧道有更长的传输距离。你还可以混用不同的隧道变体! reward_splitter_compact: title: 小型合流机 - desc: >- - 小型合流机变体已解锁。它可以把两个输入合并到一个输出上。 + desc: You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! reward_cutter_quad: - title: 四分切割机 - desc: 切割机四分变体已解锁。它可以将输入的图形切成四块而不只是左右两块。 + title: 四向切割机 + desc: 恭喜!你解锁了切割机四向变体。它可以将输入的图形切成四块而不只是左右两块! reward_painter_double: title: 双倍上色机 - desc: 上色机双倍变体已解锁。 它像普通上色机一样为图形上色,只是它可以同时为两个图形上色,每次只消耗一份颜色! + desc: 恭喜!你解锁了上色机双倍变体。它可以同时为两个图形上色,每次只消耗一份颜色! reward_painter_quad: title: 四向上色机 - desc: 上色机四向变体已解锁。它可以在一个图形的四个角上涂不同的颜色! + desc: 恭喜!你解锁了上色机四向变体。它可以在一个图形的四个角上涂不同的颜色! reward_storage: title: 仓库 - desc: 仓库变体已解锁。它可以暂时储存一些材料,有容量上限。 + desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! reward_freeplay: title: 自由模式 - desc: 恭喜你!你解锁了自由模式!现在图形将会是随机生成的!(不用担心,我计划在独立版本中加入更多内容!) + desc: 恭喜你!你解锁了自由模式。现在图形将会是随机生成的!(不用担心,我计划在独立版本中加入更多内容!) reward_blueprints: title: 蓝图 - desc: 你现在可以复制粘贴你的工厂的一部分了!按住CTRL键并拖动鼠标来选择一块区域,然后按C键复制。

粘贴并不是免费的,你需要使用蓝图图形来粘贴你的蓝图。蓝图图形是你刚刚交付的图形。 + desc: 你现在可以复制粘贴你的工厂的一部分了!按住CTRL键并拖动鼠标来选择一块区域,然后按C键复制。

粘贴并不是免费的,你需要使用蓝图图形来粘贴你的蓝图。蓝图图形是你刚刚交付的图形。 # Special reward, which is shown when there is no reward actually no_reward: @@ -702,7 +706,7 @@ settings: alwaysMultiplace: title: 多重放置 description: >- - 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下SHIFT键。 + 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下SHIFT键。 # description: >- # If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. @@ -734,10 +738,40 @@ settings: description: >- 启用晕映,将屏幕角落里的颜色变深,更容易阅读文本。 + autosaveInterval: + title: 自动保存间隔 + description: >- + 在这里控制你的游戏多长时间保存一次,或者完全关闭这个功能。 + intervals: + one_minute: 1分钟 + two_minutes: 2分钟 + five_minutes: 5分钟 + ten_minutes: 10分钟 + twenty_minutes: 20分钟 + disabled: 关闭 + compactBuildingInfo: + title: 精简建筑信息 + description: >- + 缩小建筑信息展示框。如果打开,放置建筑时建筑将不再显示建筑说明和图片,只显示建筑速度或其他数据。 + disableCutDeleteWarnings: + title: 关闭剪切/删除警告 + description: >- + 如果打开,将不再在剪切或者删除100+建筑时显示警告信息。 + + enableColorBlindHelper: + title: 色盲模式 + description: 提供一些分辨颜色的工具。目前当鼠标移至颜色资源上方时,屏幕上方会显示颜色名称。 + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. + keybindings: title: 按键设置 hint: >- - 提示:使用CTRL、SHIFT、ALT! 这些建在放置建筑时有不同的效果。 + 提示:使用CTRL、SHIFT、ALT! 这些建在放置建筑时有不同的效果。 # hint: >- # Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. @@ -788,15 +822,12 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: 取消放置 rotateWhilePlacing: 顺时针旋转 rotateInverseModifier: >- 修饰键: 改为逆时针旋转 cycleBuildingVariants: 选择建筑变体 - # cycleBuildingVariants: Cycle Variants confirmMassDelete: 确认批量删除 cycleBuildings: 选择建筑 - # cycleBuildings: Cycle Buildings massSelectStart: 开始批量选择 massSelectSelectMultiple: 选择多个区域 massSelectCopy: 复制 @@ -810,7 +841,8 @@ keybindings: mapMoveFaster: 快速移动 lockBeltDirection: 启用传送带规划 - switchDirectionLockSide: '规划器:换边' + switchDirectionLockSide: "规划器:换边" + pipette: 选取器 about: title: 关于游戏 @@ -830,6 +862,7 @@ about: 最后,我想感谢我最好的朋友Niklas——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 + changelog: title: 版本日志 @@ -842,7 +875,3 @@ demo: # customizeKeybindings: Customizing Keybindings exportingBase: 导出工厂截图 settingNotAvailable: 在演示版中不可用。 - - - - diff --git a/translations/base-zh-TW.yaml b/translations/base-zh-TW.yaml index 8ce591dd..973312d0 100644 --- a/translations/base-zh-TW.yaml +++ b/translations/base-zh-TW.yaml @@ -19,9 +19,36 @@ # the basic structure so the game also detects it. # +# Chinese (traditional) 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: @@ -30,77 +57,78 @@ 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: 錯誤 # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: " " # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: - thousands: k - millions: M - billions: B - trillions: T + thousands: 千 + millions: 百萬 + billions: 十億 + trillions: 兆 # 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,224 +136,222 @@ 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 + savegameLevelUnknown: 未知關卡 contests: contest_01_03062020: - title: "Contest #01" - desc: Win $25 for the coolest base! + title: "比賽 #01" + desc: 最屌的工廠將能贏得25美元的獎金! 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! + 為了回饋您,我認為每週進行比賽也很酷! +

+ 本週主題:建立最酷的基地! +

+ 這是交易:
+
    +
  • 將您的基地的屏幕截圖提交到 contest@shapez.io +
  • 如果您在社交媒體上分享會有額外獎勵積分! +
  • 我將選擇5張屏幕截圖,並將其提交給 discord 社區進行投票。 +
  • 獲勝者將獲得 $ 25 (貝寶paypal,亞馬遜禮品卡,隨您喜歡) +
  • 截止日期:CEST 07.06.2020 12:00 AM + +
    + 我期待看到您的出色創作! - 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以收到關於新競賽的提醒! + continue: 繼續 + newGame: 新遊戲 + madeBy: 作者: + subreddit: Reddit 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: 删除 + cancel: 取消 + 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. +
    你生產過的所有圖形都會被用來升級建築。升級菜單在屏幕右上角。 + 不要銷毀你之前建造的工廠! 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: 反向放置傳送帶。
    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: 規劃器換邊 + cutSelection: 剪下選項 + copySelection: 複製選項 + clearSelection: 清空選項 + pipette: 吸附 # 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 + completed: 完成 + unlockText: 解鎖! + buttonNextLevel: 下一關 # 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. + newUpgrade: 有新的更新啦! + gameSaved: 遊戲已保存。 # The "Upgrades" window shop: @@ -333,394 +359,446 @@ ingame: buttonUnlock: Upgrade # 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鍵旋轉它們。 + + colors: + red: 紅 + green: 綠 + blue: 藍 + yellow: 黃 + purple: 紫 + cyan: 淺藍 + white: 白 + uncolored: 無顏色 + shapeViewer: + title: 層 + empty: 空 # 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! + 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, there is a color blind mode in the settings! 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: 貳級隧道變體已解鎖。這個隧道有更長的傳輸距離。你還可以混用不同的隧道變體(點與點最長距離為7)! 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. + 啟用暈映,將屏幕角落裡的顏色變深,更容易閱讀文本。 + autosaveInterval: + title: 自動刷新時間 + description: >- + 控制遊戲自動刷新的頻率。 您也可以禁用它。 + intervals: + one_minute: 1分鐘 + two_minutes: 2分鐘 + five_minutes: 5分鐘 + ten_minutes: 10分鐘 + twenty_minutes: 20分鐘 + disabled: 禁用 + compactBuildingInfo: + title: 省略建築信息 + description: >- + 通過顯示建築物的比率來縮短建築物的信息框。 否則 + 顯示所有說明+圖像。 + disableCutDeleteWarnings: + title: 禁用剪下/刪除的警告 + description: >- + 剪下/刪除超過100幢建築物時禁用警告。 + + enableColorBlindHelper: + title: 色盲模式 + description: 如果您是色盲者,啟用了這設定,就可以玩遊戲了。 + + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. + This may be more comfortable if you frequently switch between placing + different building types. keybindings: - title: Keybindings + title: 按鍵設置 hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + 提示:使用CTRL、SHIFT、ALT! 這些建在放置建築時有不同的效果。 - 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: 回到基地 - 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 +810,56 @@ keybindings: painter: *painter trash: *trash - abortBuildingPlacement: Abort Placement - rotateWhilePlacing: Rotate + rotateWhilePlacing: 順時針旋轉 rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete - cycleBuildings: Cycle Buildings + 修飾鍵: 改為逆時針旋轉 + cycleBuildingVariants: 選擇建築變體 + confirmMassDelete: 確認批量刪除 + cycleBuildings: 選擇建築 + 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: "規劃器:換邊" + pipette: Pipette 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.

    + 本遊戲的音樂由Peppsen製作——他是個很棒的伙伴。

    - Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + 最後,我想感謝我最好的朋友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 - - settingNotAvailable: Not available in the demo. + restoringGames: 恢復存檔 #中? + importingGames: 倒入存檔 #中? + oneGameLimit: 最多一個存檔 + customizeKeybindings: 按鍵設置 + # customizeKeybindings: Customizing Keybindings + exportingBase: 導出工廠截圖 + settingNotAvailable: 在演示版中不可用。 diff --git a/version b/version index b01de297..b0c8928e 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.1.16 \ No newline at end of file +1.1.18 \ No newline at end of file